本文记录学习在Spring Boot中使用MQ。

一 什么是MQ

  MQ全称(Message Queue)又名消息队列,是一种异步通讯的中间件。它的作用类似于邮局,发信人(生产者)只需要将信(消息)交给邮局,然后由邮局再将信(消息)发送给具体的接收者(消费者),具体发送过程与时间发信人可以不关注,也不会影响发信人做其它事情。目前常见的MQ有activemq、kafka、rabbitmq、zeromq、rocketmq等。

  使用MQ的优点主要有:

  1 方法的异步执行 使用MQ可以将耗时的同步操作通过以发送消息的方式进行了异步化处理,减少了由于同步而等待的时间;

  2 程序之间松耦合 使用MQ可以减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,只要约定好消息的内容格式就行;

  JMS(Java Message Service)即java消息服务,是一个Java平台中关于面向消息中间件(MOM)的 API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。JMS的消息机制有2种模型,一种是1对1(Point to Point)的队列的消息,这种消息,只能被一个消费者消费;另一种是一对多的发布/订阅(Topic)消息,一条消息可以被多个消费者消费。ActiveMq是对JMS的一个实现。

二 SpringBoot集成Active MQ

  官网下载一个服务程序,解压后直接启动服务就可以了,下载地址:http://activemq.apache.org/activemq-5158-release.html

  SpringBoot也对Active MQ提供了支持,我们使用时引入具体的依赖即可,修改pom.xml文件,添加依赖

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

  在application.properties文件中配置Active MQ服务器的连接信息

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin
#消息模式 true:广播(Topic),false:队列(Queue),默认时false
#spring.jms.pub-sub-domain=true

  完成以上配置信息后,当我们在启动SpringBoot项目时,会自动帮我们完成初始化操作,并提供一个JmsMessagingTemplate,提提供了我们常用发送消息的各种方法供我们使用。我们只需要在使用的地方注入JmsMessagingTemplate即可使用。

  发送队列消息

@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivemqApplicationTests { @Autowired
private JmsMessagingTemplate jmsMessagingTemplate; @Test
public void testQueueMsg(){
//创建名称为zyQueue的队列
Queue queue = new ActiveMQQueue("zyQueue");
//向队列发送消息
jmsMessagingTemplate.convertAndSend(queue,"这是一个队列消息!");
}
}

  消息的接收方,监听消息队列,当队列中有消息时就可以获取到消息

@Component
public class Consumer { private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,sss"); /**
* destination 目标地址即队列
*/
@JmsListener(destination = "zyQueue")
public void receiveMessage(String text){
System.out.println("接收队列消息时间:"+ df.format(new Date()) +", 接收到消息内容:"+text);
}
}

  执行测试方法发送消息可以看到,控制台输出的消费者接受到消息

队列消息只能有一个消费者,如果有多个消费者同时监听一个队列时,只能有一个拿到消息,我们测试,修改发送方法,循环发送10调消息

@Test
public void testQueueMsg(){
//创建名称为zyQueue的队列
Queue queue = new ActiveMQQueue("zyQueue");
//向队列发送消息
for (int i=0;i<10;i++) {
jmsMessagingTemplate.convertAndSend(queue,"这是第"+i+"个队列消息!");
}
}

  在Consumer 类中再添加一个消费者,监听队列zyQueue

@JmsListener(destination = "zyQueue")
public void receiveMessage(String text){
System.out.println("接收队列消息时间:"+ df.format(new Date()) +", 接收到消息内容:"+text);
} @JmsListener(destination = "zyQueue")
public void receiveMessage1(String text){
System.out.println("1接收队列消息时间:"+ df.format(new Date()) +", 接收到消息内容:"+text);
}

  执行发送消息,看到控制台输出的结果,2个消费者平分了这10条消息

  如果希望监听同一个队列的多个消费者都能接收到所有消息,我们就只能发送Topic消息了,我们修改application.properties中的

#消息模式 true:广播(Topic),false:队列(Queue),默认时false
spring.jms.pub-sub-domain=true

  表示要发送发布/订阅消息,发送消息的队列改用Topic发送消息,如下

@Test
public void testTopicMsg(){
Topic topic = new ActiveMQTopic("zyTopic");
for (int i=0;i<5;i++){
jmsMessagingTemplate.convertAndSend(topic,"这是第"+i+"个Topic消息!");
}
}

  我们在Consumer 类中添加两个消费者来监听zyTopic队列,接受消息

@JmsListener(destination = "zyTopic")
public void receiveTopicMessage1(String text){
System.out.println("消费者1接收消息时间:"+ df.format(new Date()) +", 接收到消息内容:"+text);
} @JmsListener(destination = "zyTopic")
public void receiveTopicMessage2(String text){
System.out.println("消费者2接收消息时间:"+ df.format(new Date()) +", 接收到消息内容:"+text);
}

  执行发消息方法,可以看到控制台输出的内容,2个消费者都完整的接收到了5条消息

  我们在测试发送消息时修改了属性文件中的配置信息,才可以发送对应的类型的消息,这是由于SpringBoot中默认的是队列消息(查看源码可以知道,监听器默认使用的DefaultJmsListenerContainerFactory),如果我们想在不修改配置信息的情况下可以同时发送Queue和Topic消息怎么办呢,我们需要手动的更改初始的配置类,分别针对Queue和Topic消息提供JmsListenerContainerFactory

  新建一个配置类,如下

@SpringBootConfiguration
public class ActiveMqConfig { @Bean("queueListenerFactory")
public JmsListenerContainerFactory<?> queueListenerFactory(ConnectionFactory connectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
//设置消息模型为队列
factory.setPubSubDomain(false);
return factory;
} @Bean("topicListenerFactory")
public JmsListenerContainerFactory topicListenerFactory(ConnectionFactory connectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
//设置消息模型为队列
factory.setPubSubDomain(true);
return factory;
}
}

  在容器启动时会针对两种消息类型,初始化得到两个不同的JmsListenerContainerFactory。下来再修改消费者类,在 @JmsListener 注解中指定 containerFactory,如

@JmsListener(destination = "zyQueue", containerFactory = "queueListenerFactory")
public void receiveMessage(String text){
System.out.println("接收队列消息时间:"+ df.format(new Date()) +", 接收到消息内容:"+text);
} @JmsListener(destination = "zyTopic", containerFactory = "topicListenerFactory")
public void receiveTopicMessage1(String text){
System.out.println("消费者1接收消息时间:"+ df.format(new Date()) +", 接收到消息内容:"+text);
}

  Queue消息使用 queueListenerFactory,Topic消息使用 topicListenerFactory,然后注释掉属性文件中的消息模式配置就可以了。

SpringBoot入门 (九) MQ使用的更多相关文章

  1. SpringBoot入门基础

    目录 SpringBoot入门 (一) HelloWorld. 2 一 什么是springboot 1 二 入门实例... 1 SpringBoot入门 (二) 属性文件读取... 16 一 自定义属 ...

  2. SpringBoot入门及深入

    一:SpringBoot简介 当前互联网后端开发中,JavaEE占据了主导地位.对JavaEE开发,首选框架是Spring框架.在传统的Spring开发中,需要使用大量的与业务无关的XML配置才能使S ...

  3. SpringBoot入门教程(二)CentOS部署SpringBoot项目从0到1

    在之前的博文<详解intellij idea搭建SpringBoot>介绍了idea搭建SpringBoot的详细过程, 并在<CentOS安装Tomcat>中介绍了Tomca ...

  4. 网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

    1.前言 标题虽然是为了解释有了 IP 地址,为什么还要用 MAC 地址,但是本文的重点在于理解为什么要有 IP 这样的东西.本文对读者的定位是知道 MAC 地址是什么,IP 地址是什么. (本文同步 ...

  5. SpringBoot入门示例

    SpringBoot入门Demo SpringBoot可以说是Spring的简化版.配置简单.使用方便.主要有以下几种特点: 创建独立的Spring应用程序 嵌入的Tomcat,无需部署WAR文件 简 ...

  6. Spring全家桶系列–[SpringBoot入门到跑路]

    //本文作者:cuifuan Spring全家桶————[SpringBoot入门到跑路] 对于之前的Spring框架的使用,各种配置文件XML.properties一旦出错之后错误难寻,这也是为什么 ...

  7. C#基础入门 九

    C#基础入门 九 集合 对于很多应用程序,需要创建和管理相关对象组,有两种方式可以将对象分组,一是创建对象数组,如 object[] obj=new object[3]{1,2.33,"st ...

  8. cesium编程入门(九)实体 Entity

    cesium编程入门(九)实体 Entity 在cesium编程入门(五)绘制形状提到过添加实体的方法,这一节聊一聊实体相关的一些内容: 先来看 Entity 的各个属性 id 唯一标志,如果没设置, ...

  9. springboot入门之一:环境搭建(续)

    在上篇博客中从springboot的入门到运行一个springboot项目进行了简单讲述,详情请查看“springboot入门之一”.下面继续对springboot做讲述. 开发springboot测 ...

随机推荐

  1. spring父子Ioc容器的关系

    在网上找了一下,没有直接解说ioc父子容器关系的文章,所以大概看了下代码,自己写下吧,写俩行做个笔记. 1. 在进行dean的注册的时候,父容器和子容器是互不干扰的,各自注册自己的 2. 在实例化的时 ...

  2. Lombok自定义annotation扩展含Intellij插件

    Lombok简介 Lombok(https://projectlombok.org/)  提供了以注解的形式为java对象增加属性和方法,这使得原来冗长的java源文件变的简洁(不需要再使用ide去生 ...

  3. vue.js入门学习

    可以用淘宝npm镜像 然后安装 然后初始化项目: Watch就是一个监听 v-if是如果为false就根本不在页面存在这个元素 v-show是通过display:none来控制这个元素的显示和隐藏 r ...

  4. 主题模型之潜在语义分析(Latent Semantic Analysis)

    主题模型(Topic Models)是一套试图在大量文档中发现潜在主题结构的机器学习模型,主题模型通过分析文本中的词来发现文档中的主题.主题之间的联系方式和主题的发展.通过主题模型可以使我们组织和总结 ...

  5. hdu 5072 两两(不)互质个数逆向+容斥

    http://acm.hdu.edu.cn/showproblem.php?pid=5072 求n个不同的数(<=1e5)中有多少组三元组(a, b, c)两两不互质或者两两互质. 逆向求解,把 ...

  6. Android x86模拟器Intel Atom x86 System Image配置与使用方法

    Android x86模拟器Intel Atom x86 System Image配置与使用方法      前言:      大家现在开发使用的Android 模拟器模拟的是 ARM 的体系结构(ar ...

  7. 让你的照片更鲜艳------hsv拉伸

    如果你的照片看上去灰蒙蒙的,缺少生机,那么hsv拉伸也许可以帮你的忙.hsv拉伸是一种可以提高图像鲜艳程度的图像增强方法,它能够让图像的颜色更加鲜活.艳丽,而且它的处理结果看上去很自然,比如源图中较暗 ...

  8. iTerm2连接远程-中文乱码问题

    现象 mac 上用是iterm2终端, Shell 环境是zsh. ssh 到Linux 服务器上查看一些文件时,中文乱码. 
这种情况一般是终端和服务器的字符集不匹配,MacOSX下默认的是utf8 ...

  9. 【系统架构】亿级Web系统搭建(1):Web负载均衡

    当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题.为了解决这些性能压力带来问题,我们需要通过搭建不同的服务 ...

  10. 25_re模块

    一.re模块的核心功能       1.findall —— 查找所有,返回list lst = re.findall("m", "mai le fo len, mai ...