Spring Boot集成RocketMQ实现普通、延时、事务消息发送接收、PULL消费模式及开启ACL | Spring Cloud 30

一、前言

在前面我们通过以下章节对RocketMQ有了基础的了解:

docker-compose 搭建RocketMQ 5.1.0 集群(双主双从模式) | Spring Cloud 28

docker-compose 搭建RocketMQ 5.1.0 集群开启ACL权限控制 | Spring Cloud 29

现在开始我们正式学习Spring Boot中集成RocketMQ使用,,在本章节主要进行对以下部分讲解说明:

  • 普通消息的发送接收
  • 延时消息的发送接收
  • 事务消息的发送接收
  • 发送端和接收端开启ACL
  • PULL模式消费及@ExtRocketMQConsumerConfiguration使用

二、项目集成RocketMQ

2.1 项目总体结构

在这里插入图片描述

2.2 引入依赖

rocketmq/pom.xml

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.2.3</version>
</dependency>

2.3 配置文件

rocketmq/src/main/resources/application.yml

server:
  port: 8888

spring:
  application:
    name: @artifactId@

rocketmq:
  name-server: 192.168.0.30:9876
  producer:
    group: @artifactId@-group
    send-message-timeout: 60000  # 发送消息超时时间,单位:毫秒。默认为 3000
    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次
    retry-times-when-send-async-failed: 2 # 异步发送消息时,失败重试次数。默认为 2 次
    retry-next-server: false # 发送消息给 Broker 时,如果发送失败,是否重试另外一台 Broker 默认为 false
    access-key: RocketMQAdmin # Access Key
    secret-key: 1qaz@WSX # Secret Key
    enable-msg-trace: true # 是否开启消息轨迹功能,默认为 true 开启
    customized-trace-topic: RMQ_SYS_TRACE_TOPIC # 自定义消息轨迹的 Topic,默认为 RMQ_SYS_TRACE_TOPIC
  consumer:
    access-key: RocketMQAdmin # Access Key
    secret-key: 1qaz@WSX # Secret Key

logging:
  level:
    org:
      springframework:
        boot:
          autoconfigure:
            logging: info

2.4主题及消费组常量

com/gm/rocketmq/component/rocketmq/TopicConstants.java

package com.gm.rocketmq.component.rocketmq;

/**
 * 主题常量
 */
public interface TopicConstants {

    String NORMAL_ROCKETMQ_TOPIC_TEST= "NORMAL_ROCKETMQ_TOPIC_TEST";

    String ORDERLY_ROCKETMQ_TOPIC_TEST= "ORDERLY_ROCKETMQ_TOPIC_TEST";

    String SCHEDULE_ROCKETMQ_TOPIC_TEST= "SCHEDULE_ROCKETMQ_TOPIC_TEST";

    String TRANSACTION_ROCKETMQ_TOPIC_TEST= "TRANSACTION_ROCKETMQ_TOPIC_TEST";

    String PULL_ROCKETMQ_TOPIC_TEST= "PULL_ROCKETMQ_TOPIC_TEST";

    String EXT_ROCKETMQ_TOPIC_TEST= "EXT_ROCKETMQ_TOPIC_TEST";

    String CONSUMER_GROUP = "_CONSUMER_GROUP";
}

三、各类型消息收发

3.1 普通消息

3.1.1 普通消息发送

     @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 向rocketmq发送同步和异步消息
     */
    @RequestMapping(value = "sendNormal", method = RequestMethod.GET)
    public String sendNormal() {
        rocketMQTemplate.send(TopicConstants.NORMAL_ROCKETMQ_TOPIC_TEST + ":sync", MessageBuilder.withPayload("同步发送消息").build());
        rocketMQTemplate.asyncSend(TopicConstants.NORMAL_ROCKETMQ_TOPIC_TEST + ":async", MessageBuilder.withPayload("异步发送消息").build(), new SendCallback() {

            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("异步发送成功:{}", sendResult.getSendStatus().name());
            }

            @Override
            public void onException(Throwable throwable) {
                log.info("异步发送失败:{}", throwable.getMessage());
            }
        });
        return "OK";
    }

3.1.2 普通消息接收

com/gm/rocketmq/component/rocketmq/NormalRocketMqListener.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RocketMQMessageListener(topic = TopicConstants.NORMAL_ROCKETMQ_TOPIC_TEST, consumerGroup = TopicConstants.NORMAL_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP, accessKey = "${rocketmq.consumer.access-key}", secretKey = "${rocketmq.consumer.secret-key}")
public class NormalRocketMqListener implements RocketMQListener<String> {
    @Override
    public void onMessage(String s) {
        log.info("普通订阅-接收到的信息:{}", s);
    }
}

@RocketMQMessageListener注解参数说明:

  • consumerGroup:消费者订阅组,它是必需的,并且必须是唯一的。
  • topic:主题名字,生产发送的主题名。
  • consumeMode:消费模式,可选择并发或有序接收消息;默认CONCURRENTLY同时接收异步传递的消息。
  • messageModel:消息模式,默认CLUSTERING集群消费;如果希望所有订阅者都接收消息,可以设置广播BROADCASTING
  • consumeThreadMax:消费者最大线程数,默认64
  • consumeTimeout:消息阻塞最长时间,默认15分钟。
  • nameServer:服务器地址,默认读取配置文件地址,可以单独为消费者设置指定位置。
  • selectorExpression:消费指定的Tag标签的业务消息。
  • ConsumerACL 功能需要在 @RocketMQMessageListener 中进行配置
  • ProducerACL 功能需要在配置文件中进行配置
  • 更多查看官方解释

3.2 顺序消息

3.2.1 顺序消息发送

    /**
     * 向rockertmq发送顺序消息,同步方式
     *
     * @return
     */
    @RequestMapping(value = "sendOrderlySync", method = RequestMethod.GET)
    public String sendOrderlySync() {
        // 订单列表
        List<OrderStep> orderList = buildOrders();
        for (int i = 0; i < 10; i++) {
            Message msg = MessageBuilder.withPayload(orderList.get(i).toString()).build();
            String orderId = String.valueOf(orderList.get(i).getOrderId());
            rocketMQTemplate.sendOneWayOrderly(TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST + ":sync", msg, orderId);
        }
        return "OK";
    }

    /**
     * rockertmq发送顺序消息,异步方式
     *
     * @return
     */
    @RequestMapping(value = "sendOrderlyAsync", method = RequestMethod.GET)
    public String sendOrderlyAsync() {
        // 订单列表
        List<OrderStep> orderList = buildOrders();
        for (int i = 0; i < 10; i++) {
            Message msg = MessageBuilder.withPayload(orderList.get(i).toString()).build();
            String orderId = String.valueOf(orderList.get(i).getOrderId());
            rocketMQTemplate.syncSendOrderly(TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST + ":async", msg, orderId);
        }
        return "OK";
    }
    
   /**
     * 订单的步骤
     */
    private static class OrderStep {
        private long orderId;
        private String desc;

        public long getOrderId() {
            return orderId;
        }

        public void setOrderId(long orderId) {
            this.orderId = orderId;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "OrderStep{" + "orderId=" + orderId + ", desc='" + desc + '\'' + '}';
        }
    }

    /**
     * 生成模拟订单数据
     */
    private List<OrderStep> buildOrders() {
        List<OrderStep> orderList = new ArrayList<OrderStep>();

        OrderStep orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111039L);
        orderDemo.setDesc("创建");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111065L);
        orderDemo.setDesc("创建");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111039L);
        orderDemo.setDesc("付款");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103117235L);
        orderDemo.setDesc("创建");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111065L);
        orderDemo.setDesc("付款");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103117235L);
        orderDemo.setDesc("付款");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111065L);
        orderDemo.setDesc("完成");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111039L);
        orderDemo.setDesc("推送");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103117235L);
        orderDemo.setDesc("完成");
        orderList.add(orderDemo);

        orderDemo = new OrderStep();
        orderDemo.setOrderId(15103111039L);
        orderDemo.setDesc("完成");
        orderList.add(orderDemo);

        return orderList;
    }

3.2.1 顺序消息接收

com/gm/rocketmq/component/rocketmq/OrderlyRocketMqListenerA.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RocketMQMessageListener(topic = TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST,
        consumerGroup = TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP,
        accessKey = "${rocketmq.consumer.access-key}", secretKey = "${rocketmq.consumer.secret-key}",
        consumeMode = ConsumeMode.ORDERLY)
public class OrderlyRocketMqListenerA implements RocketMQListener<String> {
    @Override
    public void onMessage(String s) {
        log.info("顺序订阅-接收到的信息:{}", s);
    }
}

com/gm/rocketmq/component/rocketmq/OrderlyRocketMqListenerB.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RocketMQMessageListener(topic = TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST,
        consumerGroup = TopicConstants.ORDERLY_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP,
        accessKey = "${rocketmq.consumer.access-key}", secretKey = "${rocketmq.consumer.secret-key}",
        consumeMode = ConsumeMode.ORDERLY)
public class OrderlyRocketMqListenerB implements RocketMQListener<String> {
    @Override
    public void onMessage(String s) {
        log.info("顺序订阅-接收到的信息:{}", s);
    }
}

3.3 延时消息

3.3.1 延时消息发送

    /**
     * rockertmq发送延时消息
     *
     * @return
     */
    @RequestMapping(value = "sendSchedule", method = RequestMethod.GET)
    public String sendSchedule() {
        Message msg = MessageBuilder.withPayload("延时消息")
                .build();
        rocketMQTemplate.syncSendDelayTimeSeconds(TopicConstants.SCHEDULE_ROCKETMQ_TOPIC_TEST + ":", msg, 20);
        log.info("延时消息-发布时间:{}", System.currentTimeMillis());
        return "OK";
    }

3.3.2 延时消息接收

com/gm/rocketmq/component/rocketmq/ScheduleRocketMqListener.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RocketMQMessageListener(topic = TopicConstants.SCHEDULE_ROCKETMQ_TOPIC_TEST,
        consumerGroup = TopicConstants.SCHEDULE_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP,
        accessKey = "${rocketmq.consumer.access-key}", secretKey = "${rocketmq.consumer.secret-key}")
public class ScheduleRocketMqListener implements RocketMQListener<MessageExt> {
    @Override
    public void onMessage(MessageExt message) {
        String msg = "内容:" + new String(message.getBody()) + ",时间:" + (System.currentTimeMillis() - message.getBornTimestamp()) + "ms later";
        log.info("延时订阅-接收到的信息:{}", msg);
        log.info("延时消息-接受时间:{}", System.currentTimeMillis());
    }
}

3.4 发送端事务消息

3.4.1 事务消息发送

    /**
     * rockertmq发送生产端事务消息
     *
     * @return
     */
    @RequestMapping(value = "sendTransaction", method = RequestMethod.GET)
    public String sendTransaction() {
        Message msg = MessageBuilder.withPayload("事务消息")
                .build();
        TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction(TopicConstants.TRANSACTION_ROCKETMQ_TOPIC_TEST + ":", msg, "自定义参数");
        log.info("事务消息-发布结果:{} = {}", result.getTransactionId(), result.getSendStatus());
        return "OK";
    }

com/gm/rocketmq/component/rocketmq/TransactionListenerImpl.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.messaging.Message;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@RocketMQTransactionListener
class TransactionListenerImpl implements RocketMQLocalTransactionListener {
    private AtomicInteger transactionIndex = new AtomicInteger(0);
    private ConcurrentHashMap<String, Integer> localTrans = new ConcurrentHashMap<>();

    // 事务消息共有三种状态,提交状态、回滚状态、中间状态:

    // RocketMQLocalTransactionState.COMMIT: 提交事务,它允许消费者消费此消息。
    // RocketMQLocalTransactionState.ROLLBACK: 回滚事务,它代表该消息将被删除,不允许被消费。
    // RocketMQLocalTransactionState.UNKNOWN: 中间状态,它代表需要检查消息队列来确定状态。

    // executeLocalTransaction 方法来执行本地事务
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        String transactionId = msg.getHeaders().get("__transactionId__").toString();
        log.info("执行本地事务,transactionId:{}", transactionId);

        int value = transactionIndex.getAndIncrement();
        int status = value % 3;
        localTrans.put(transactionId, status);
        log.info("获取自定义参数:{}", arg);
        return RocketMQLocalTransactionState.UNKNOWN;
    }

    // checkLocalTransaction 方法用于检查本地事务状态,并回应消息队列的检查请求
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        String transactionId = msg.getHeaders().get("__transactionId__").toString();
        log.info("检查本地事务状态,transactionId:{}", transactionId);
        Integer status = localTrans.get(transactionId);
        if (null != status) {
            switch (status) {
                case 0:
                    return RocketMQLocalTransactionState.UNKNOWN;
                case 1:
                    return RocketMQLocalTransactionState.COMMIT;
                case 2:
                    return RocketMQLocalTransactionState.ROLLBACK;
            }
        }
        return RocketMQLocalTransactionState.COMMIT;
    }
}

3.5 Pull模式消费

3.5.1 源码分析

rocketmq-spring-boot-starter中关于Pull模式消费的自动配置,
org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration

在这里插入图片描述
其中rocketmq.name-serverrocketmq.pull-consumer.grouprocketmq.pull-consumer.topic三项配置为必填项。

剩余其他配置,org.apache.rocketmq.spring.autoconfigure.RocketMQProperties.PullConsumer

在这里插入图片描述

由上可知,利用rocketmq-spring-boot-starter实现PULL模式,只支持单TopicPULL消费,要想对多个Topic进行PULL模式消费需要用到@ExtRocketMQConsumerConfiguration

3.5.2 PULL消费所需配置文件

配置文件新增pull-consumer相关配置,完整rocketmq/src/main/resources/application.yml

rocketmq:
  name-server: 192.168.0.30:9876
  producer:
    group: @artifactId@-group
    send-message-timeout: 60000  # 发送消息超时时间,单位:毫秒。默认为 3000
    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次
    retry-times-when-send-async-failed: 2 # 异步发送消息时,失败重试次数。默认为 2 次
    retry-next-server: false # 发送消息给 Broker 时,如果发送失败,是否重试另外一台 Broker 默认为 false
    access-key: RocketMQAdmin # Access Key
    secret-key: 1qaz@WSX # Secret Key
    enable-msg-trace: true # 是否开启消息轨迹功能,默认为 true 开启
    customized-trace-topic: RMQ_SYS_TRACE_TOPIC # 自定义消息轨迹的 Topic,默认为 RMQ_SYS_TRACE_TOPIC
  consumer:
    access-key: RocketMQAdmin # Access Key
    secret-key: 1qaz@WSX # Secret Key
  pull-consumer:
    access-key: RocketMQAdmin # Access Key
    secret-key: 1qaz@WSX # Secret Key
    topic: PULL_ROCKETMQ_TOPIC_TEST
    group: PULL_ROCKETMQ_TOPIC_TEST_CONSUMER_GROUP

3.5.3 消息发送

    /**
     * 向ockertmq 消费端pull模式发生消息
     *
     * @return
     */
    @RequestMapping(value = "sendPull", method = RequestMethod.GET)
    public String pull() {
        for (int i = 0; i < 10; i++) {
            Message msg = MessageBuilder.withPayload("pull 消息" + i).build();
            rocketMQTemplate.syncSend(TopicConstants.PULL_ROCKETMQ_TOPIC_TEST + ":", msg);
        }
        for (int i = 0; i < 10; i++) {
            Message msg = MessageBuilder.withPayload("pull ext 消息" + i).build();
            rocketMQTemplate.syncSend(TopicConstants.EXT_ROCKETMQ_TOPIC_TEST + ":", msg);
        }
        return "OK";
    }

3.5.4 @ExtRocketMQConsumerConfiguration使用

此示例利用@ExtRocketMQConsumerConfiguration定义消费,声明消费的Topic和消费组,或声明不同name-server

利用@ExtRocketMQTemplateConfiguration定义生产者,声明不同name-server或者其他特定的属性来定义非标的RocketMQTemplate

com/gm/rocketmq/component/rocketmq/ExtRocketMQTemplate.java

import org.apache.rocketmq.spring.annotation.ExtRocketMQConsumerConfiguration;
import org.apache.rocketmq.spring.core.RocketMQTemplate;

/**
 * 可用于不同name-server或者其他特定的属性来定义非标的RocketMQTemplate,此示例定义消息Topic和消费者
 */
@ExtRocketMQConsumerConfiguration(group = TopicConstants.EXT_ROCKETMQ_TOPIC_TEST + TopicConstants.CONSUMER_GROUP,
        topic = TopicConstants.EXT_ROCKETMQ_TOPIC_TEST)
public class ExtRocketMQTemplate extends RocketMQTemplate {
}

3.5.5 PULL模式消息接收

com/gm/rocketmq/component/rocketmq/PullConsumer.java

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;

@Slf4j
@Component
public class PullConsumer implements CommandLineRunner {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private ExtRocketMQTemplate extRocketMQTemplate;

    @Override
    public void run(String... args) {
        while (true) {

            List<String> messages = rocketMQTemplate.receive(String.class, 5000);
            log.info("receive from rocketMQTemplate, messages={}", messages);


            messages = extRocketMQTemplate.receive(String.class, 5000);
            log.info("receive from extRocketMQTemplate, messages={}", messages);
        }
    }
}

3.6 源码

源码地址:https://gitee.com/gm19900510/springboot-cloud-example.git 中模块rocketmq

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/3731.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯 - 求组合数【C(a,b)】+ 卡特兰数

文章目录&#x1f4ac;前言885. 求组合数 I C(m,n) 【dp】886 求组合数 II 【数据大小10万级别】 【费马小定理快速幂逆元】887. 求组合数 III 【le18级别】 【卢卡斯定理 逆元 快速幂 】888.求组合数 IV 【没有%p -- 高精度算出准确结果】 【分解质因数 高精度乘法 --只用一…

5.5G产业再提速!高通5GAdvanced-ready芯片商用终端下半年面世

MWC2023大会召开在即&#xff0c;5GAdvanced产业再添重磅消息&#xff01;2月15日&#xff0c;高通宣布推出全球首个5GAdvanced-ready基带芯片——骁龙X755G调制解调器及射频系统&#xff0c;支持毫米波和Sub-6GHz频段&#xff0c;带来网络覆盖、时延、能效和移动性等全方位的提…

【C语言】深度理解指针(下)

一. 前言&#x1f48e;昨晚整理博客时突然发现指针还少了一篇没写&#xff0c;今天就顺便来补一补。上回书说到&#xff0c;emmm忘记了&#xff0c;没事&#xff0c;我们直接进入本期的内容:本期我们带来了几道指针相关笔试题的解析&#xff0c;还算是相对比较轻松的。话不多说…

RTL8201 以太网PHY芯片 调试记录

一、概述 为了尽量给甲方降低成本&#xff0c;决定使用较低成本的PHY芯片RTL8201F-VB-CG芯片。移植官网的以太网demo程序&#xff0c;git上下载了一份很好看的rtl8201F的驱动程序&#xff0c;用来替换官方demo的lan8742程序。并没有直接通&#xff0c;于是开始了调试之路。 二…

mysql索引类型有哪些?

在Mysql数据库当中&#xff0c;我们经常会谈到Sql语句&#xff0c;当然也会谈到索引优化&#xff0c;那么在数据库当中有哪些索引类型呢&#xff0c;博主在这里进行分享&#xff0c;希望对大家能有所帮助。 目录 1、B-Tree索引&#xff1a; 2、Hash索引&#xff1a; 3、Full…

SpringBoot 将PDF转成图片或World

SpringBoot 将PDF转成图片或World 准备工作Apache PDFBox将PDF转成一张图片将PDF转成多张图片将PDF转成其他文件格式总结SpringBoot 是一款非常流行的 Java Web 开发框架,可以用来构建各种 Web 应用程序。在本篇博客中,我们将介绍如何使用 SpringBoot 将 PDF 转换成图片或其他…

Elasticsearch 学习+SpringBoot实战教程(三)

需要学习基础的可参照这两文章 Elasticsearch 学习SpringBoot实战教程&#xff08;一&#xff09; Elasticsearch 学习SpringBoot实战教程&#xff08;一&#xff09;_桂亭亭的博客-CSDN博客 Elasticsearch 学习SpringBoot实战教程&#xff08;二&#xff09; Elasticsearch …

第十四届蓝桥杯三月真题刷题训练——第 23 天

目录 第 1 题&#xff1a;长草 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码&#xff1a; 思路&#xff1a; 第 2 题&#xff1a;蓝肽子序列_LCS_最长公共子序列dp问题 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码&#xff1a; 思路&am…

Spring源码面试最难问题——循环依赖

前言 问&#xff1a;Spring 如何解决循环依赖&#xff1f; 答&#xff1a;Spring 通过提前曝光机制&#xff0c;利用三级缓存解决循环依赖&#xff08;这原理还是挺简单的&#xff0c;参考&#xff1a;三级缓存、图解循环依赖原理&#xff09; 再问&#xff1a;Spring 通过提前…

【前沿技术】问答pk【ChatGPT Vs Notion AI Vs BAT AI 】

目录 写在前面 问题&#xff1a; 1 ChatGPT 1.1 截图 ​1.2 文字版 2 Notion AI 2.1 截图 2.2 文字版 3 BAT AI 3.1 截图 3.2 文字版 总结 序言 所有幸运和巧合的事&#xff0c;要么是上天注定&#xff0c;要么是一个人偷偷的在努力。 突发奇想&#xff0c;问三个…

③【Java组】蓝桥杯省赛真题 持续更新中...

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 蓝桥杯真题--持续更新中...一、错误票据题目描…

CCF-CSP认证 202303 500分题解

202303-1 田地丈量&#xff08;矩阵面积交&#xff09; 矩阵面积交x轴线段交长度*y轴线段交长度 线段交长度&#xff0c;相交的时候是min右端点-max左端点&#xff0c;不相交的时候是0 #include<bits/stdc.h> using namespace std; int n,a,b,ans,x,y,x2,y2; int f(in…

用CSS3画了一只猫

感觉我写得技术含量不高&#xff0c;全都是用绝对定位写的&#xff0c;一定会有更好的&#xff0c;代码量更少的做法吧 <!DOCTYPE html> <html> <head><title>Cute Cat</title><style type"text/css">*{box-sizing: border-box…

100天精通Python(可视化篇)——第81天:matplotlib绘制不同种类炫酷饼图参数说明+代码实战(自定义、百分比、多个子图、圆环、嵌套饼图)

文章目录专栏导读0. 前言1. 参数说明2. 普通饼图3. 百分比饼图4. 突出某一块的饼图5. 自定义颜色的饼图6. 多个子图7. 圆环饼图8. 圆环分离饼图9. 饼图圆环图组合10. 多层圆环饼图专栏导读 &#x1f525;&#x1f525;本文已收录于《100天精通Python从入门到就业》&#xff1a…

【VScode】远程连接Linux

目录标题1. 安装扩展插件2. 在Linux上操作3. 确定Linux的IP地址4. 远程连接到Linux5. 实现免密码登录使用 VScode 远程编程与调试的时有会用到插件 Remote Development&#xff0c;使用这个插件可以在很多情况下代替 vim 直接远程修改与调试服务器上的代码&#xff0c;同时具备…

超详细讲解C语言文件操作!!

超详细讲解C语言文件操作&#xff01;&#xff01;什么是文件文件名文件的打开和关闭文件指针文件的打开和关闭文件的顺序读写文件的随机读写fseekftellrewind文本文件和二进制文件文件读取结束的判定文件缓冲区什么是文件 磁盘上的文件是文件。但是在程序设计中&#xff0c;我…

Python | 蓝桥杯系列文章总结+经典例题重做

欢迎交流学习~~ 专栏&#xff1a; 蓝桥杯Python组刷题日寄 从 4 个月前开始写蓝桥杯系列&#xff0c;到目前为止一共是 19 篇&#xff0c;其中&#xff1a;入门篇 5 篇&#xff0c;简单篇 8 篇&#xff0c;进阶篇 6 篇。 这篇文章主要是为了为先前内容进行总结&#xff0c;并对…

蓝桥杯冲刺 - Lastweek - 你离省一仅剩一步之遥!!!(掌握【DP】冲刺国赛)

文章目录&#x1f4ac;前言&#x1f3af;week3&#x1f332;day10-1背包完全背包多重背包多重背包 II分组背包&#x1f332;day2数字三角形 - 线性DP1015. 摘花生 - 数字三角形&#x1f332;day3最长上升子序列 - 线性DP1017. 怪盗基德的滑翔翼 - LIS1014.登山 - LIS最长公共子…

【JaveEE】多线程之阻塞队列(BlockingQueue)

目录 1.了解阻塞队列 2.生产者消费者模型又是什么&#xff1f; 2.1生产者消费者模型的优点 2.1.1降低服务器与服务器之间耦合度 2.1.2“削峰填谷”平衡消费者和生产的处理能力 3.标准库中的阻塞队列&#xff08;BlockingQueue&#xff09; 3.1基于标准库&#xff08;Bloc…

笔记本只使用Linux是什么体验?

个人主页&#xff1a;董哥聊技术我是董哥&#xff0c;嵌入式领域新星创作者创作理念&#xff1a;专注分享高质量嵌入式文章&#xff0c;让大家读有所得&#xff01;近期&#xff0c;也有朋友问我&#xff0c;笔记本只安装Linux怎么样&#xff0c;刚好我也借此来表达一下我的感受…