我在上一章節中,給大家介紹了ActiveMQ,本節中我會介紹Spring Boot中如何整合ActiveMQ,實現消息的創建和消費。
一. Spring Boot中整合ActiveMQ
1. 創建web項目
我們按照之前的經驗,創建一個web程序,並將之改造成Spring Boot項目,具體過程略。
2. 添加依賴包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
3. 創建application.yml配置文件
#配置activemq
spring:
activemq:
#activemq的url
broker-url: tcp://127.0.0.1:61616
#用戶名
user: admin
#密碼
password: admin
pool:
enabled: false #是否使用線程池
max-connections: 100 #最大連接數
#是否信任所有包
packages:
trust-all: true
#默認情況下,activemq使用的是queue模式,如果要使用topic模式,必須設置爲true
jms:
pub-sub-domain: true
4. 創建ActiveMQ的配置類
在這個類中創建連接工廠,消息隊列等。
package com.yyg.boot.config;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import javax.jms.Topic;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/14
* @Description Description
* //@EnableJms啓用jms功能
*/
@Configuration
@EnableJms
public class ActivemqConfig {
@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;
}
/**
* 實現監聽queue
*/
@Bean("jmsQueueListenerContainerFactory")
public JmsListenerContainerFactory<?> queueContainerFactory(ConnectionFactory connectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
//開啓接收topic類型的消息
factory.setPubSubDomain(false);
return factory;
}
/**
* 實現監聽topic
*/
@Bean("jmsTopicListenerContainerFactory")
public JmsListenerContainerFactory<?> topicContainerFactory(ConnectionFactory connectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(true);
return factory;
}
/**
* 隊列名稱
*/
@Bean("springboot.queue")
public Queue queue() {
return new ActiveMQQueue("springboot.queue") ;
}
/**
* Topic名稱
*/
@Bean("springboot.topic")
public Topic topic() {
return new ActiveMQTopic("springboot.topic") ;
}
}
5. 創建消息生產者的工具類
在這個Producer類中,創建幾個發送消息的的方法。
package com.yyg.boot.jms;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/15
* @Description 消息生產者
*/
@Slf4j
@Component
public class Producer {
@Resource(name = "springboot.queue")
private Queue queue;
@Resource(name = "springboot.topic")
private Topic topic;
@Resource(name = "springboot.replyQueue")
private Queue replyQueue;
@Autowired
private JmsMessagingTemplate jmsTemplate;
/**
* 發送消息,destination是發送到的目標隊列,message是待發送的消息內容;
*/
public void sendMessage(Destination destination, final String message) {
jmsTemplate.convertAndSend(destination, message);
}
/**
* 發送隊列消息
*/
public void sendQueueMessage(final String message) {
sendMessage(queue, message);
}
/**
* 發送Topic消息
*/
public void sendTopicMessage(final String message) {
sendMessage(topic, message);
}
}
6. 定義消費消息的Consumer類
package com.yyg.boot.jms;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/15
* @Description 消息的消費者
*/
@Slf4j
@Component
public class Consumer {
/**
* 監聽Queue隊列,queue類型
*/
@JmsListener(destination="springboot.queue",
containerFactory = "jmsQueueListenerContainerFactory")
public void receiveQueue(String text){
log.warn(this.getClass().getName()+ "-->收到的報文爲:"+text);
}
/**
* 監聽Topic隊列,topic類型,這裏containerFactory要配置爲jmsTopicListenerContainerFactory
*/
@JmsListener(destination = "springboot.topic",
containerFactory = "jmsTopicListenerContainerFactory")
public void receiveTopic(String text) {
log.warn(this.getClass().getName()+"-->收到的報文爲:"+text);
}
}
7. 創建Controller,發佈消息
package com.yyg.boot.web;
import com.yyg.boot.domain.User;
import com.yyg.boot.jms.Consumer;
import com.yyg.boot.jms.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/15
* @Description Description
*/
@RestController
public class MsgController {
@Autowired
private Producer producer;
@Autowired
private Consumer consumer;
@GetMapping("/sendQueue")
public String sendQueueMsg() {
User user = new User();
user.setId(1L);
user.setUsername("一一哥Queue");
user.setPassword("123");
producer.sendQueueMessage(user.toString());
return "發送成功!";
}
@GetMapping("/sendTopic")
public String sendTopicMsg() {
User user = new User();
user.setId(2L);
user.setUsername("一一哥Topic");
user.setPassword("123456");
producer.sendTopicMessage(user.toString());
return "發送成功!";
}
}
8. 創建入口類
package com.yyg.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ActiveMQApplication {
public static void main(String[] args) {
SpringApplication.run(ActiveMQApplication.class, args);
}
}
9. 完整項目結構
10. 啓動項目進行測試
測試發送點對點類型的消息
隊列中可以看到成功的收到了消息。
在ActiveMQ中也可以看到出現了springboot.queue隊列,並且隊列中的消息已被消費掉。
測試發送發佈者訂閱者類型的消息
Topic中可以看到成功的收到了消息。
在ActiveMQ中也可以看到出現了springboot.topic隊列,並且隊列中的消息已被消費掉。
二. 回覆消息的實現
我們在上面的基礎之上,進一步實現發送消息後,進行消息的回覆。
1. 改造ActiveMQ類
在該類中添加一個用來接收回復消息的隊列。
/**
* 回覆隊列名稱
*/
@Bean("springboot.replyQueue")
public Queue queueReply() {
return new ActiveMQQueue("springboot.replyQueue") ;
}
完整的ActivemqConfig代碼:
package com.yyg.boot.config;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import javax.jms.Topic;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/14
* @Description Description
* //@EnableJms啓用jms功能
*/
@Configuration
@EnableJms
public class ActivemqConfig {
@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;
}
/**
* 實現監聽queue
*/
@Bean("jmsQueueListenerContainerFactory")
public JmsListenerContainerFactory<?> queueContainerFactory(ConnectionFactory connectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
//開啓接收topic類型的消息
factory.setPubSubDomain(false);
return factory;
}
/**
* 實現監聽topic
*/
@Bean("jmsTopicListenerContainerFactory")
public JmsListenerContainerFactory<?> topicContainerFactory(ConnectionFactory connectionFactory){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(true);
return factory;
}
/**
* 隊列名稱
*/
@Bean("springboot.queue")
public Queue queue() {
return new ActiveMQQueue("springboot.queue") ;
}
/**
* Topic名稱
*/
@Bean("springboot.topic")
public Topic topic() {
return new ActiveMQTopic("springboot.topic") ;
}
/**
* 回覆隊列名稱
*/
@Bean("springboot.replyQueue")
public Queue queueReply() {
return new ActiveMQQueue("springboot.replyQueue") ;
}
}
2. 改造Producer類
在Producer類中定義一個新的Queue類,並定義發送消息和消費消息的方法。
@Resource(name = "springboot.replyQueue")
private Queue replyQueue;
/**
* 發送隊列的回覆消息
*/
public void sendQueueMessageReply(String message) {
sendMessage(replyQueue, message);
}
/**
* 生產者監聽消費者的應答信息
*/
@JmsListener(destination = "replyTo.queue",containerFactory = "jmsQueueListenerContainerFactory")
public void consumerMessage(final String text) {
log.warn("從replyTo.queue隊列中收到的應答報文爲:" + text);
}
完整的Producer類代碼:
package com.yyg.boot.jms;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/15
* @Description 消息生產者
*/
@Slf4j
@Component
public class Producer {
@Resource(name = "springboot.queue")
private Queue queue;
@Resource(name = "springboot.topic")
private Topic topic;
@Resource(name = "springboot.replyQueue")
private Queue replyQueue;
@Autowired
private JmsMessagingTemplate jmsTemplate;
/**
* 發送消息,destination是發送到的目標隊列,message是待發送的消息內容;
*/
public void sendMessage(Destination destination, final String message) {
jmsTemplate.convertAndSend(destination, message);
}
/**
* 發送隊列消息
*/
public void sendQueueMessage(final String message) {
sendMessage(queue, message);
}
/**
* 發送Topic消息
*/
public void sendTopicMessage(final String message) {
sendMessage(topic, message);
}
/**
* 發送隊列的回覆消息
*/
public void sendQueueMessageReply(String message) {
sendMessage(replyQueue, message);
}
/**
* 生產者監聽消費者的應答信息
*/
@JmsListener(destination = "replyTo.queue",containerFactory = "jmsQueueListenerContainerFactory")
public void consumerMessage(final String text) {
log.warn("從replyTo.queue隊列中收到的應答報文爲:" + text);
}
}
3. 改造Consumer類
在該類中添加接收消息,並且設置回覆消息的方法。
/**
* 回覆給生產者的應答信息
*/
@JmsListener(destination="springboot.replyQueue",containerFactory = "jmsQueueListenerContainerFactory")
@SendTo("replyTo.queue") //消費者應答後通知生產者
public String receiveQueueReply(String text){
log.warn(this.getClass().getName()+ "-->收到的報文爲:"+text);
return "回覆的信息爲-->"+text;
}
完整的Consumer類代碼:
package com.yyg.boot.jms;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;
/**
* @Author 一一哥Sun
* @Date Created in 2020/4/15
* @Description 消息的消費者
*/
@Slf4j
@Component
public class Consumer {
/**
* 監聽Queue隊列,queue類型
*/
@JmsListener(destination="springboot.queue",
containerFactory = "jmsQueueListenerContainerFactory")
public void receiveQueue(String text){
log.warn(this.getClass().getName()+ "-->收到的報文爲:"+text);
}
/**
* 監聽Topic隊列,topic類型,這裏containerFactory要配置爲jmsTopicListenerContainerFactory
*/
@JmsListener(destination = "springboot.topic",
containerFactory = "jmsTopicListenerContainerFactory")
public void receiveTopic(String text) {
log.warn(this.getClass().getName()+"-->收到的報文爲:"+text);
}
/**
* 回覆給生產者的應答信息
*/
@JmsListener(destination="springboot.replyQueue",containerFactory = "jmsQueueListenerContainerFactory")
@SendTo("replyTo.queue") //消費者應答後通知生產者
public String receiveQueueReply(String text){
log.warn(this.getClass().getName()+ "-->收到的報文爲:"+text);
return "回覆的信息爲-->"+text;
}
}
4. 重新運行,測試消息的回覆功能
調用如下接口,測試消息回覆功能。
此時可以看到控制檯輸出如下信息,說明消息回覆成功。
至此,我們實現了Spring boot中如何整合ActiveMQ。