序言
ActiveMQ是Apache所提供的一个开源的消息系统,完全采用Java来实现,因此,它能很好地支持J2EE提出的JMS(Java Message Service,即Java消息服务)规范。JMS是一组Java应用程序接口,它提供消息的创建、发送、读取等一系列服务,虽然比较老,但是依然可以运用于中小项目的生产环境。
JMS
JMS支持两种消息发送和接收模型。
P2P(Ponit to Point)
即采用点对点的方式发送消息。P2P模型是基于队列的,消息生产者发送消息到队列,消息消费者从队列中接收消息,队列的存在使得消息的异步传输称为可能,P2P模型在点对点的情况下进行消息传递时采用。
Pub/Sub(Publish/Subscribe
发布-订阅模型定义了如何向一个内容节点发布和订阅消息,这个内容节点称为topic(主题)。主题可以认为是消息传递的中介,消息发布这将消息发布到某个主题,而消息订阅者则从主题订阅消息。主题使得消息的订阅者与消息的发布者互相保持独立,不需要进行接触即可保证消息的传递,发布-订阅模型在消息的一对多广播时采用。
使用
怎么在SpringBoot中使用呢?加入如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!-- 连接外部mq-->
<dependency>
<groupId>org.messaginghub</groupId>
<artifactId>pooled-jms</artifactId>
</dependency>
默认spring-boot-starter-activemq
会内直一个ActiveMq,咱们这次用外置的,加入pooled-jms
即可。
然后在yml中配置
spring:
activemq:
broker-url: tcp://localhost:61616
close-timeout: 5000
in-memory: false
user: admin
password: 'admin'
pool:
enabled: true
max-connections: 100
send-timeout: 3000
然后呢就是创建队列
@Configuration
@EnableJms
public class ActiveMqConfig {
private static final String QUEUE_NAME = "queueTest";
/**
* 定义存放消息的队列
*
* @return
*/
@Bean
public Queue queueTest() {
return new ActiveMQQueue(QUEUE_NAME);
}
}
在然后spring-boot-starter-activemq
内直了一个 jmsMessagingTemplate
方便我们去发送消息
@RestController
public class SendController {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Queue queueTest;
/**
* 发送消息
*
* @param value
*/
@GetMapping("queue")
public void jmsQueueTemplate(@RequestParam String value) {
jmsMessagingTemplate.convertAndSend(queueTest, value);
}
}
这样发就可以啦 !
然后在创立一个消息的监听者
@Component
@Slf4j
public class QueueReceiver {
@JmsListener(destination = "queueTest")
public void receive(String msg) {
log.info("queueTest queue1 监听到的消息内容为: " + msg);
}
}
其中@JmsListener
标注是一个消息的监听方法,然后destination = "queueTest"
指的就是怎么队列的名字。
那么如何使用消息队列中的发布订阅呢?很简单只需要改一下队列的bean即可
@Configuration
@EnableJms
public class ActiveMqConfig {
private static final String TOPIC_NAME = "topicTest";
//发布订阅队列
@Bean
public Topic topicTest() {
return new ActiveMQTopic(TOPIC_NAME);
}
}
然后在controller里使用即可
@RestController
public class SendController {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Topic topicTest;
/**
* 发送消息
*
* @param value
*/
@GetMapping("topic")
public void jmsTopicTemplate(@RequestParam String value) {
jmsMessagingTemplate.convertAndSend(topicTest, value);
}
}
接收消息的监听也只是改一改队列的名字就行了
@Component
@Slf4j
public class QueueReceiver {
@JmsListener(destination = "topicTest")
public void topicReceive1(String msg) {
log.info("topicTest 1 监听到的消息内容为: " + msg);
}
}
结果就是发送失败,因为SpringBoot默认提供的连接工厂不支持发布订阅,所以要在yml里这样设置一下
spring:
activemq:
broker-url: tcp://localhost:61616
close-timeout: 5000
in-memory: false
password: 'admin'
pool:
enabled: true
max-connections: 100
send-timeout: 3000
user: admin
non-blocking-redelivery: true
jms:
pub-sub-domain: true
但是这样也太不方便了吧。
我两个都想使用怎么办呢?对 我们自己定义一下连接工厂就行了。
首先呢定义两个连接工厂
@Configuration
@EnableJms
public class ActiveMqConfig {
/**
* topic模式的ListenerContainer
*
* @return
*/
@Bean
public JmsListenerContainerFactory<?> topicListenerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
ActiveMQConnectionFactory connectionFactor = new ActiveMQConnectionFactory();
factory.setPubSubDomain(true);
factory.setConnectionFactory(connectionFactor);
return factory;
}
/**
* queue模式的ListenerContainer
*
* @return
*/
@Bean
public JmsListenerContainerFactory<?> queueListenerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
ActiveMQConnectionFactory connectionFactor = new ActiveMQConnectionFactory();
factory.setPubSubDomain(false);
factory.setConnectionFactory(connectionFactor);
return factory;
}
}
其中呢factory.setPubSubDomain(true)
就代表是一个发布订阅的连接工厂,factory.setPubSubDomain(false)
则是默认队列的连接工厂,在监听方法中这样使用即可。
@Component
@Slf4j
public class QueueReceiver {
@JmsListener(destination = "queueTest", containerFactory = "queueListenerFactory")
public void receive2(String msg) {
log.info("queueTest queue2 监听到的消息内容为: " + msg);
}
@JmsListener(destination = "topicTest", containerFactory = "topicListenerFactory")
public void topicReceive1(String msg) {
log.info("topicTest 1 监听到的消息内容为: " + msg);
}
}
此外还有很多细节用法,还是那句话建议大家多去官网看看文档,这才是解决问题和提升自己的关键所在啊。
本博文是基于springboot2.x 如果有什么不对的请在下方留言。