我們?cè)谥暗膬蓚€(gè)章節(jié)第四十一章: 基于SpringBoot & RabbitMQ完成DirectExchange分布式消息消費(fèi)、第四十二章: 基于SpringBoot & RabbitMQ完成DirectExchange分布式消息多消費(fèi)者消費(fèi)提高了RabbitMQ
消息隊(duì)列的DirectExchange
交換類型的消息消費(fèi)赊舶,我們之前的章節(jié)提到了RabbitMQ
比較常用的交換類型有三種精耐,我們今天來(lái)看看TopicExchange
主題交換類型粪摘。
免費(fèi)教程專題
恒宇少年在博客整理三套免費(fèi)學(xué)習(xí)教程專題
魂莫,由于文章偏多
特意添加了閱讀指南
隅熙,新文章以及之前的文章都會(huì)在專題內(nèi)陸續(xù)填充
沐旨,希望可以幫助大家解惑更多知識(shí)點(diǎn)衅金。
本章目標(biāo)
基于SpringBoot
平臺(tái)完成RabbitMQ
的TopicExchange
消息類型交換噪伊。
SpringBoot 企業(yè)級(jí)核心技術(shù)學(xué)習(xí)專題
專題 | 專題名稱 | 專題描述 |
---|---|---|
001 | Spring Boot 核心技術(shù) | 講解SpringBoot一些企業(yè)級(jí)層面的核心組件 |
002 | Spring Boot 核心技術(shù)章節(jié)源碼 | Spring Boot 核心技術(shù)簡(jiǎn)書每一篇文章碼云對(duì)應(yīng)源碼 |
003 | Spring Cloud 核心技術(shù) | 對(duì)Spring Cloud核心技術(shù)全面講解 |
004 | Spring Cloud 核心技術(shù)章節(jié)源碼 | Spring Cloud 核心技術(shù)簡(jiǎn)書每一篇文章對(duì)應(yīng)源碼 |
005 | QueryDSL 核心技術(shù) | 全面講解QueryDSL核心技術(shù)以及基于SpringBoot整合SpringDataJPA |
006 | SpringDataJPA 核心技術(shù) | 全面講解SpringDataJPA核心技術(shù) |
007 | SpringBoot核心技術(shù)學(xué)習(xí)目錄 | SpringBoot系統(tǒng)的學(xué)習(xí)目錄,敬請(qǐng)關(guān)注點(diǎn)贊5ā酥宴!! |
解決問(wèn)題
之前少年也遇到了一個(gè)問(wèn)題,分類了多模塊后消息隊(duì)列無(wú)法自動(dòng)創(chuàng)建您觉,說(shuō)來(lái)也好笑拙寡,之前沒(méi)有時(shí)間去看這個(gè)問(wèn)題,今天在編寫本章文章時(shí)發(fā)現(xiàn)原因竟然是SpringBoot
沒(méi)有掃描到common
模塊內(nèi)的配置類琳水。讓我一陣的頭大~~~肆糕,我們?cè)?code>XxxApplication啟動(dòng)類上添加@ComponentScan(value = "com.hengyu.rabbitmq")
就可以自動(dòng)創(chuàng)建隊(duì)列了0愣选!诚啃!
構(gòu)建項(xiàng)目
本章構(gòu)建項(xiàng)目時(shí)同樣采用多模塊的方式進(jìn)行設(shè)計(jì)淮摔,可以很好的看到消息處理的效果,因?yàn)槭嵌嗄K項(xiàng)目始赎,我們先來(lái)創(chuàng)建一個(gè)SpringBoot
項(xiàng)目和橙,pom.xml
配置文件依賴配置如下所示:
<dependencies>
<!--rabbbitMQ相關(guān)依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--web相關(guān)依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok依賴-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--spring boot tester-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--fast json依賴-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.40</version>
</dependency>
</dependencies>
下面我們先來(lái)構(gòu)建公共RabbitMQ
模塊,因?yàn)槲覀兊南M(fèi)者以及生產(chǎn)者都是需要RabbitMQ
相關(guān)的配置信息造垛,這里我們可以提取出來(lái)魔招,使用時(shí)進(jìn)行模塊之間的引用。
rabbitmq-topic-common
創(chuàng)建子模塊rabbitmq-topic-common
五辽,在resources
下添加application.yml
配置文件并配置RabbitMQ
相關(guān)的依賴配置办斑,如下所示:
spring:
#rabbitmq消息隊(duì)列配置信息
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
virtual-host: /
publisher-confirms: true
定義交換配置信息
我們跟之前的章節(jié)一張,獨(dú)立編寫一個(gè)枚舉類型來(lái)配置消息隊(duì)列的交換信息杆逗,如下所示:
/**
* rabbitmq交換配置枚舉
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:13:56
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@Getter
public enum ExchangeEnum
{
/**
* 用戶注冊(cè)交換配置枚舉
*/
USER_REGISTER_TOPIC_EXCHANGE("register.topic.exchange")
;
private String name;
ExchangeEnum(String name) {
this.name = name;
}
}
定義隊(duì)列配置信息
同樣消息隊(duì)列的基本信息配置也同樣采用枚舉的形式配置乡翅,如下所示:
/**
* 隊(duì)列配置枚舉
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:05
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@Getter
public enum QueueEnum
{
/**
* 用戶注冊(cè)
* 創(chuàng)建賬戶消息隊(duì)列
*/
USER_REGISTER_CREATE_ACCOUNT("register.account","register.#"),
/**
* 用戶注冊(cè)
* 發(fā)送注冊(cè)成功郵件消息隊(duì)列
*/
USER_REGISTER_SEND_MAIL("register.mail","register.#")
;
/**
* 隊(duì)列名稱
*/
private String name;
/**
* 隊(duì)列路由鍵
*/
private String routingKey;
QueueEnum(String name, String routingKey) {
this.name = name;
this.routingKey = routingKey;
}
}
消息隊(duì)列枚舉內(nèi)添加了兩個(gè)屬性,分別對(duì)應(yīng)了隊(duì)列名稱
罪郊、隊(duì)列路由
蠕蚜,我們本章所講解的TopicExchange
類型消息隊(duì)列可以根據(jù)路徑信息配置多個(gè)消息消費(fèi)者,而轉(zhuǎn)發(fā)的匹配規(guī)則信息則是我們定義的隊(duì)列的路由信息悔橄。
定義發(fā)送消息路由信息
我們?cè)诎l(fā)送消息到隊(duì)列時(shí)靶累,需要我們傳遞一個(gè)路由相關(guān)的配置信息,RabbitMQ
會(huì)根據(jù)發(fā)送時(shí)的消息路由規(guī)則信息與定義消息隊(duì)列時(shí)的路由信息進(jìn)行匹配橄维,如果可以匹配則調(diào)用該隊(duì)列的消費(fèi)者完成消息的消費(fèi)尺铣,發(fā)送消息路由信息配置如下所示:
/**
* 消息隊(duì)列topic交換路由key配置枚舉
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/12/11
* Time:21:58
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@Getter
public enum TopicEnum {
/**
* 用戶注冊(cè)topic路由key配置
*/
USER_REGISTER("register.user")
;
private String topicRouteKey;
TopicEnum(String topicRouteKey) {
this.topicRouteKey = topicRouteKey;
}
}
路由特殊字符 #
我們?cè)?code>QueueEnum內(nèi)配置的路由鍵
時(shí)有個(gè)特殊的符號(hào):#
拴曲,在RabbitMQ
消息隊(duì)列內(nèi)路由配置#
時(shí)表示可以匹配零個(gè)或多個(gè)字符争舞,我們TopicEnum
枚舉內(nèi)定義的register.user
,則是可以匹配QueueEnum
枚舉定義register.#
隊(duì)列的路由規(guī)則澈灼。
當(dāng)然發(fā)送消息時(shí)如果路由傳遞:register.user.account
也是可以同樣匹配register.#
的路由規(guī)則竞川。
路由特殊字符 *
除此之外比較常用到的特殊字符還有一個(gè)*
,在RabbitMQ
消息隊(duì)列內(nèi)路由配置*
時(shí)表示可以匹配一個(gè)字符叁熔,我們QueueEnum
定義路由鍵如果修改成register.*
時(shí)委乌,發(fā)送消息時(shí)路由為register.user
則是可以接受到消息的。但如果發(fā)送時(shí)的路由為register.user.account
時(shí)荣回,則是無(wú)法匹配該消息遭贸。
消息隊(duì)列配置
配置準(zhǔn)備工作已經(jīng)做好,接下來(lái)我們開(kāi)始配置隊(duì)列相關(guān)的內(nèi)容心软,跟之前一樣我們需要配置Queue
壕吹、Exchange
著蛙、Binding
將消息隊(duì)列與交換綁定。下面我們來(lái)看看配置跟之前的章節(jié)有什么差異的地方耳贬,代碼如下所示:
/**
* 用戶注冊(cè)消息隊(duì)列配置
* ========================
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:16:58
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@Configuration
public class UserRegisterQueueConfiguration {
private Logger logger = LoggerFactory.getLogger(UserRegisterQueueConfiguration.class);
/**
* 配置用戶注冊(cè)主題交換
* @return
*/
@Bean
public TopicExchange userTopicExchange()
{
TopicExchange topicExchange = new TopicExchange(ExchangeEnum.USER_REGISTER_TOPIC_EXCHANGE.getName());
logger.info("用戶注冊(cè)交換實(shí)例化成功踏堡。");
return topicExchange;
}
/**
* 配置用戶注冊(cè)
* 發(fā)送激活郵件消息隊(duì)列
* 并設(shè)置持久化隊(duì)列
* @return
*/
@Bean
public Queue sendRegisterMailQueue()
{
Queue queue = new Queue(QueueEnum.USER_REGISTER_SEND_MAIL.getName());
logger.info("創(chuàng)建用戶注冊(cè)消息隊(duì)列成功");
return queue;
}
/**
* 配置用戶注冊(cè)
* 創(chuàng)建賬戶消息隊(duì)列
* 并設(shè)置持久化隊(duì)列
* @return
*/
@Bean
public Queue createAccountQueue()
{
Queue queue = new Queue(QueueEnum.USER_REGISTER_CREATE_ACCOUNT.getName());
logger.info("創(chuàng)建用戶注冊(cè)賬號(hào)隊(duì)列成功.");
return queue;
}
/**
* 綁定用戶發(fā)送注冊(cè)激活郵件隊(duì)列到用戶注冊(cè)主題交換配置
* @return
*/
@Bean
public Binding sendMailBinding(TopicExchange userTopicExchange,Queue sendRegisterMailQueue)
{
Binding binding = BindingBuilder.bind(sendRegisterMailQueue).to(userTopicExchange).with(QueueEnum.USER_REGISTER_SEND_MAIL.getRoutingKey());
logger.info("綁定發(fā)送郵件到注冊(cè)交換成功");
return binding;
}
/**
* 綁定用戶創(chuàng)建賬戶到用戶注冊(cè)主題交換配置
* @return
*/
@Bean
public Binding createAccountBinding(TopicExchange userTopicExchange,Queue createAccountQueue)
{
Binding binding = BindingBuilder.bind(createAccountQueue).to(userTopicExchange).with(QueueEnum.USER_REGISTER_CREATE_ACCOUNT.getRoutingKey());
logger.info("綁定創(chuàng)建賬號(hào)到注冊(cè)交換成功。");
return binding;
}
}
我們從上面開(kāi)始分析咒劲。
第一步: 首先我們創(chuàng)建了TopicExchange
消息隊(duì)列對(duì)象顷蟆,使用ExchangeEnum
枚舉內(nèi)的USER_REGISTER_TOPIC_EXCHANGE
類型作為交換名稱。
第二步:我們創(chuàng)建了發(fā)送注冊(cè)郵件的隊(duì)列sendRegisterMailQueue
腐魂,使用QueueEnum
枚舉內(nèi)的類型USER_REGISTER_SEND_MAIL
作為隊(duì)列名稱帐偎。
第三步:與發(fā)送郵件隊(duì)列一致,用戶創(chuàng)建完成后需要初始化賬戶信息挤渔,而createAccountQueue
消息隊(duì)列后續(xù)邏輯就是來(lái)完成該工作肮街,使用QueueEnum
枚舉內(nèi)的USER_REGISTER_CREATE_ACCOUNT
枚舉作為創(chuàng)建賬戶隊(duì)列名稱。
第四步:在上面步驟中已經(jīng)將交換判导、隊(duì)列創(chuàng)建完成嫉父,下面就開(kāi)始將隊(duì)列綁定到用戶注冊(cè)交換,從而實(shí)現(xiàn)注冊(cè)用戶消息隊(duì)列消息消費(fèi)眼刃,sendMailBinding
綁定了QueueEnum.USER_REGISTER_SEND_MAIL
的RoutingKey
配置信息绕辖。
createAccountBinding
綁定了QueueEnum.USER_REGISTER_CREATE_ACCOUNT
的RoutingKey
配置信息。
到目前為止我們完成了rabbitmq-topic-common
模塊的所有配置信息擂红,下面我們開(kāi)始編寫用戶注冊(cè)消息消費(fèi)者模塊仪际。
rabbitmq-topic-consumer
我們首先來(lái)創(chuàng)建一個(gè)子模塊命名為rabbitmq-topic-consumer
,在pom.xml
配置文件內(nèi)添加rabbitmq-topic-common
模塊的引用昵骤,如下所示:
....//
<dependencies>
<!--公共模塊依賴-->
<dependency>
<groupId>com.hengyu</groupId>
<artifactId>rabbitmq-topic-common</artifactId>
<version>${parent.version}</version>
</dependency>
</dependencies>
....//
消費(fèi)者程序入口
下面我們來(lái)創(chuàng)建程序啟動(dòng)類RabbitMqTopicConsumerApplication
树碱,在這里需要注意,手動(dòng)配置下掃描路徑@ComponentScan
变秦,啟動(dòng)類代碼如下所示:
/**
* 消息消費(fèi)者程序啟動(dòng)入口
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/12/11
* Time:21:48
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@SpringBootApplication
@ComponentScan(value = "com.hengyu.rabbitmq")
public class RabbitMqTopicConsumerApplication {
/**
* logback
*/
private static Logger logger = LoggerFactory.getLogger(RabbitMqTopicConsumerApplication.class);
/**
* 程序入口
* @param args
*/
public static void main(String[] args)
{
SpringApplication.run(RabbitMqTopicConsumerApplication.class,args);
logger.info("【【【【【Topic隊(duì)列消息Consumer啟動(dòng)成功】】】】】");
}
}
手動(dòng)配置掃描路徑在文章的開(kāi)始解釋過(guò)了成榜,主要目的是為了掃描到RabbitMQConfiguration
配置類內(nèi)的信息,讓RabbitAdmin
自動(dòng)創(chuàng)建配置信息到server
端蹦玫。
發(fā)送郵件消費(fèi)者
發(fā)送郵件消息費(fèi)監(jiān)聽(tīng)register.mail
消息隊(duì)列信息赎婚,如下所示:
/**
* 發(fā)送用戶注冊(cè)成功郵件消費(fèi)者
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/12/11
* Time:22:07
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@Component
@RabbitListener(queues = "register.mail")
public class SendMailConsumer
{
/**
* logback
*/
Logger logger = LoggerFactory.getLogger(SendMailConsumer.class);
/**
* 處理消息
* 發(fā)送用戶注冊(cè)成功郵件
* @param userId 用戶編號(hào)
*/
@RabbitHandler
public void handler(String userId)
{
logger.info("用戶:{},注冊(cè)成功樱溉,自動(dòng)發(fā)送注冊(cè)成功郵件.",userId);
//... 發(fā)送注冊(cè)成功郵件邏輯
}
}
在這里我只是完成了消息的監(jiān)聽(tīng)挣输,具體的業(yè)務(wù)邏輯可以根據(jù)需求進(jìn)行處理。
創(chuàng)建賬戶消費(fèi)者
創(chuàng)建用戶賬戶信息消費(fèi)者監(jiān)聽(tīng)隊(duì)列register.account
福贞,代碼如下所示:
/**
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/12/11
* Time:22:04
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@Component
@RabbitListener(queues = "register.account")
public class CreateAccountConsumer {
/**
* logback
*/
Logger logger = LoggerFactory.getLogger(CreateAccountConsumer.class);
/**
* 處理消息
* 創(chuàng)建用戶賬戶
* @param userId 用戶編號(hào)
*/
@RabbitHandler
public void handler(String userId)
{
logger.info("用戶:{}撩嚼,注冊(cè)成功,自動(dòng)創(chuàng)建賬戶信息.",userId);
//... 創(chuàng)建賬戶邏輯
}
}
創(chuàng)建賬戶,賬戶初始化邏輯都可以在handler
方法進(jìn)行處理完丽,本章沒(méi)有做數(shù)據(jù)庫(kù)復(fù)雜的處理向瓷,所以沒(méi)有過(guò)多的邏輯處理在消費(fèi)者業(yè)務(wù)內(nèi)。
rabbitmq-topic-provider
接下來(lái)是我們的消息提供者的模塊編寫舰涌,我們依然先來(lái)創(chuàng)建程序入口類猖任,并添加掃描配置@ComponentScan
路徑,代碼如下所示:
/**
* 消息生產(chǎn)者程序啟動(dòng)入口
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/12/11
* Time:21:48
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@SpringBootApplication
@ComponentScan(value = "com.hengyu.rabbitmq")
public class RabbitMqTopicProviderApplication {
/**
* logback
*/
private static Logger logger = LoggerFactory.getLogger(RabbitMqTopicProviderApplication.class);
/**
* 程序入口
* @param args
*/
public static void main(String[] args)
{
SpringApplication.run(RabbitMqTopicProviderApplication.class,args);
logger.info("【【【【【Topic隊(duì)列消息Provider啟動(dòng)成功】】】】】");
}
}
定義消息發(fā)送接口
創(chuàng)建QueueMessageService
隊(duì)列消息發(fā)送接口并添加send
方法瓷耙,如下所示:
/**
* 消息隊(duì)列業(yè)務(wù)
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:50
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
public interface QueueMessageService
{
/**
* 發(fā)送消息到rabbitmq消息隊(duì)列
* @param message 消息內(nèi)容
* @param exchangeEnum 交換配置枚舉
* @param routingKey 路由key
* @throws Exception
*/
public void send(Object message, ExchangeEnum exchangeEnum, String routingKey) throws Exception;
}
send
方法內(nèi)有三個(gè)參數(shù)朱躺,解析如下:
- message:發(fā)送消息內(nèi)容,可以為任意類型搁痛,當(dāng)然本章內(nèi)僅僅是java.lang.String长搀。
- exchangeEnum:我們自定義的交換枚舉類型,方便發(fā)送消息到指定交換鸡典。
- routingKey:發(fā)送消息時(shí)的路由鍵內(nèi)容源请,該值采用
TopicEnum
枚舉內(nèi)的topicRouteKey
作為參數(shù)值。
下面我們來(lái)看看該接口的實(shí)現(xiàn)類QueueMessageServiceSupport
內(nèi)send
方法實(shí)現(xiàn)彻况,如下所示:
/**
* 消息隊(duì)列業(yè)務(wù)邏輯實(shí)現(xiàn)
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:52
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@Component
public class QueueMessageServiceSupport
implements QueueMessageService
{
/**
* 消息隊(duì)列模板
*/
@Autowired
private RabbitTemplate rabbitTemplate;
@Override
public void send(Object message, ExchangeEnum exchangeEnum, String routingKey) throws Exception {
//發(fā)送消息到消息隊(duì)列
rabbitTemplate.convertAndSend(exchangeEnum.getName(),routingKey,message);
}
}
我們通過(guò)RabbitTemplate
實(shí)例的convertAndSend
方法將對(duì)象類型轉(zhuǎn)換成JSON
字符串后發(fā)送到消息隊(duì)列服務(wù)端谁尸,RabbitMQ
接受到消息后根據(jù)注冊(cè)的消費(fèi)者并且路由規(guī)則篩選后進(jìn)行消息轉(zhuǎn)發(fā),并實(shí)現(xiàn)消息的消費(fèi)纽甘。
運(yùn)行測(cè)試
為了方便測(cè)試我們創(chuàng)建一個(gè)名為UserService
的實(shí)現(xiàn)類良蛮,如下所示:
/**
* 用戶業(yè)務(wù)邏輯
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/12/11
* Time:22:10
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@Service
public class UserService
{
/**
* 消息隊(duì)列發(fā)送業(yè)務(wù)邏輯
*/
@Autowired
private QueueMessageService queueMessageService;
/**
* 隨機(jī)創(chuàng)建用戶
* 隨機(jī)生成用戶uuid編號(hào),發(fā)送到消息隊(duì)列服務(wù)端
* @return
* @throws Exception
*/
public String randomCreateUser() throws Exception
{
//用戶編號(hào)
String userId = UUID.randomUUID().toString();
//發(fā)送消息到rabbitmq服務(wù)端
queueMessageService.send(userId, ExchangeEnum.USER_REGISTER_TOPIC_EXCHANGE, TopicEnum.USER_REGISTER.getTopicRouteKey());
return userId;
}
}
該類內(nèi)添加了一個(gè)名為randomCreateUser
隨機(jī)創(chuàng)建用戶的方法悍赢,通過(guò)UUID
隨機(jī)生成字符串作為用戶的編號(hào)進(jìn)行傳遞給用戶注冊(cè)消息隊(duì)列决瞳,完成用戶的模擬創(chuàng)建。
編寫測(cè)試用例
接下來(lái)我們創(chuàng)建RabbitMqTester
測(cè)試類來(lái)完成隨機(jī)用戶創(chuàng)建消息發(fā)送左权,測(cè)試用例完成簡(jiǎn)單的UserService
注入皮胡,并調(diào)用randomCreateUser
方法,如下所示:
/**
* ========================
*
* @author 恒宇少年
* Created with IntelliJ IDEA.
* Date:2017/12/11
* Time:22:10
* 碼云:http://git.oschina.net/jnyqy
* ========================
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RabbitMqTopicProviderApplication.class)
public class RabbitMqTester
{
/**
* 用戶業(yè)務(wù)邏輯
*/
@Autowired
private UserService userService;
/**
* 模擬隨機(jī)創(chuàng)建用戶 & 發(fā)送消息到注冊(cè)用戶消息隊(duì)列
* @throws Exception
*/
@Test
public void testTopicMessage() throws Exception
{
userService.randomCreateUser();
}
}
到目前為止赏迟,我們的編碼已經(jīng)完成屡贺,下面我們按照下面的步驟啟動(dòng)測(cè)試:
- 啟動(dòng)
rabbitmq-topic-consumer
消息消費(fèi)者模塊,并查看控制臺(tái)輸出內(nèi)容是否正常- 運(yùn)行
rabbitmq-topic-provider
模塊測(cè)試用例方法testTopicMessage
- 查看
rabbitmq-topic-consumer
控制臺(tái)輸出內(nèi)容
最終效果:
2017-12-30 18:39:16.819 INFO 2781 --- [ main] c.h.r.c.RabbitMqTopicConsumerApplication : 【【【【【Topic隊(duì)列消息Consumer啟動(dòng)成功】】】】】
2017-12-30 18:39:29.376 INFO 2781 --- [cTaskExecutor-1] c.h.r.consumer.CreateAccountConsumer : 用戶:c6ef682d-da2e-4cac-a004-c244ff4c4503瀑梗,注冊(cè)成功烹笔,自動(dòng)創(chuàng)建賬戶信息.
2017-12-30 18:39:29.376 INFO 2781 --- [cTaskExecutor-1] c.h.rabbitmq.consumer.SendMailConsumer : 用戶:c6ef682d-da2e-4cac-a004-c244ff4c4503裳扯,注冊(cè)成功抛丽,自動(dòng)發(fā)送注冊(cè)成功郵件.
總結(jié)
本章主要講解了TopicExchange
交換類型如何消費(fèi)隊(duì)列消息,講解了常用到了的特殊字符#
饰豺、*
如何匹配亿鲜,解決了多模塊下的隊(duì)列配置信息無(wú)法自動(dòng)創(chuàng)建問(wèn)題。還有一點(diǎn)需要注意TopicExchange
交換類型在消息消費(fèi)時(shí)不存在固定的先后順序!]锪饶套!
本章源碼已經(jīng)上傳到碼云:
SpringBoot配套源碼地址:https://gitee.com/hengboy/spring-boot-chapter
SpringCloud配套源碼地址:https://gitee.com/hengboy/spring-cloud-chapter