SpringBoot2.x系列教程61--SpringBoot整合消息队列之ActiveMQ代码实现异步消息传递及回复

SpringBoot2.x系列教程61--SpringBoot整合消息队列之ActiveMQ代码实现消息传递

作者:一一哥

我在上一章节中,给大家介绍了ActiveMQ,本节中我会介绍Spring Boot中如何整合ActiveMQ,实现消息的创建和消费。

一. Spring Boot中整合ActiveMQ

1. 创建web项目

我们按照之前的经验,创建一个web程序,并将之改造成Spring Boot项目,具体过程略。
SpringBoot2.x系列教程61--SpringBoot整合消息队列之ActiveMQ代码实现异步消息传递及回复_第1张图片

2. 添加依赖包


    org.springframework.boot
    spring-boot-starter-activemq

3. 创建application.yml配置文件

#配置activemq
spring:
  activemq:
    #activemq的url
    broker-url: tcp://127.0.0.1:61616
    #用户名
    user: admin
    #密码
    password: admin
    pool:
      enabled: false #是否使用线程池
      max-connections: 100 #最大连接数
    #是否信任所有包
    packages:
      trust-all: true
  #默认情况下,activemq使用的是queue模式,如果要使用topic模式,必须设置为true
  jms:
    pub-sub-domain: true

4. 创建ActiveMQ的配置类

在这个类中创建连接工厂,消息队列等。

package com.yyg.boot.config;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;

import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import javax.jms.Topic;

/**
 * @Author 一一哥Sun
 * @Date Created in 2020/4/14
 * @Description Description
 * //@EnableJms启用jms功能
 */
@Configuration
@EnableJms
public class ActivemqConfig {

    @Autowired
    private Environment env;

    @Bean
    public ConnectionFactory connectionFactory() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        connectionFactory.setBrokerURL(env.getProperty("spring.activemq.broker-url"));
        connectionFactory.setUserName(env.getProperty("spring.activemq.user"));
        connectionFactory.setPassword(env.getProperty("spring.activemq.password"));
        return connectionFactory;
    }

    /**
     * 实现监听queue
     */
    @Bean("jmsQueueListenerContainerFactory")
    public JmsListenerContainerFactory queueContainerFactory(ConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        //开启接收topic类型的消息
        factory.setPubSubDomain(false);
        return factory;
    }

    /**
     * 实现监听topic
     */
    @Bean("jmsTopicListenerContainerFactory")
    public JmsListenerContainerFactory topicContainerFactory(ConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(true);
        return factory;
    }

    /**
     * 队列名称
     */
    @Bean("springboot.queue")
    public Queue queue() {
        return new ActiveMQQueue("springboot.queue") ;
    }

    /**
     * Topic名称
     */
    @Bean("springboot.topic")
    public Topic topic() {
        return new ActiveMQTopic("springboot.topic") ;
    }

}

5. 创建消息生产者的工具类

在这个Producer类中,创建几个发送消息的的方法。

package com.yyg.boot.jms;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;

/**
 * @Author 一一哥Sun
 * @Date Created in 2020/4/15
 * @Description 消息生产者
 */
@Slf4j
@Component
public class Producer {

    @Resource(name = "springboot.queue")
    private Queue queue;

    @Resource(name = "springboot.topic")
    private Topic topic;

    @Resource(name = "springboot.replyQueue")
    private Queue replyQueue;

    @Autowired
    private JmsMessagingTemplate jmsTemplate;

    /**
     * 发送消息,destination是发送到的目标队列,message是待发送的消息内容;
     */
    public void sendMessage(Destination destination, final String message) {
        jmsTemplate.convertAndSend(destination, message);
    }

    /**
     * 发送队列消息
     */
    public void sendQueueMessage(final String message) {
        sendMessage(queue, message);
    }

    /**
     * 发送Topic消息
     */
    public void sendTopicMessage(final String message) {
        sendMessage(topic, message);
    }

}

6. 定义消费消息的Consumer类

package com.yyg.boot.jms;

import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;

/**
 * @Author 一一哥Sun
 * @Date Created in 2020/4/15
 * @Description 消息的消费者
 */
@Slf4j
@Component
public class Consumer {

    /**
     * 监听Queue队列,queue类型
     */
    @JmsListener(destination="springboot.queue",
            containerFactory = "jmsQueueListenerContainerFactory")
    public void receiveQueue(String text){
        log.warn(this.getClass().getName()+ "-->收到的报文为:"+text);
    }

    /**
     * 监听Topic队列,topic类型,这里containerFactory要配置为jmsTopicListenerContainerFactory
     */
    @JmsListener(destination = "springboot.topic",
            containerFactory = "jmsTopicListenerContainerFactory")
    public void receiveTopic(String text) {
        log.warn(this.getClass().getName()+"-->收到的报文为:"+text);
    }
    
}

7. 创建Controller,发布消息

package com.yyg.boot.web;

import com.yyg.boot.domain.User;
import com.yyg.boot.jms.Consumer;
import com.yyg.boot.jms.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author 一一哥Sun
 * @Date Created in 2020/4/15
 * @Description Description
 */
@RestController
public class MsgController {

    @Autowired
    private Producer producer;

    @Autowired
    private Consumer consumer;

    @GetMapping("/sendQueue")
    public String sendQueueMsg() {
        User user = new User();
        user.setId(1L);
        user.setUsername("一一哥Queue");
        user.setPassword("123");
        producer.sendQueueMessage(user.toString());
        return "发送成功!";
    }

    @GetMapping("/sendTopic")
    public String sendTopicMsg() {
        User user = new User();
        user.setId(2L);
        user.setUsername("一一哥Topic");
        user.setPassword("123456");
        producer.sendTopicMessage(user.toString());
        return "发送成功!";
    }

}

8. 创建入口类

package com.yyg.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ActiveMQApplication {

    public static void main(String[] args) {
        SpringApplication.run(ActiveMQApplication.class, args);
    }

}

9. 完整项目结构

10. 启动项目进行测试

测试发送点对点类型的消息
SpringBoot2.x系列教程61--SpringBoot整合消息队列之ActiveMQ代码实现异步消息传递及回复_第2张图片

队列中可以看到成功的收到了消息。

在ActiveMQ中也可以看到出现了springboot.queue队列,并且队列中的消息已被消费掉。
SpringBoot2.x系列教程61--SpringBoot整合消息队列之ActiveMQ代码实现异步消息传递及回复_第3张图片

测试发送发布者订阅者类型的消息
SpringBoot2.x系列教程61--SpringBoot整合消息队列之ActiveMQ代码实现异步消息传递及回复_第4张图片

Topic中可以看到成功的收到了消息。

在ActiveMQ中也可以看到出现了springboot.topic队列,并且队列中的消息已被消费掉。

二. 回复消息的实现

我们在上面的基础之上,进一步实现发送消息后,进行消息的回复。

1. 改造ActiveMQ类

在该类中添加一个用来接收回复消息的队列。

/**
* 回复队列名称
*/
@Bean("springboot.replyQueue")
public Queue queueReply() {
        return new ActiveMQQueue("springboot.replyQueue") ;
}

完整的ActivemqConfig代码:

package com.yyg.boot.config;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;

import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import javax.jms.Topic;

/**
 * @Author 一一哥Sun
 * @Date Created in 2020/4/14
 * @Description Description
 * //@EnableJms启用jms功能
 */
@Configuration
@EnableJms
public class ActivemqConfig {

    @Autowired
    private Environment env;

    @Bean
    public ConnectionFactory connectionFactory() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        connectionFactory.setBrokerURL(env.getProperty("spring.activemq.broker-url"));
        connectionFactory.setUserName(env.getProperty("spring.activemq.user"));
        connectionFactory.setPassword(env.getProperty("spring.activemq.password"));
        return connectionFactory;
    }

    /**
     * 实现监听queue
     */
    @Bean("jmsQueueListenerContainerFactory")
    public JmsListenerContainerFactory queueContainerFactory(ConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        //开启接收topic类型的消息
        factory.setPubSubDomain(false);
        return factory;
    }

    /**
     * 实现监听topic
     */
    @Bean("jmsTopicListenerContainerFactory")
    public JmsListenerContainerFactory topicContainerFactory(ConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(true);
        return factory;
    }

    /**
     * 队列名称
     */
    @Bean("springboot.queue")
    public Queue queue() {
        return new ActiveMQQueue("springboot.queue") ;
    }

    /**
     * Topic名称
     */
    @Bean("springboot.topic")
    public Topic topic() {
        return new ActiveMQTopic("springboot.topic") ;
    }

    /**
     * 回复队列名称
     */
    @Bean("springboot.replyQueue")
    public Queue queueReply() {
        return new ActiveMQQueue("springboot.replyQueue") ;
    }

}

2. 改造Producer类

在Producer类中定义一个新的Queue类,并定义发送消息和消费消息的方法。

@Resource(name = "springboot.replyQueue")
private Queue replyQueue;

/**
* 发送队列的回复消息
*/
public void sendQueueMessageReply(String message) {
    sendMessage(replyQueue, message);
}

/**
* 生产者监听消费者的应答信息
*/
@JmsListener(destination = "replyTo.queue",containerFactory = "jmsQueueListenerContainerFactory")
public void consumerMessage(final String text) {
    log.warn("从replyTo.queue队列中收到的应答报文为:" + text);
}    

完整的Producer类代码:

package com.yyg.boot.jms;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;

/**
 * @Author 一一哥Sun
 * @Date Created in 2020/4/15
 * @Description 消息生产者
 */
@Slf4j
@Component
public class Producer {

    @Resource(name = "springboot.queue")
    private Queue queue;

    @Resource(name = "springboot.topic")
    private Topic topic;

    @Resource(name = "springboot.replyQueue")
    private Queue replyQueue;

    @Autowired
    private JmsMessagingTemplate jmsTemplate;

    /**
     * 发送消息,destination是发送到的目标队列,message是待发送的消息内容;
     */
    public void sendMessage(Destination destination, final String message) {
        jmsTemplate.convertAndSend(destination, message);
    }

    /**
     * 发送队列消息
     */
    public void sendQueueMessage(final String message) {
        sendMessage(queue, message);
    }

    /**
     * 发送Topic消息
     */
    public void sendTopicMessage(final String message) {
        sendMessage(topic, message);
    }

    /**
     * 发送队列的回复消息
     */
    public void sendQueueMessageReply(String message) {
        sendMessage(replyQueue, message);
    }

    /**
     * 生产者监听消费者的应答信息
     */
    @JmsListener(destination = "replyTo.queue",containerFactory = "jmsQueueListenerContainerFactory")
    public void consumerMessage(final String text) {
        log.warn("从replyTo.queue队列中收到的应答报文为:" + text);
    }
    
}

3. 改造Consumer类

在该类中添加接收消息,并且设置回复消息的方法。

/**
* 回复给生产者的应答信息
*/
@JmsListener(destination="springboot.replyQueue",containerFactory = "jmsQueueListenerContainerFactory")
@SendTo("replyTo.queue") //消费者应答后通知生产者
public String receiveQueueReply(String text){
    log.warn(this.getClass().getName()+ "-->收到的报文为:"+text);
    return "回复的信息为-->"+text;
}

完整的Consumer类代码:

package com.yyg.boot.jms;

import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;

/**
 * @Author 一一哥Sun
 * @Date Created in 2020/4/15
 * @Description 消息的消费者
 */
@Slf4j
@Component
public class Consumer {

    /**
     * 监听Queue队列,queue类型
     */
    @JmsListener(destination="springboot.queue",
            containerFactory = "jmsQueueListenerContainerFactory")
    public void receiveQueue(String text){
        log.warn(this.getClass().getName()+ "-->收到的报文为:"+text);
    }

    /**
     * 监听Topic队列,topic类型,这里containerFactory要配置为jmsTopicListenerContainerFactory
     */
    @JmsListener(destination = "springboot.topic",
            containerFactory = "jmsTopicListenerContainerFactory")
    public void receiveTopic(String text) {
        log.warn(this.getClass().getName()+"-->收到的报文为:"+text);
    }

    /**
     * 回复给生产者的应答信息
     */
    @JmsListener(destination="springboot.replyQueue",containerFactory = "jmsQueueListenerContainerFactory")
    @SendTo("replyTo.queue") //消费者应答后通知生产者
    public String receiveQueueReply(String text){
        log.warn(this.getClass().getName()+ "-->收到的报文为:"+text);
        return "回复的信息为-->"+text;
    }

}

4. 重新运行,测试消息的回复功能

调用如下接口,测试消息回复功能。
SpringBoot2.x系列教程61--SpringBoot整合消息队列之ActiveMQ代码实现异步消息传递及回复_第5张图片

此时可以看到控制台输出如下信息,说明消息回复成功。

至此,我们实现了Spring boot中如何整合ActiveMQ。
 

你可能感兴趣的:(Spring,Boot,2,ActiveMQ)