SpringBoot 2.x (13):整合ActiveMQ
ActiveMQ5.x不多做介绍了,主要是SpringBoot的整合
特点:
1)支持来自Java,C,C ++,C#,Ruby,Perl,Python,PHP的各种跨语言客户端和协议
2)支持许多高级功能,如消息组,虚拟目标,通配符和复合目标
3) 完全支持JMS 1.1和J2EE 1.4,支持瞬态,持久,事务和XA消息
4) Spring支持,ActiveMQ可以轻松嵌入到Spring应用程序中,并使用Spring的XML配置机制进行配置
5) 支持在流行的J2EE服务器(如TomEE,Geronimo,JBoss,GlassFish和WebLogic)中进行测试
6) 使用JDBC和高性能日志支持非常快速的持久化
下载:
http://activemq.apache.org/activemq-5153-release.html
实际开发推荐部署到Linux系统,具体操作网上也有教程
我这里为了方便,直接安装在本地Windows机器上
如果想了解更多,查看官方文档:
http://activemq.apache.org/getting-started.html
进入bin目录win64目录启动activemq.bat即可
访问localhost:8161进入首页
访问http://localhost:8161/admin/进入管理页面,默认用户名和密码都是admin
整合:
依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency>
连接池
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-pool</artifactId> </dependency>
基本的配置
# ActiveMQ spring.activemq.broker-url=tcp://127.0.0.1:61616 spring.activemq.user=admin spring.activemq.password=admin spring.activemq.pool.enabled=true spring.activemq.pool.max-connections=100
使用ActiveMQ必须要在SpringBoot启动类中开启JMS,并进行配置
package org.dreamtech.avtivemq; import javax.jms.ConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.core.env.Environment; import org.springframework.jms.annotation.EnableJms; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.jms.core.JmsTemplate; @SpringBootApplication @EnableJms public class AvtivemqApplication { public static void main(String[] args) { SpringApplication.run(AvtivemqApplication.class, args); } @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; } @Bean public JmsTemplate genJmsTemplate() { return new JmsTemplate(connectionFactory()); } @Bean public JmsMessagingTemplate jmsMessageTemplate() { return new JmsMessagingTemplate(connectionFactory()); } }
点对点模型:
首先实现消息的发送
package org.dreamtech.avtivemq.service; import javax.jms.Destination; /** * 消息生产 * * @author Xu Yiqing * */ public interface ProducerService { /** * 使用指定消息队列发送 * * @param destination * @param message */ void sendMsg(Destination destination, final String message); }
package org.dreamtech.avtivemq.service.impl; import javax.jms.Destination; import org.dreamtech.avtivemq.service.ProducerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.stereotype.Service; @Service public class ProducerServiceImpl implements ProducerService { @Autowired private JmsMessagingTemplate jmsTemplate; @Override public void sendMsg(Destination destination, String message) { jmsTemplate.convertAndSend(destination, message); } }
package org.dreamtech.avtivemq.controller; import javax.jms.Destination; import org.apache.activemq.command.ActiveMQQueue; import org.dreamtech.avtivemq.service.ProducerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class OrderController { @Autowired private ProducerService producerService; @GetMapping("/order") private Object order(String msg) { Destination destination = new ActiveMQQueue("order.queue"); producerService.sendMsg(destination,msg); return "order"; } }
访问:http://localhost:8080/order?msg=demo,然后查看ActiveMQ界面:
有生产者就就有消费者:监听消息队列
package org.dreamtech.avtivemq.jms; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class OrderConsumer { /** * 监听指定消息队列 * * @param text */ @JmsListener(destination = "order.queue") public void receiveQueue(String text) { System.out.println("[ OrderConsumer收到的报文 : " + text + " ]"); } }
由于实时监听,一启动SpringBoot就会打印:
[ OrderConsumer收到的报文 : demo ]
发布订阅模型:比如抖音小视频,某网红发布新视频,多名粉丝收到消息
默认ActiveMQ只支持点对点模型,想要开启发布订阅模型,需要进行配置
spring.jms.pub-sub-domain=true
Spring管理主题对象
@Bean public Topic topic() { return new ActiveMQTopic("demo.topic"); }
发布者
/** * 消息发布者 * * @param msg */ void publish(String msg);
@Autowired private JmsMessagingTemplate jmsTemplate; @Autowired private Topic topic; @Override public void publish(String msg) { jmsTemplate.convertAndSend(topic, msg); }
@Autowired private ProducerService producerService; @GetMapping("/topic") private Object topic(String msg) { producerService.publish(msg); return "success"; }
订阅者(消费者):一人发布,多人订阅
package org.dreamtech.avtivemq.jms; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class TopicConsumer { @JmsListener(destination = "demo.topic") public void receiver1(String text) { System.out.println("TopicConsumer : receiver1 : " + text); } @JmsListener(destination = "demo.topic") public void receiver2(String text) { System.out.println("TopicConsumer : receiver2 : " + text); } @JmsListener(destination = "demo.topic") public void receiver3(String text) { System.out.println("TopicConsumer : receiver3 : " + text); } }
启动项目,访问:
http://localhost:8080/topic?msg=666
打印如下
TopicConsumer : receiver1 : 666 TopicConsumer : receiver3 : 666 TopicConsumer : receiver2 : 666
那么点对点和发布订阅模型可以一起使用吗?
不可以
如何配置?
1.注释掉 #spring.jms.pub-sub-domain=true
2.加入Bean:给topic定义独立的JmsListenerContainer
@Bean public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) { DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory(); bean.setPubSubDomain(true); bean.setConnectionFactory(activeMQConnectionFactory); return bean; }
3.@JmsListener如果不指定独立的containerFactory的话是只能消费queue消息
@JmsListener(destination = "demo.topic", containerFactory = "jmsListenerContainerTopic") public void receiver1(String text) { System.out.println("TopicConsumer : receiver1 : " + text); }