SpringBoot项目如何使用ActiveMQ的订阅/发布(topic)、点对点(queue)两种模式?

前言:mq的订阅/发布模式和点对点模式的区别网上很多,博主不再赘述,直接上代码:

一、部署MQ

网上很多教程,操作相对简单,这里我就不详细说了。大概就是:

1、去官网下载active的解压缩版;

2、解压之后以管理员身份运行“...\ActiveMQ\bin\win64”目录下的InstallService.bat批处理文件,然后就可以将mq注册成windows服务了。

二、在pom文件中引入ActiveMQ的库

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

三、编写配置类,用于连接MQ服务(订阅/发布模式和点对点模式的配置都在这里了)

1、编写配置文件,配置mq地址、用户名、密码等

//端口默认为61616
spring.activemq.broker-url=tcp://192.168.1.110:61616
spring.activemq.user=admin
spring.activemq.password=admin

将mq的连接信息写入配置类的意义在于便于开发环境和生产环境的切换,不理解的可以留言,我看到了会回复的。

2、编写配置类,订阅/发布模式即Topic,点对点模式即Queue

import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
import org.springframework.jms.core.JmsMessagingTemplate;

@Configuration
public class ActiveMQConfiguration {

    //这个Bean用于和mq建立连接、mq的地址、用户名、密码从配置文件中获取
    @Bean(name = "innerConnectionFactory")
    @Primary
    public ActiveMQConnectionFactory firstConnectionFactory(
            //mq服务地址
            @Value("${spring.activemq.broker-url}") String brokerUrl,
            //mq用户名
            @Value("${spring.activemq.user}") String username,
            //mq密码
            @Value("${spring.activemq.password}") String password) {
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
        factory.setBrokerURL(brokerUrl);
        factory.setUserName(username);
        factory.setPassword(password);
        return factory;
    }

    //这个Bean用于发布主题消息或者生产队列消息
    @Bean(name = "jmsMessagingTemplate")
    @Primary
    public JmsMessagingTemplate jmsMessagingTemplate(
            //将“innerConnectionFactory”这个Bean注入
            @Qualifier("innerConnectionFactory") ActiveMQConnectionFactory connectionFactory) {
        JmsMessagingTemplate template = new JmsMessagingTemplate(connectionFactory);
        return template;
    }


    /**
     * 在Queue模式中,对消息的监听需要对containerFactory进行配置
     */
    @Bean("queueJmsListenerContainerFactory")
    public JmsListenerContainerFactory<?> queueJmsListenerContainerFactory(
            //将“innerConnectionFactory”这个Bean注入  
            @Qualifier("innerConnectionFactory") ActiveMQConnectionFactory connectionFactory){
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(false);
        return factory;
    }

    /**
     * 在Topic模式中,对消息的监听需要对containerFactory进行配置
     */
    @Bean("topicJmsListenerContainerFactory")
    public JmsListenerContainerFactory<?> topicJmsListenerContainerFactory(
            //将“innerConnectionFactory”这个Bean注入
            @Qualifier("innerConnectionFactory") ActiveMQConnectionFactory connectionFactory){
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(true);
        return factory;
    }
}

四、使用mq的订阅/发布模式(即订阅/发布topic)

1、发布主题消息类

import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;

import javax.jms.Destination;

@Service
public class TopicPublisherService {
    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    /**
     * 发布主题消息
     * @destinationName 主题名
     * @message 消息
     */
    public void publishMsg(String destinationName, String message) {
        Destination destination = new ActiveMQTopic(destinationName);
        jmsMessagingTemplate.convertAndSend(destination, message);
    }
}

2、订阅主题消息类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

@Service
public class TopicSubscriberService {

    @Autowired
    SimpMessagingTemplate simpMessagingTemplate;

    /**
     * 订阅主题
     */
    @JmsListener(destination = "test.topic",containerFactory = "topicJmsListenerContainerFactory")
    public void subscribeTopicWebsocketSystemNoticeMsg(String message) {
        System.out.println("接收到了一条主题消息:" + message);
    }
}

3、测试发布主题消息类和订阅主题类

import cn.xxx.SpringBootApplication;
import cn.xxx.mq.TopicPublisherService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootApplication.class) // 指定我们SpringBoot工程的Application启动类
@WebAppConfiguration // 由于是Web项目,Junit需要模拟ServletContext,因此我们需要给我们的测试类加上@WebAppConfiguration。
public class TestMq {

    @Autowired
    private TopicPublisherService topicPublisherService;

    @Test
    public void TestPublishMQTopic(){
        topicPublisherService.publishMsg("test.topic","test...");
    }
}

先用application启动项目,然后运行“TestPublishMQTopic()”方法,然后打开ActiveMQ的主页查看是否成功(我部署的路径为http://192.168.1.160:8161,8681是打开mq主页的默认端口):

首先进入首页:

然后点击Topic,查看所有的主题

找到test.topic这个主题,可以看到,有消息发布成功:

然后在控制台看到:

说明收到了发布的消息!

五、使用MQ的点对点模式

1、点对点的生产者类

import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;

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

@Service
public class MessageProducerService {
    @Resource
    private JmsMessagingTemplate jmsMessagingTemplate;

    /**
     * 发送队列消息
     * @param destinationName 消息目的地标识
     * @param message 消息文本
     */
    public void sendMsg(String destinationName, String message) {
        Destination destination = new ActiveMQQueue(destinationName);
        jmsMessagingTemplate.convertAndSend(destination, message);
    }
}

2、点对点的消费者类

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;

@Service
public class MessageConsumerService {
    @JmsListener(destination="test.msg.queue",containerFactory = "queueJmsListenerContainerFactory")
    public void receiveMessage(String text) {    // 进行消息接收处理
        System.out.println("【*** 接收消息 ***】" + text);
    }
}

3、测试类

import cn.sinvie.SpringBootApplication;
import cn.sinvie.mq.MessageProducerService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootApplication.class) // 指定我们SpringBoot工程的Application启动类
@WebAppConfiguration // 由于是Web项目,Junit需要模拟ServletContext,因此我们需要给我们的测试类加上@WebAppConfiguration。
public class TestMq {

    @Autowired
    private MessageProducerService messageProducerService;

    @Test
    public void TestSendMQQueue(){
        messageProducerService.sendMsg("test.msg.queue","test...");
    }
}

先后运行SpringBootApplication主程序和TestSendMQQueue测试方法,然后去MQ的主页查看queue,看看是否有“test.msg.queue”这个消息队列

有就证明生产者生产消息成功,然后再看控制台是否打印了消息

成功打印了消息,说明消费者类消费成功!

实现了订阅/发布模式和点对点模式以后,可能会有疑问,两者实现的功能看起来不是一样的吗?

当然有区别,简单的来说,有这些区别:

Topic--订阅/发布         Queue--点对点
实时通讯,发布时,若订阅者未连接则消息丢失 持久化,消息被消费者消费后才会消失
需要先订阅,后发布 生产了就能收到
发布的消息所有的订阅者都能收到 生产者生产的消息只能被消费者消费一次,故又被称为点对点模式
发布了96 篇原创文章 · 获赞 45 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_26356861/article/details/100546338