Spring Boot集成ActiveMQ

ActiveMQ异步消息主要有两种目的地形式,队列(queue)和主题(topic),队列用于点对点形式的消息通信,主题用于发布/订阅式的消息通信。
ActiveMQ安装:
百度网盘下载:https://pan.baidu.com/s/1BNoOeiZ_Ry0oe-raEEVEmA
提取码:3qba
官网:http://activemq.apache.org/
安装:
进入路劲
Spring Boot集成ActiveMQ_第1张图片Spring Boot集成ActiveMQ_第2张图片双击Spring Boot集成ActiveMQ_第3张图片启动成功后,会出现如图所示结果 Connector vm://localhost Started
Spring Boot集成ActiveMQ_第4张图片在浏览器中输入 http://127.0.0.1:8161/admin/ 来访问 ActiveMQ 的服务器,用户名和密码是 admin/admin。如下:
Spring Boot集成ActiveMQ_第5张图片我们可以看到有 Queues 和 Topics 这两个选项,这两个选项分别是点对点消息和发布/订阅消息的查看窗口
ActiveMQ集成
在 Spring Boot 中集成 ActiveMQ 需要导入如下 starter 依赖:

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

然后在 application.yml 配置文件中,对 activemq 做一下配置:

spring:
  activemq:
    broker-url: tcp://localhost:61616
    in-memory: true
    pool:
      # 如果此处设置为true,需要添加activemq-pool的依赖包,否则会自动配置失败,无法注入JmsMessagingTemplate
      enabled: false
server:
  port: 8080

队列(Queue)和主题(Topic)是JMS支持的两种消息传递模型:
1、点对点(point-to-point,简称PTP)Queue消息传递模型:
通过该消息传递模型,一个应用程序(即消息生产者)可以向另外一个应用程序(即消息消费者)发送消息。在此传递模型中,消息目的地类型是队列(即Destination接口实现类实例由Session接口实现类实例通过调用其createQueue方法并传入队列名称而创建)。消息首先被传送至消息服务器端特定的队列中,然后从此对列中将消息传送至对此队列进行监听的某个消费者。同一个队列可以关联多个消息生产者和消息消费者,但一条消息仅能传递给一个消息消费者。如果多个消息消费者正在监听队列上的消息,,JMS消息服务器将根据“先来者优先”的原则确定由哪个消息消费者接收下一条消息。如果没有消息消费者在监听队列,消息将保留在队列中,直至消息消费者连接到队列为止。这种消息传递模型是传统意义上的懒模型或轮询模型。在此模型中,消息不是自动推动给消息消费者的,而是要由消息消费者从队列中请求获得。
2、发布/订阅(publish/subscribe,简称pub/sub)Topic消息传递模型:
通过该消息传递模型,应用程序能够将一条消息发送给多个消息消费者。在此传送模型中,消息目的地类型是主题(即Destination接口实现类实例由Session接口实现类实例通过调用其createTopic方法并传入主题名称而创建)。消息首先由消息生产者发布至消息服务器中特定的主题中,然后由消息服务器将消息传送至所有已订阅此主题的消费者。主题目标也支持长期订阅。长期订阅表示消费者已注册了主题目标,但在消息到达目标时该消费者可以处于非活动状态。当消费者再次处于活动状态时,将会接收该消息。如果消费者均没有注册某个主题目标,该主题只保留注册了长期订阅的非活动消费者的消息。与PTP消息传递模型不同,pub/sub消息传递模型允许多个主题订阅者接收同一条消息。JMS一直保留消息,直至所有主题订阅者都接收到消息为止。pub/sub消息传递模型基本上是一个推模型。在该模型中,消息会自动广播,消息消费者无须通过主动请求或轮询主题的方法来获得新的消息。
Queue 和 Topic 的创建
首先我们需要创建两种消息 Queue 和 Topic,这两种消息的创建,我们放到 ActiveMqConfig 中来创建,如下:

import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;

import javax.jms.ConnectionFactory;
import javax.jms.Destination;
@Configuration
public class ActiveMqConfig {
    /**
     * 发布/订阅模式队列名称
     */
    public static final String TOPIC_NAME = "activemq.topic";
    /**
     * 点对点模式队列名称
     */
    public static final String QUEUE_NAME = "activemq.queue";

    @Bean
    public Destination topic() {
        
        return new ActiveMQTopic(TOPIC_NAME);
    }

    @Bean
    public Destination queue() {
        return new ActiveMQQueue(QUEUE_NAME);
    }

消息发送者:


import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.jms.Destination;
@Service
public class MsgProducer {

    @Resource
    private JmsMessagingTemplate jmsMessagingTemplate;
	
    public void sendMessage(Destination destination, String msg) {
        jmsMessagingTemplate.convertAndSend(destination, msg);
    }
}

点对点消息生产与消费

@RestController
@RequestMapping("/activemq")
public class ActiveMqController {

    private static final Logger logger = LoggerFactory.getLogger(ActiveMqController.class);

    @Resource
    private MsgProducer producer;
    @Resource
    private Destination topic;
    @Resource
    private Destination queue;

    @GetMapping("/send/queue")
    public String sendQueueMessage() {
        logger.info("===开始发送点对点消息===");
        producer.sendMessage(queue, "Queue: hello activemq!");
        return "success";
    }

点对点消息的消费

@Service
public class QueueConsumer {

    /**
     * 接收点对点消息
     * @param msg
     */
    @JmsListener(destination = ActiveMqConfig.QUEUE_NAME)
    public void receiveQueueMsg(String msg) {
        System.out.println("收到的消息为:" + msg);
    }

启动项目,在浏览器中输入:http://localhost:8081/activemq/send/queue,观察控制台的输出日志,出现下面的日志说明消息发送和消费成功。
在这里插入图片描述
发布/订阅消息的生产和消费(topic )

@RestController
@RequestMapping("/activemq")
public class ActiveMqController {

    private static final Logger logger = LoggerFactory.getLogger(ActiveMqController.class);

    @Resource
    private MsgProducer producer;
    @Resource
    private Destination topic;

    @GetMapping("/send/topic")
    public String sendTopicMessage() {

        logger.info("===开始发送订阅消息===");
        producer.sendMessage(topic, "Topic: hello activemq!");
        return "success";
    }
}

解决同时接收queue消息和topic消息

   /**
     * 
     * 解决同时接收queue消息和topic消息
     */
    @Bean
    public JmsListenerContainerFactory topicListenerContainer(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        // 相当于在application.yml中配置:spring.jms.pub-sub-domain=true
        factory.setPubSubDomain(true);
        return factory;
    }

Topic消息消费者(可同时支持多个消费者)

@Service
public class TopicConsumer1 {

    /**
     * 接收订阅消息
     * @param msg
     * ,在 @JmsListener 注解中指定这个容器工厂即可消费 topic 消息
     */
    @JmsListener(destination = ActiveMqConfig.TOPIC_NAME, containerFactory = "topicListenerContainer")
    public void receiveTopicMsg(String msg) {
        System.out.println("收到的消息为1:" + msg);
    }

}
@Service
public class TopicConsumer2{

    /**
     * 接收订阅消息
     * @param msg
     * ,在 @JmsListener 注解中指定这个容器工厂即可消费 topic 消息
     */
    @JmsListener(destination = ActiveMqConfig.TOPIC_NAME, containerFactory = "topicListenerContainer")
    public void receiveTopicMsg2(String msg) {
        System.out.println("收到的消息为2:" + msg);
    }

}

测试:

  @GetMapping("/send/topic")
    public String sendTopicMessage() {

        logger.info("===开始发送订阅消息===");
//        Destination destination = new ActiveMQTopic(ActiveMqConfig.TOPIC_NAME);
        producer.sendMessage(topic, "Topic: hello activemq!");
        return "success";
    }

收到的消息为1:Topic: hello activemq!
收到的消息为2:Topic: hello activemq!
topic的持久化配置:

  @Bean(name = "topicContainerFactory1")
    public DefaultJmsListenerContainerFactory topicClient1(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer){
        DefaultJmsListenerContainerFactory factory = defaultJmsListenerContainerFactoryTopic(connectionFactory,configurer);
        factory.setConnectionFactory(connectionFactory);
        // 相当于在application.yml中配置:spring.jms.pub-sub-domain=true
        factory.setPubSubDomain(true);
        factory.setClientId("10001");
        return factory;
    }

    @Bean(name = "topicContainerFactory2")
    public DefaultJmsListenerContainerFactory topicClient2(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer){
        DefaultJmsListenerContainerFactory factory = defaultJmsListenerContainerFactoryTopic(connectionFactory,configurer);
        factory.setConnectionFactory(connectionFactory);
        // 相当于在application.yml中配置:spring.jms.pub-sub-domain=true
        factory.setPubSubDomain(true);
        factory.setClientId("10002");
        return factory;
    }
    public DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactoryTopic(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        configurer.configure(factory,connectionFactory);
        factory.setPubSubDomain(true);
        factory.setSessionTransacted(true);
        factory.setAutoStartup(true);
        //开启持久化订阅
        factory.setSubscriptionDurable(true);
        return factory;
    }
@JmsListener(destination = ActiveMqConfig.TOPIC_NAME,containerFactory = "topicContainerFactory1") // 监听指定消息主题
    public void receiveMessage1(String message) throws Exception {
        System.out.println("收到的消息为1:" + message);
    }

 @JmsListener(destination = ActiveMqConfig.TOPIC_NAME,containerFactory = "topicContainerFactory2") // 监听指定消息主题
    public void receiveMessage1(String message) throws Exception {
        System.out.println("收到的消息为2:" + message);
    }

测试接收:
先启动项目,注释以下接收代码访问http://localhost:8080/activemq/send/topic 推送消息
将注释放开,重启项目,会接收到刚才推送的消息

在这里插入图片描述
参考:https://blog.csdn.net/eson_15/article/details/104347476
https://blog.csdn.net/Cons_Step_By_Step/article/details/78314826

你可能感兴趣的:(Spring Boot集成ActiveMQ)