《ActiveMQ系列》3.SpringBoot整合Activemq

本文详细介绍了如何在SpringBoot项目中整合ActiveMQ,包括配置环境、设置YML文件、创建配置类,以及发送文本和对象信息。同时,文章讲解了点对点队列和发布订阅主题的区别,以及如何实现持久化订阅,确保消费者在服务重启后仍能接收到之前的消息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《ActiveMQ系列》3.SpringBoot整合Activemq

1 准备环境

  1. 新建springboot项目,引入以下maven依赖,我新建的springboot版本为2.6.14。本应该有提供者和消费者两个项目,我这里用controller代替提供者。
<dependencies>
    <!-- activemq依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-activemq</artifactId>
    </dependency>
    <!--消息队列连接池-->
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-pool</artifactId>
        <version>5.15.0</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- 不写测试类可以删除 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

2 配置ActiveMQ

2.1 配置yml

server:
  port: 9003
spring:
  activemq:
    broker-url: tcp://localhost:61616
    # 消息不放在内存中
    in-memory: false
    pool:
      # true表示使用连接池
      enabled: true
      # 连接池最大连接数
      max-connections: 10
    user: admin
    password: admin

2.2 创建配置类

@Configuration
public class ActiveMQConfig {
    @Value("${spring.activemq.broker-url}")
    private  String brokerUrl;
    
    /**
     * 创建连接工厂
     * @return
     */
    @Bean
    public ActiveMQConnectionFactory connectionFactory() {
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerUrl);
        // 设置所以实体类被activemq信任,消息类型为对象时必须设置,否则会报错:MessageConversionException
        factory.setTrustAllPackages(true);
        return factory;
    }
}

2.3 项目结构

在这里插入图片描述

3 发送文本信息

3.1 配置信息

ActiveMQConfig中增加以下配置

     /**
     * 点对点队列
     * @return
     */
    @Bean
    public Queue queue() {
        return new ActiveMQQueue("QueueTest");
    }

    /**
     * 发布订阅主题
     * @return
     */
    @Bean
    public Topic topic(){
        return new ActiveMQTopic("TopicTest");
    }
	/**
     * Queue模式连接注入(点对点)
     */
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setConnectionFactory(connectionFactory);
        return bean;
    }

    /**
     * Topic模式连接注入
     */
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        //设置为发布订阅方式, 默认情况下使用的生产消费者方式
        bean.setPubSubDomain(true);
        bean.setConnectionFactory(connectionFactory);
        return bean;
    }

3.2 提供者

新建ProducerController提供者,代码如下

@Controller
public class ProducerController {
 
    //注入点对点的模式(Queue模式)
    @Autowired
    private Queue queue;
 
    //注入订阅模式(Topic)的消息
    @Autowired
    private Topic topic;
 
    //注入springboot封装的工具类
    @Autowired
    private JmsMessagingTemplate jms;


    /**
     * 点对点模式(queue)模式发消息
     * @param text
     */
    @GetMapping("/queueSend")
    @ResponseBody
    public String queueSend(String text) {
        //发送消息至消息中间件
        jms.convertAndSend(queue, text);
        return "queue send ok";
    }

    /**
     * 订阅模式(topic)发送消息
     * @param text
     * @return
     */
    @RequestMapping("/topicSend")
    @ResponseBody
    public String topicSend(String text) {
        jms.convertAndSend(topic,text);
        return "topic send ok";
    }
 
}

3.3 消费者

分别新建队列和订阅消费者,代码如下

队列消费者:

/**
 * 消息消費者(Queue模式)
 */
@Component
public class ConsumerQueue {
    /**
     * 使用JmsListener配置消费者监听的队列,text是接收到的消息
     * @param text
     */
    @JmsListener(destination = "QueueTest", containerFactory = "jmsListenerContainerQueue")
    public void receiveQueue(String text) {
        System.out.println("Queue1消费者收到消息:" + text);
    }

}

订阅消费者:

/**
 * 消息消費者(Topic模式)
 */
@Component
public class ConsumerTopic {
    /**
     * 使用JmsListener配置消费者监听的队列,text是接收到的消息
     * @param text
     */
    @JmsListener(destination = "TopicTest", containerFactory = "jmsListenerContainerTopic")
    public void receiveTopic1(String text) {
        System.out.println("Topic消费者1收到消息:" + text);
    }


    @JmsListener(destination = "TopicTest", containerFactory = "jmsListenerContainerTopic")
    public void receiveTopic2(String text) {
        System.out.println("Topic消费者2收到消息:" + text);
    }

}

3.4 测试

队列测试:http://localhost:9003/queueSend?text=helloworld

控制台输出结果:

Queue消费者收到消息:helloworld

发布订阅测试:http://localhost:9003/topicSend?text=helloworld

Topic消费者2收到消息:helloworld
Topic消费者1收到消息:helloworld

3.5 小结

  • 当发送队列(Queue)消息时,只允许一个消费者来消费这些消息。如果存在多个消费者,则它们将会以轮询的方式竞争消费消息。
  • 在发布订阅模式中,消息的发送者(发布者)将消息发送到一个主题(Topic),然后所有订阅该主题的接收者(订阅者)都会收到这个消息的副本。
  • 持久化模式的发布订阅只能有一个消费者。
  • 在发布订阅模式中,如果某个消费者处于离线或者宕机状态时,此时提供者发布的消息会丢失,因为该消费者无法接收到消息。(持久化订阅可以解决该问题)

4 发送对象信息

4.1 配置信息

ActiveMQConfig中增加以下配置,队列和订阅的容器工厂用之前创建的即可。

    /**
     * 点对点队列(发送对象信息)
     * @return
     */
    @Bean
    public Queue queueUser() {
        return new ActiveMQQueue("QueueUser");
    }

    /**
     * 发布订阅主题(发送对象信息)
     * @return
     */
    @Bean
    public Topic topicUser(){
        return new ActiveMQTopic("TopicUser");
    }

4.2 创建实体类

创建实体类,用来发送对象类型消息。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
    private String id;
    private String name;
    private String sex;
}

4.3 提供者

ProducerController增加如下配置

    // 注入点对点模式(发送对象信息)
    @Autowired
    private Queue queueUser;

    // 注入订阅模式(发送对象信息)
    @Autowired
    private Topic topicUser;

    /**
     * 点对点模式(queue)模式发消息
     */
    @GetMapping("/queueSendUser")
    @ResponseBody
    public String queueSendUser() {
        User user = new User("1", "张三", "男");
        jms.convertAndSend(queueUser,user);
        return "queue send user ok";
    }

    /**
     * 订阅模式(topic)发送消息
     * @return
     */
    @RequestMapping("/topicSendUser")
    @ResponseBody
    public String topicSendUser() {
        User user = new User("1", "张三", "男");
        jms.convertAndSend(topicUser,user);
        return "topic send user ok";
    }

4.4 消费者

队列和订阅消费者,增加如下配置

ConsumerQueue

    /**
     * 使用JmsListener配置消费者监听的队列,接收对象消息
     * @param user
     */
    @JmsListener(destination = "QueueUser", containerFactory = "jmsListenerContainerQueue")
    public void receiveQueue(User user) {
        System.out.println("Queue消费者收到对象消息:" + user);
    }

ConsumerTopic

    /**
     * 使用JmsListener配置消费者监听的队列,接收对象消息
     * @param user
     */
    @JmsListener(destination = "TopicUser", containerFactory = "jmsListenerContainerTopic")
    public void receiveTopicUser1(User user) {
        System.out.println("Topic消费者1收到对象消息:" + user);
    }


    @JmsListener(destination = "TopicUser", containerFactory = "jmsListenerContainerTopic")
    public void receiveTopicUser2(User user) {
        System.out.println("Topic消费者2收到对象消息:" + user);
    }

4.5 测试

队列测试:http://localhost:9003/queueSendUser

Queue消费者收到对象消息:User(id=1, name=张三, sex=男)

发布订阅测试:http://localhost:9003/topicSendUser

Topic消费者2收到对象消息:User(id=1, name=张三, sex=男)
Topic消费者1收到对象消息:User(id=1, name=张三, sex=男)

5 持久化订阅

5.1 配置信息

ActiveMQConfig中增加以下配置,使用持久化主题之前请先配置JDBC持久化(参考ActiveMQ安装教程)

    /**
     * 发布订阅主题(持久化主题)
     * @return
     */
    @Bean
    public Topic topicDurable(){
        return new ActiveMQTopic("topicDurable");
    }

    /**
     * Topic模式连接注入,持久化配置
     */
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerTopicDurable(ActiveMQConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        //设置为发布订阅方式, 默认情况下使用的生产消费者方式
        bean.setPubSubDomain(true);
        bean.setConnectionFactory(connectionFactory);
        // 设置持久化,每个持久化的订阅都需要设置一个clientId
        bean.setSubscriptionDurable(true);
        bean.setClientId("myClientId");
        return bean;
    }

5.2 提供者

ProducerController增加如下配置

 /**
     * 持久化订阅发送消息
     * @return
     */
    @RequestMapping("/subSend")
    @ResponseBody
    public String topicSendUser(String text) {
        jms.convertAndSend(topicDurable,text);
        return "topic send durable ok";
    }

5.3 消费者

ConsumerTopic增加如下配置

    /**
     * 接收持久化订阅消息
     * @param text
     */
    @JmsListener(destination = "topicDurable", containerFactory = "jmsListenerContainerTopicDurable")
    public void receiveTopicDurable(String text) {
        System.out.println("持久化Topic消费者收到消息:" + text);
    }

5.4 测试

访问ActiveMQ页面,有如下内容,代表持久化订阅注册成功。

在这里插入图片描述

发布订阅测试:http://localhost:9003/subSend?text=helloworld

持久化Topic消费者收到消息:helloworld

5.5 小结

​ 当使用持久化主题时,订阅该主题的消费者不仅可以接收到发布者发送的当前消息,还可以接收到之前发送的消息。这是因为服务器会将所有发布到持久化主题的消息保存到持久化存储中,以便在重启后重新加载这些消息并传递给消费者。

​ 相比之下,非持久化主题只能传递当前消息,如果服务器在消息传递过程中宕机或重启,那么未被消费的消息将会丢失。

如果需要源码,私信我,我看到会回复你们。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值