前言
选择Apache ActiveMQ 主要是因为,是一个完全使用Java开发的消息中间件。与Java的Java Message Service 服务可以无缝衔接。并且支持多协议,包括:OpenWire、REST、STOMP、WS-Notification、MQTT、XMPP以及AMQP。
当然性能上和集群使用上,无法和kafka、RabbitMQ等近几年比较火的消息中间件相比。但是,够用就好。
文章目录
- 前言
- Docker 部署 ActiveMQ
- 下载镜像
- 镜像协议端口
- 启动容器服务
- Spring Boot
- 添加依赖
- application.yml 配置
- 消息队列发布
- 消息广播发布
- 消费队列消息
- 消费广播消息
- 问题
- 增加ActiveMQConfiguration
- 消息消费
Docker 部署 ActiveMQ
下载镜像
$ sudo docker pull rmohr/activemq
镜像协议端口
在以下端口开放了针对不同协议的
61616 JMS
8161 UI
5672 AMQP (since `rmohr/activemq:5.12.1`)
61613 STOMP (since `rmohr/activemq:5.12.1`)
1883 MQTT (since `rmohr/activemq:5.12.1`)
61614 WS (since `rmohr/activemq:5.12.1`)
启动容器服务
$ sudo docker run -p 61616:61616 -p 8161:8161 rmohr/activemq
仅映射了 61616 和 8161 端口,需要其他协议方式的,可以自行增加映射
Spring Boot
添加依赖
gradle 为例
dependencies {
...
compile('org.springframework.boot:spring-boot-starter-activemq')
compile('org.apache.activemq:activemq-pool')
...
}
application.yml 配置
spring:
activemq:
brokerUrl: tcp://localhost:61616 //JMS 服务
pool:
enabled: true
消息队列发布
message 类型可以是 String 、 Map<String,String>、List<String>、序列化对象
@Component
class JMSProducer {
@Autowired
private lateinit var jmsMessage: JmsMessagingTemplate
fun sendMessage(destination : String , message:String) {
jmsTemplate.convertAndSend(ActiveMQQueue(destination),message)
}
}
消息广播发布
message 类型可以是 String 、 Map<String,String>、List<String>、序列化对象
@Component
class JMSProducer {
@Autowired
private lateinit var jmsMessage: JmsMessagingTemplate
fun sendMessage(destination : String , message:String) {
jmsTemplate.convertAndSend(ActiveMQTopic(destination),message);
}
}
消费队列消息
@Component
public class JMSConsumer {
private val logger = LoggerFactory.getLogger(JMSConsumer.java.class);
@JmsListener(destination = "springboot.queue.test") // 与发布者destination 一致
fun receiveQueue(msg:String) {
logger.info("接收到消息:{}",msg);
}
}
消费广播消息
默认只能发送和接收queue消息,如果要发送和接收topic消息,需要在application.yml文件中加入:
spring:
jms:
pub-sub-domain: true
接收代码仍旧是该方式接受
@Component
class JMSConsumer {
private val logger = LoggerFactory.getLogger(JMSConsumer.java.class);
@JmsListener(destination = "springboot.queue.test") // 与发布者destination 一致
fun receiveQueue(msg:String) {
logger.info("接收到消息:{}",msg);
}
}
问题
其实从上面就发现了问题,就是要么只能消费队列消息、要么只能消费广播消息,那么如何能够同时在一个程序中同时处理队列消息和广播消息呢?
增加ActiveMQConfiguration
@Configuration
public class ActiveMQConfiguration {
/**
* 在Queue模式中,对消息的监听需要对containerFactory进行配置
*/
@Bean("QueueComsumer")
fun queueJmsListenerContainerFactory(connectionFactory:ConnectionFactory):JmsListenerContainerFactory<?> {
val factory = SimpleJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(false);
return factory;
}
/**
* 在Topic模式中,对消息的监听需要对containerFactory进行配置
*/
@Bean("TopicComsumer")
fun topicJmsListenerContainerFactory(connectionFactory:ConnectionFactory):JmsListenerContainerFactory<?> {
val factory = SimpleJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(true);
return factory;
}
}
消息消费
@Component
class JMSConsumer {
private val logger = LoggerFactory.getLogger(JMSConsumer.java.class);
@JmsListener(destination = "springboot.queue.test",containerFactory = "QueueComsumer") // 与发布者destination 一致
fun receiveQueue( msg:String) {
logger.info("接收到消息:{}",msg);
}
@JmsListener(destination = "springboot.queue.test",containerFactory = "TopicComsumer") // 与发布者destination 一致
fun receiveTopic(msg:String) {
logger.info("接收到消息:{}",msg);
}
}