研究一下訊息佇列,現在來簡單搭建一下。
1. Docker搭建RabbitMQ
1.1 查詢並下載RabbitMQ映象
docker search rabbitmq
// 選擇可以訪問web管理介面的tag
docker pull rabbitmq:management
1.2 執行RabbitMQ映象
// 設定賬號密碼都為admin
docker run -dit --name myrabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:management
1.3 瀏覽器上訪問 伺服器IP:15672
出現以下頁面表示啟動成功
2. 搭建SpringBoot專案整合RabbitMQ
2.1 pom.xml
新增web和rabbitmq的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
2.2 aplication.yml
將rabbitmq的地址使用者名稱密碼等配置上
spring:
rabbitmq:
host: localhost
port: 5672
username: admin
password: admin
2.3 新建交換機SenderConfig.java
有以下三種常用的交換機,我們這裡使用第三種
DirectExchange
直連型交換機,根據訊息攜帶的路由鍵,將訊息轉發給對應的佇列
FanoutExchange
扇形交換機,接收到訊息後會將訊息轉發到所有佇列
TopicExchange
主題交換機,根據訊息攜帶的路由鍵和交換機與佇列繫結鍵的規則,將訊息轉發給對應的佇列
規則:
*(星號):表示一個字元必須出現
#(井號):表示任意數量的字元
/**
* 交換機
* @author zhouzhaodong
*/
@Configuration
public class SenderConfig {
/**
* ----- 交換機 -----
* 引數意義:
* name: 名稱
* durable: 持久化
* autoDelete: 自動刪除
*/
@Bean
public TopicExchange topicExchange() {
return new TopicExchange("topicExchange", true, false);
}
/**
* ----- 佇列 -----
*/
@Bean
public Queue queueOne() {
return new Queue("queueOne", true);
}
@Bean
public Queue queueTwo() {
return new Queue("queueTwo", true);
}
@Bean
public Queue queueThree() {
return new Queue("queueThree", true);
}
/**
* ----- 繫結 -----
* routingKey就是路由規則,訊息對應的佇列,用來區分不同的訊息佇列
*/
@Bean
public Binding bindingFanoutOne() {
return BindingBuilder.bind(queueOne()).to(topicExchange()).with("topic_one");
}
@Bean
public Binding bindingFanoutTwo() {
return BindingBuilder.bind(queueTwo()).to(topicExchange()).with("topic_two");
}
@Bean
public Binding bindingFanoutThree() {
return BindingBuilder.bind(queueThree()).to(topicExchange()).with("topic_one");
}
}
2.4 傳送者 SenderController.java
/**
* 訊息傳送者
*
* @author zhouzhaodong
*/
@RestController
public class SenderController {
@Resource
AmqpTemplate amqpTemplate;
Logger logger = LoggerFactory.getLogger(SenderController.class);
@RequestMapping(value = "/send")
public String sendMessage(String message) {
logger.info("訊息傳送開始時間:" + new Date());
// 這裡convertAndSend第一個引數是交換機的名稱
// 第二個引數可以是routingKey
// 最後一個引數就是要傳送的訊息
amqpTemplate.convertAndSend("topicExchange", "topic_one", message);
return "傳送成功";
}
}
2.5 消費者 ReceiverController.java
/**
* 消費者
* @author zhouzhaodong
*/
@Component
public class ReceiverController {
Logger logger = LoggerFactory.getLogger(ReceiverController.class);
@RabbitHandler
@RabbitListener(queues = "queueOne")
public void processA(String message){
logger.info("queueOne接收訊息時間為:" + new Date());
logger.info("queueOne接收訊息為:" + message);
}
@RabbitHandler
@RabbitListener(queues = "queueTwo")
public void processB(String message){
logger.info("queueTwo接收訊息時間為:" + new Date());
logger.info("queueTwo接收訊息為:" + message);
}
@RabbitHandler
@RabbitListener(queues = "queueThree")
public void processC(String message){
logger.info("queueThree接收訊息時間為:" + new Date());
logger.info("queueThree接收訊息為:" + message);
}
}
3. 啟動專案進行測試
3.1 呼叫生產者介面
發現有兩個佇列收到了訊息,因為這兩個佇列都配置的routingKey相同,都是topic_one
3.2 不帶routingKey進行訪問
發現並沒有佇列收到訊息
測試結束