Springboot整合Active消息队列

简单理解:

Active是Apache公司旗下的一个消息总线,ActiveMQ是一个开源兼容Java Message Service(JMS) 面向消息的中件间. 是一个提供松耦合的应用程序架构.

主要用来在服务与服务之间进行异步通信的。

一、搭建步骤

    1、相应jar包

 <!-- 整合消息队列ActiveMQ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency> <!-- 如果配置线程池则加入 -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>

    2、application.properties文件

#整合jms测试,安装在别的机器,防火墙和端口号记得开放
spring.activemq.broker-url=tcp://47.96.44.110:61616 spring.activemq.user=admin
spring.activemq.password=admin
#下列配置要增加依赖
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=100 #集群配置(后续需要在配上)
#spring.activemq.broker-url=failover:(tcp://localhost:61616,tcp://localhost:61617)
#消息队列默认是点对点的,如果需要发布/订阅模式那么需要加上下面注解(如果同时需要点对点发布订阅这里也需注释掉)
# spring.jms.pub-sub-domain=true

 3、Springboot主类

<!-- 主类需要多加一个@EnableJms注解,不过貌似我没有加的时候,也能运行,为安全起见姑且加上 -->
@SpringBootApplication
@EnableJms

4.5.......根据不同消息模式来写了。

二、点对点案例

我在这里案例中创建了两个点对点队列,所以他会有两个queue对象,同样对应每个queue对象,都会有单一对应的消费者。

      1、Springboot主类

@SpringBootApplication
@EnableJms
public class Main { public static void main(String[] args) {
SpringApplication.run(Main.class, args);
} //新建一个的Queue对象,交给sringboot管理,这个queue的名称叫"first.queue".
@Bean
public Queue queue(){
return new ActiveMQQueue("first.queue");
}
}

      2.1、first.queue对应消费者

@Component
public class FirstConsumer { //名为"first.queue"消息队列的消费者,通过JmsListener进行监听有没有消息,有消息会立刻读取过来
@JmsListener(destination="first.queue")
public void receiveQueue(String text){
System.out.println("FirstConsumer收到的报文为:"+text);
}
}

       2.2、two.queue对应消费者(后面会创建)

@Component
public class TwoConsumer { //名为"two.queue"消息队列的消费者
@JmsListener(destination="two.queue")
public void receiveQueue(String text){
System.out.println("TwoConsumer收到的报文为:"+text);
}
}

      3、Service类

   /**
* 功能描述:消息生产
*/
public interface ProducerService { // 功能描述:指定消息队列,还有消息
public void sendMessage(Destination destination, final String message); // 功能描述:使用默认消息队列, 发送消息
public void sendMessage( final String message); }

      4、ServiceImpl实现类

/**
* 功能描述:消息生产者实现类
*/
@Service
public class ProducerServiceImpl implements ProducerService{ //这个队列就是Springboot主类中bean的对象
@Autowired
private Queue queue; //用来发送消息到broker的对象,可以理解连接数据库的JDBC
@Autowired
private JmsMessagingTemplate jmsTemplate; //发送消息,destination是发送到的队列,message是待发送的消息
@Override
public void sendMessage(Destination destination, String message) {
jmsTemplate.convertAndSend(destination, message);
} //发送消息,queue是发送到的队列,message是待发送的消息
@Override
public void sendMessage(final String message) {
jmsTemplate.convertAndSend(this.queue, message);
}
}

     5.QueueController类

/**
* 功能描述:点对点消息队列控制层
*/
@RestController
@RequestMapping("/api/v1")
public class QueueController { @Autowired
private ProducerService producerService; // 这里后面调用的是Springboot主类的quene队列
@GetMapping("first")
public Object common(String msg){
producerService.sendMessage(msg);
return "Success";
} // 这个队列是新建的一个名为two.queue的点对点消息队列
@GetMapping("two")
public Object order(String msg){ Destination destination = new ActiveMQQueue("two.queue");
producerService.sendMessage(destination, msg); return "Success";
}
}

      6、案例演示:

从演示效果可以得出以下结论:

     1:当springboot启动时候,就生成了这两个队列,而且他们都会有一个消费者

2:当我通过页面访问的时候,就相当于生产者把消息放到队列中,一旦放进去就会被消费者监听到,就可以获取生产者放进去的值并在后台打印出

顺便对页面中四个单词进行解释:

   Number Of Pending Messages :待处理消息的数量。我们每次都会被监听处理掉,所以不存在待处理,如果存在就说这里面哪里出故障了,需要排查

   Number Of Consumers : 消费者数量

   Messages Enqueued:    消息排列,这个只增不见,代表已经处理多少消息

   Messages Dequeued:    消息出队。

     

三、发布/订阅者模式

在上面点对点代码的基础上,添加发布/订阅相关代码

     1.appliaction.properties文件

#消息队列默认是点对点的,如果需要发布/订阅模式那么需要加上下面注解(如果同时需要点对点发布订阅这里也需注释掉)
spring.jms.pub-sub-domain=true

      2.Springboot主类添加

//新建一个topic队列
@Bean
public Topic topic(){
return new ActiveMQTopic("video.topic");
}

       3.添加多个消费者类

//这里定义了三个消费者
@Component
public class TopicSub { @JmsListener(destination="video.topic")
public void receive1(String text){
System.out.println("video.topic 消费者:receive1="+text);
} @JmsListener(destination="video.topic")
public void receive2(String text){
System.out.println("video.topic 消费者:receive2="+text);
} @JmsListener(destination="video.topic")
public void receive3(String text){
System.out.println("video.topic 消费者:receive3="+text);
}
}

       4.Service类

 //功能描述:消息发布者
public void publish(String msg);

      5.ServiceImpl实现类

//=======发布订阅相关代码=========

        @Autowired
private Topic topic; @Override
public void publish(String msg) {
this.jmsTemplate.convertAndSend(this.topic, msg); }

       6.Controller类

// 这个队列是新建的一个名为two.queue的点对点消息队列
@GetMapping("topic")
public Object topic(String msg){ producerService.publish(msg); return "Success";
}

      7.演示效果:

从演示效果总结如下:

1:Springboot启动的时候,在Topics目录下,一共出现了5个消费者。first.queue一个消费者、two.queue一个消费者、video.topic三个消费者

2:当我在控制台输入信息后,video.topic的三个消费者都会监听video.topic发布的消息,并在控制台打印。

四、如何让点对点和发布订阅同时有效

为什么这么说呢,因为当我向上面一样同时开启,会发现点对点模式已经失效了。

 效果演示

从演示效果,可以得出如下结论:

1:我们发现我们在页面输入..../two?msg=555消息后,后台并没有成功打印消息。再看Active界面发现,这个queue对象,确实有一条待处理的消息,但是我们发现,它对应的消费者数量是为0.

2:然而我们在打开topic页面发现,这里却存在一个消费者。

所以我个人理解是,当同时启动的时候,所产生的消费者默认都是Topic消费者,没有Queue消费者,所以它监听不到queue所待处理的消息。

当配置文件不加:spring.jms.pub-sub-domain=true  那么系统会默认支持quene(点对点模式),但一旦加上这段配置,系统又变成只支持发布订阅模式。

那如何同时都可以成功呢?

思路如下:

第一步:还是需要去掉配置文件中的:

#消息队列默认是点对点的,如果需要发布/订阅模式那么需要加上下面注解(如果同时需要点对点发布订阅这里也需注释掉)
#spring.jms.pub-sub-domain=true

第二步:在发布订阅者的中消费者中指定独立的containerFactory

因为你去掉上面的配置,那么系统就默认是queue,所以@JmsListener如果不指定独立的containerFactory的话是只能消费queue消息

    @JmsListener(destination="video.topic", containerFactory="jmsListenerContainerTopic")
public void receive1(String text){
System.out.println("video.topic 消费者:receive1="+text);
} @JmsListener(destination="video.topic", containerFactory="jmsListenerContainerTopic")
public void receive2(String text){
System.out.println("video.topic 消费者:receive2="+text);
} //第三步我不添加containerFactory="jmsListenerContainerTopic"看等下是否会打印出
@JmsListener(destination="video.topic")
public void receive3(String text){
System.out.println("video.topic 消费者:receive3="+text);
}

第三步:定义独立的topic定义独立的JmsListenerContainer

在springboot主类中添加:

        @Bean
public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setPubSubDomain(true);
bean.setConnectionFactory(activeMQConnectionFactory);
return bean;
}

效果:

得出结论:

1:点对点,和发布订阅都有用

2:receive3没有指定独立的containerFactory一样没有打印出来。

源码

github地址:https://github.com/yudiandemingzi/springbootAcitveMQ

想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。上尉【14】

springBoot(11)---整合Active消息队列的更多相关文章

  1. SpringBoot非官方教程 | 第十四篇:在springboot中用redis实现消息队列

    转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot14-redis-mq/ 本文出自方志朋的博客 这 ...

  2. SpringBoot(八) Spring和消息队列RabbitMQ

    概述 1.大多数应用中,可以通过消息服务中间件来提升系统异步能力和拓展解耦能力. 2.消息服务中的两个重要概念:消息代理(Message broker)和目的地(destination) 当消息发送者 ...

  3. 实战Spring4+ActiveMQ整合实现消息队列(生产者+消费者)

    引言: 最近公司做了一个以信息安全为主的项目,其中有一个业务需求就是,项目定时监控操作用户的行为,对于一些违规操作严重的行为,以发送邮件(ForMail)的形式进行邮件告警,可能是多人,也可能是一个人 ...

  4. Spring整合ActiveMq消息队列

    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久 ...

  5. Kafka:Springboot整合Kafka消息队列

    本文主要分享下Spring Boot和Spring Kafka如何配置整合,实现发送和接收来自Spring Kafka的消息. 项目结构 pom依赖包 <?xml version="1 ...

  6. 在springboot中用redis实现消息队列

    环境依赖 创建一个新的springboot工程,在其pom文件,加入spring-boot-starter-data-redis依赖: <dependency> <groupId&g ...

  7. Spring Boot教程(一)在springboot中用redis实现消息队列

    环境依赖 创建一个新的springboot工程,在其pom文件,加入spring-boot-starter-data-redis依赖: <dependency> <groupId&g ...

  8. SpringBoot 集成Apache Kafak 消息队列

    Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性,但是在实现上完全不同,此外它并不是JMS规范 ...

  9. SpringBoot RedisMQ消息队列与发布订阅

    SpringBoot简单整合RedisMQ消息队列和发布订阅 注:RedisMq消息队列使用redis数组实现,leftpush存一,rightpop取一. 1.application.propert ...

随机推荐

  1. gperftools对程序进行分析

    gperftools是google出品的一个性能分析工具,相关介绍可见:https://github.com/gperftools/gperftools/wikigperftools性能分析通过抽样方 ...

  2. android shape 怎么在底部画横线

    使用layer-list可以,画了两层 1 2 3 4 5 6 7 8 9         <layer-list>             <!-- This is the lin ...

  3. 201771010142 张燕& 杨蓉庆 实验十一 集合

    实验十一   集合 实验时间 2018-11-8 一  理论知识 一般将数据结构分为两大类:线性数据结构和非线性数据结构.线性数据结构:线性表.栈.队列.串.数组和文件.非线性数据结构:树和图. 线性 ...

  4. web安全系列1:入侵的途径

    大家好,接下来的很长一段时间我都会介绍和web安全有关的知识,欢迎大家关注和转发. 话不多说,我们首先来看看今天的主题----入侵的途径.当然,今天介绍的都是针对web网站的常用手法和技巧. 不可否认 ...

  5. rem 是如何实现自适应布局的

    摘要:rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个px字号,则可以来算出元素的宽高.本文讲的是如何使用rem实现自适应.· rem这是个低调的css单位,近一 ...

  6. 记一次需要用到复杂的groupingBy的需求

    一:先定义结构 public class Foo { private Integer id; private String name; private BigDecimal amount; publi ...

  7. ASP.NET获取POST提交过来的数据流,转换成Json格式的字符串

    public class Public { private static Public _instance = new Public(); /// <summary> /// 全局访问点 ...

  8. Python字符串格式化--format()方法

    https://blog.csdn.net/i_chaoren/article/details/77922939       csdn

  9. nginx的锁

    一.原理 nginx的锁是基于共享内存实现的,这点跟redis中利用一个存储(也就是一个键值对)来实现锁的原理是一致的,每一项操作通过检查锁对象的lock域是否为0,来判断能否获取锁并尝试获取锁. 二 ...

  10. 基于面向方面和UML的实时系统建模研究

    一.基本信息 标题:基于面向方面和UML的实时系统建模研究 时间:2010 出版源:计算机技术与发展 领域分类:面向方向:实时系统:横切关注点:统一建模语言: 二.研究背景 问题定义:实时系统建模研究 ...