訊息佇列目前流行的有KafKa、RabbitMQ、ActiveMQ等,它們的誕生無非不是為了解決訊息的分散式消費,完成專案、服務之間的解耦動作。訊息佇列提供者與消費者之間完全採用非同步通訊方式,極力的提高了系統的響應能力,從而提高系統的網路請求吞吐量。 每一種的訊息佇列都有它在設計上的獨一無二的優勢,在實際的專案技術選型時根據專案的需求來確定。
本章目標
基於SpringBoot
專案整合RabbitMQ
訊息佇列,完成DirectExchange(路由鍵)
分散式訊息消費。
Exchange
在RabbitMQ
中有三種轉發方式,分別是:
DirectExchange
:路由鍵方式轉發訊息。
FanoutExchange
:廣播方式轉發訊息。
TopicExchange
:主題匹配方式轉發訊息。
我們本章先來講解DirectExchange
路由鍵方式,根據設定的路由鍵的值進行完全匹配時轉發,下面我們來看一張圖,形象的介紹了轉發訊息匹配流程,如下圖所示:
我們可以看到上圖,當訊息被提供者傳送到RabbitMQ
後,會根據配置佇列的交換以及繫結例項進行轉發訊息,上圖只會將訊息轉發路由鍵為KEY
的佇列消費者對應的實現方法邏輯中,從而完成訊息的消費過程。
安裝RabbitMQ
因為RabbitMQ
是跨平臺的分散式訊息佇列服務,可以部署在任意的作業系統上,下面我們分別介紹在不同的系統下該怎麼去安裝RabbitMQ
服務。
我們本章採用的環境版本如下:
- RabbitMQ Server 3.6.14
- Erlang/OTP_X64 20.1
Windows下安裝
我們先去RabbitMQ
官方網站下載最新版的安裝包,下載地址:https://www.rabbitmq.com/download.html
,可以根據不同的作業系統選擇下載。
我們在安裝RabbitMQ
服務端時需要Erlang
環境的支援,所以我們需要先安裝Erlang
。
-
我們通過
Erlang
官方網站http://www.erlang.org/downloads
下載最新的安裝包,因為是國外的網站所以下載比較慢,不過沒有關係,我再本章原始碼的resource
目錄下存放了安裝包,本章原始碼在文章底部。 -
我們訪問
RabiitmQ
官方下載地址https://www.rabbitmq.com/download.html
下載最新安裝包,該安裝包同樣存放在resource
目錄下。 -
執行安裝
Erlang
-
執行安裝
RabbitMQ
5.檢查服務是否安裝完成,RabbitMQ
安裝完成後會以服務的形式建立,並且隨著開機啟動,如下所示:
Mac OS X 安裝
在Mac OS X中我們使用brew
工具可以很簡單的安裝RabbitMQ
服務端,步驟如下:
brew
更新到最新版本,執行:brew update
- 接下來我們安裝
Erlang
,執行:brew install erlang
- 最後安裝
RabbitMQ
,執行:brew install rabbitmq
我們通過上面的步驟安裝後,RabbitMQ
會被自動安裝到/usr/local/sbin
目錄下,下面我們需要手動設定環境變數,來支援服務執行,修改.profile
配置檔案並新增如下配置:
PATH=$PATH:/usr/local/sbin
複製程式碼
配置完成後,可以直接通過rabbitmq-server
命令來操作RabbitMQ
服務。
Ubuntu 安裝
在Ubuntu
作業系統中,我們可以直接使用APT
倉庫進行安裝,我使用的系統版本是16.04
,系統版本並不影響安裝。
- 安裝
Erlang
,執行命令:sudo apt-get install erlang
- 下面我們需要將
RabbitMQ
的安裝源配置資訊寫入到系統的/etc/apt/sources.list.d
配置檔案內,執行如下命令:
echo 'deb http://www.rabbitmq.com/debian/ testing main' | sudo tee /etc/apt/sources.list.d/rabbitmq.list
複製程式碼
- 下面我們更新
APT
本地倉庫的安裝包列表,執行命令:sudo apt-get update
- 最後安裝
RabbitMQ
服務,執行命令:sudo apt-get install rabbitmq-server
啟用介面管理外掛
RabbitMQ
提供了介面管理的web
外掛,我們只需要啟用指定的外掛就可以了,下面我們來看看Windows
作業系統下該怎麼啟動介面管理外掛。
我們使用CMD
進入RabbitMQ
安裝目錄C:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.14
,然後我們進入sbin
目錄,可以看到目錄記憶體在很多個bat
指令碼程式,我們找到rabbitmq-plugins.bat
,這個指令碼程式可以控制RabbitMQ
外掛啟用禁用,我們執行如下指令碼命令來啟用介面管理外掛:
rabbitmq-plugins.bat enable rabbitmq_management
複製程式碼
命令列輸出內容如下所示:
The following plugins have been enabled:
amqp_client
cowlib
cowboy
rabbitmq_web_dispatch
rabbitmq_management_agent
rabbitmq_management
Applying plugin configuration to rabbit@yuqiyu... started 6 plugins.
複製程式碼
可以看到輸出的內容RabbitMQ
自動啟動了6個外掛,我們現在訪問http://127.0.0.1:15672地址可以直接開啟RabbitMQ
的介面管理平臺,而預設的使用者名稱/密碼分別為:guest/guest
,通過該使用者可以直接登入管理平臺。
禁用介面管理外掛
我們同樣可以禁用RabbitMQ
指定外掛,執行如下命令:
rabbitmq-plugins.bat disable rabbitmq_management
複製程式碼
命令建立輸出內容則是相關停止外掛的日誌,如下:
The following plugins have been disabled:
amqp_client
cowlib
cowboy
rabbitmq_web_dispatch
rabbitmq_management_agent
rabbitmq_management
Applying plugin configuration to rabbit@yuqiyu... stopped 6 plugins.
複製程式碼
這樣我們再訪問http://127.0.0.1:15672就會發現我們無法訪問到介面。
構建專案
我們使用idea
開發工具建立一個SpringBoot
專案,新增依賴,pom.xml配置檔案如下所示:
<dependencies>
<!--rabbitmq依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--web依賴-->
<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>
<!--fastjson依賴-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.40</version>
</dependency>
<!--測試依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
複製程式碼
我們本章來模擬使用者註冊完成後,將註冊使用者的編號通過Provider
模組傳送到RabbitMQ
,然後RabbitMQ
根據配置的DirectExchange
的路由鍵進行非同步轉發。
初始化使用者表
下面我們先來建立所需要的使用者基本資訊表
,建表SQL如下所示:
CREATE TABLE `user_info` (
`UI_ID` int(11) DEFAULT NULL COMMENT '使用者編號',
`UI_USER_NAME` varchar(20) DEFAULT NULL COMMENT '使用者名稱稱',
`UI_NAME` varchar(20) DEFAULT NULL COMMENT '真實姓名',
`UI_AGE` int(11) DEFAULT NULL COMMENT '使用者年齡',
`UI_BALANCE` decimal(10,0) DEFAULT NULL COMMENT '使用者餘額'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='使用者基本資訊表';
複製程式碼
構建 rabbitmq-provider 專案
基於我們上述的專案建立一個Maven
子模組,命名為:rabbitmq-provider
,因為是直接建立的Module
專案,IDEA
並沒有給我建立SpringApplication
啟用類。
建立入口類
下面我們自行建立一個Provider
專案啟動入口程式,如下所示:
/**
* 訊息佇列訊息提供者啟動入口
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:14
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@SpringBootApplication
public class RabbitmqProviderApplication
{
static Logger logger = LoggerFactory.getLogger(RabbitmqProviderApplication.class);
/**
* 訊息佇列提供者啟動入口
* @param args
*/
public static void main(String[] args)
{
SpringApplication.run(RabbitmqProviderApplication.class,args);
logger.info("【【【【【訊息佇列-訊息提供者啟動成功.】】】】】");
}
}
複製程式碼
application.properties配置檔案
下面我們在src/main/resource
目錄下建立application.properties
並將對應RabbitMQ
以及Druid
的配置加入,如下所示:
#使用者名稱
spring.rabbitmq.username=guest
#密碼
spring.rabbitmq.password=guest
#伺服器ip
spring.rabbitmq.host=localhost
#虛擬空間地址
spring.rabbitmq.virtual-host=/
#埠號
spring.rabbitmq.port=5672
#配置釋出訊息確認回撥
spring.rabbitmq.publisher-confirms=true
#資料來源配置
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
spring.datasource.druid.username=root
spring.datasource.druid.password=123456
複製程式碼
在RabbitMQ
內有個virtual-host
即虛擬主機的概念,一個RabbitMQ
服務可以配置多個虛擬主機,每一個虛擬機器主機之間是相互隔離,相互獨立的,授權使用者到指定的virtual-host
就可以傳送訊息到指定佇列。
使用者實體
本章資料庫操作採用spring-data-jpa
,相關文章請訪問:第十三章:SpringBoot實戰SpringDataJPA,我們基於user_info
資料表對應建立實體,如下所示:
@Data
@Table(name = "user_info")
@Entity
public class UserEntity
implements Serializable
{
/**
* 使用者編號
*/
@Id
@GeneratedValue
@Column(name = "UI_ID")
private Long id;
/**
* 使用者名稱稱
*/
@Column(name = "UI_USER_NAME")
private String userName;
/**
* 姓名
*/
@Column(name = "UI_NAME")
private String name;
/**
* 年齡
*/
@Column(name = "UI_AGE")
private int age;
/**
* 餘額
*/
@Column(name = "UI_BALANCE")
private BigDecimal balance;
}
複製程式碼
使用者資料介面
建立UserRepository
使用者資料操作介面,並繼承JpaRepository
獲得spring-data-jpa
相關的介面定義方法。如下所示:
/**
* 使用者資料介面定義
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:35
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
public interface UserRepository
extends JpaRepository<UserEntity,Long>
{
}
複製程式碼
使用者業務邏輯實現
本章只是簡單完成了資料的新增,程式碼如下所示:
/**
* 使用者業務邏輯實現類
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:37
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class UserService
{
@Autowired
private UserRepository userRepository;
/**
* 訊息佇列業務邏輯實現
*/
@Autowired
private QueueMessageService queueMessageService;
/**
* 儲存使用者
* 並寫入訊息佇列
* @param userEntity
* @return
*/
public Long save(UserEntity userEntity) throws Exception
{
/**
* 儲存使用者
*/
userRepository.save(userEntity);
/**
* 將訊息寫入訊息佇列
*/
queueMessageService.send(userEntity.getId(), ExchangeEnum.USER_REGISTER, QueueEnum.USER_REGISTER);
return userEntity.getId();
}
複製程式碼
在上面業務邏輯實現類內出現了一個名為QueueMessageService
訊息佇列實現類,該類是我們定義的用於傳送訊息到訊息佇列的統一入口,在下面我們會詳細講解。
使用者控制器
建立一個名為UserController
的控制器類,對應編寫一個新增使用者的請求方法,如下所示:
/**
* 使用者控制器
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:41
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@RestController
@RequestMapping(value = "/user")
public class UserController
{
/**
* 使用者業務邏輯
*/
@Autowired
private UserService userService;
/**
* 儲存使用者基本資訊
* @param userEntity
* @return
*/
@RequestMapping(value = "/save")
public UserEntity save(UserEntity userEntity) throws Exception
{
userService.save(userEntity);
return userEntity;
}
}
複製程式碼
到這我們新增使用者的流程已經編寫完成了,那麼我們就來看下訊息佇列QueueMessageService
介面的定義以及實現類的定義。
訊息佇列方法定義介面
建立一個名為QueueMessageService
的介面並且繼承了RabbitTemplate.ConfirmCallback
介面,而RabbitTemplate.ConfirmCallback
介面是用來回撥訊息傳送成功後的方法,當一個訊息被成功寫入到RabbitMQ
服務端時,就會自動的回撥RabbitTemplate.ConfirmCallback
介面內的confirm
方法完成通知,QueueMessageService
介面如下所示:
/**
* 訊息佇列業務
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:50
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
public interface QueueMessageService
extends RabbitTemplate.ConfirmCallback
{
/**
* 傳送訊息到rabbitmq訊息佇列
* @param message 訊息內容
* @param exchangeEnum 交換配置列舉
* @param queueEnum 佇列配置列舉
* @throws Exception
*/
public void send(Object message, ExchangeEnum exchangeEnum, QueueEnum queueEnum) throws Exception;
}
複製程式碼
接下來我們需要實現該介面內的所有方法,並做出一些業務邏輯的處理。
訊息佇列業務實現
建立名為QueueMessageServiceSupport
實體類實現QueueMessageService
介面,並實現介面內的所有方法,如下所示:
/**
* 訊息佇列業務邏輯實現
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:52
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@Component
public class QueueMessageServiceSupport
implements QueueMessageService
{
/**
* 訊息佇列模板
*/
@Autowired
private RabbitTemplate rabbitTemplate;
@Override
public void send(Object message, ExchangeEnum exchangeEnum, QueueEnum queueEnum) throws Exception {
//設定回撥為當前類物件
rabbitTemplate.setConfirmCallback(this);
//構建回撥id為uuid
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
//傳送訊息到訊息佇列
rabbitTemplate.convertAndSend(exchangeEnum.getValue(),queueEnum.getRoutingKey(),message,correlationId);
}
/**
* 訊息回撥確認方法
* @param correlationData 請求資料物件
* @param ack 是否傳送成功
* @param cause
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println(" 回撥id:" + correlationData.getId());
if (ack) {
System.out.println("訊息傳送成功");
} else {
System.out.println("訊息傳送失敗:" + cause);
}
}
}
複製程式碼
convertAndSend
方法用於將Object
型別的訊息轉換後傳送到RabbitMQ
服務端,傳送是的訊息型別要與訊息消費者方法引數保持一致。
在confirm
方法內,我們僅僅列印了訊息傳送時的id
,根據ack
引數輸出訊息傳送狀態。
在上面程式碼中我們注入了
RabbitTemplate
訊息佇列模板例項,而通過該例項我們可以將訊息傳送到RabbitMQ
服務端。那麼這個例項具體在什麼地方定義的呢?我們帶著這個疑問來建立下面的模組,我們需要將RabbitMQ
相關的配置抽取出來作為一個單獨的Module
存在。
構建 rabbitmq-common 專案
該模組專案很簡單,只是新增RabbitMQ
相關的配置資訊,由於Module
是一個子模組所以繼承了parent
所有的依賴,當然我們用到的RabbitMQ
相關依賴也不例外。
配置rabbitmq
在建立配置類之前,我們先來定義兩個列舉,分別存放了佇列的交換資訊、佇列路由資訊,
- ExchangeEnum (存放了佇列交換配置資訊)
/**
* rabbitmq交換配置列舉
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:13:56
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@Getter
public enum ExchangeEnum
{
/**
* 使用者註冊交換配置列舉
*/
USER_REGISTER("user.register.topic.exchange")
;
private String value;
ExchangeEnum(String value) {
this.value = value;
}
}
複製程式碼
- QueueEnum (存放了佇列資訊以及佇列的路由配置資訊)
/**
* 佇列配置列舉
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:14:05
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@Getter
public enum QueueEnum
{
/**
* 使用者註冊列舉
*/
USER_REGISTER("user.register.queue","user.register")
;
/**
* 佇列名稱
*/
private String name;
/**
* 佇列路由鍵
*/
private String routingKey;
QueueEnum(String name, String routingKey) {
this.name = name;
this.routingKey = routingKey;
}
}
複製程式碼
建立名為UserRegisterQueueConfiguration
的實體類用於配置本章用到的使用者註冊佇列資訊,如果你得專案中使用多個佇列,建議每一個業務邏輯建立一個配置類,分開維護,這樣不容易出錯。配置資訊如下:
/**
* 使用者註冊訊息佇列配置
* ========================
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:16:58
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@Configuration
public class UserRegisterQueueConfiguration {
/**
* 配置路由交換物件例項
* @return
*/
@Bean
public DirectExchange userRegisterDirectExchange()
{
return new DirectExchange(ExchangeEnum.USER_REGISTER.getValue());
}
/**
* 配置使用者註冊佇列物件例項
* 並設定持久化佇列
* @return
*/
@Bean
public Queue userRegisterQueue()
{
return new Queue(QueueEnum.USER_REGISTER.getName(),true);
}
/**
* 將使用者註冊佇列繫結到路由交換配置上並設定指定路由鍵進行轉發
* @return
*/
@Bean
public Binding userRegisterBinding()
{
return BindingBuilder.bind(userRegisterQueue()).to(userRegisterDirectExchange()).with(QueueEnum.USER_REGISTER.getRoutingKey());
}
}
複製程式碼
該配置類大致分為如下三部分:
-
配置交換例項 配置
DirectExchange
例項物件,為交換設定一個名稱,引用ExchangeEnum
列舉配置的交換名稱,訊息提供者與訊息消費者的交換名稱必須一致才具備的第一步的通訊基礎。 -
配置佇列例項 配置
Queue
例項物件,為訊息佇列設定一個名稱,引用QueueEnum
列舉配置的佇列名稱,當然佇列的名稱同樣也是提供者與消費者之間的通訊基礎。 -
繫結佇列例項到交換例項 配置
Binding
例項物件,訊息繫結的目的就是將Queue
例項繫結到Exchange
上,並且通過設定的路由Key
進行訊息轉發,配置了路由Key
後,只有符合該路由配置的訊息才會被轉發到繫結交換上的訊息佇列。
我們的rabbitmq-common
模組已經編寫完成。
新增 rabbitmq-provider 依賴 rabbitmq-common
下面我們回到rabbitmq-provider
模組,修改pom.xml配置檔案,如下所示:
<dependencies>
<!--新增common模組依賴-->
<dependency>
<groupId>com.hengyu</groupId>
<artifactId>rabbitmq-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--mysql依賴-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--druid資料來源依賴-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.5</version>
</dependency>
<!--data jpa依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
複製程式碼
可以看到我們將rabbitmq-common
模組新增到了rabbitmq-provider
模組的pom
配置檔案內,完成了模組之間的相互依賴,這樣我們rabbitmq-provider
就自動新增了對應的訊息佇列配置。
構建rabbitmq-consumer
我們再來建立一個rabbitmq-consumer
佇列訊息消費者模組,用於接受消費使用者註冊訊息。
建立入口類
同樣我們先來建立一個SpringApplication
入口啟動類,如下所示:
/**
* 訊息佇列訊息消費者入口
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:15:15
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@SpringBootApplication
public class RabbitmqConsumerApplication
{
static Logger logger = LoggerFactory.getLogger(RabbitmqConsumerApplication.class);
/**
* rabbitmq消費者啟動入口
* @param args
*/
public static void main(String[] args)
{
SpringApplication.run(RabbitmqConsumerApplication.class,args);
logger.info("【【【【【訊息佇列-訊息消費者啟動成功.】】】】】");
}
}
複製程式碼
application.properties配置檔案
配置檔案的訊息佇列配置資訊要與rabbitmq-provider
配置檔案一致,如下所示:
spring.application.name=rabbitmq-consumer
#啟動埠
server.port=1111
#使用者名稱
spring.rabbitmq.username=guest
#密碼
spring.rabbitmq.password=guest
#伺服器ip
spring.rabbitmq.host=localhost
#虛擬空間地址
spring.rabbitmq.virtual-host=/
#埠號
spring.rabbitmq.port=5672
#配置釋出訊息確認回撥
spring.rabbitmq.publisher-confirms=true
複製程式碼
我們修改了程式啟動的埠號,為了我們下面進行測試的時候不出現埠占用的情況。
如果
RabbitMQ
配置資訊與rabbitmq-provider
不一致,就不會收到消費訊息。
使用者註冊訊息消費者
建立名為UserConsumer
類,用於完成訊息監聽,並且實現訊息消費,如下所示:
/**
* 使用者註冊訊息消費者
* ========================
*
* @author 恆宇少年
* Created with IntelliJ IDEA.
* Date:2017/11/26
* Time:15:20
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@Component
@RabbitListener(queues = "user.register.queue")
public class UserConsumer {
@RabbitHandler
public void execute(Long userId)
{
System.out.println("使用者:" + userId+",完成了註冊");
//...//自行業務邏輯處理
}
}
複製程式碼
在訊息消費者類內,有兩個陌生的註解:
- @RabbitListener
RabbitMQ
佇列訊息監聽註解,該註解配置監聽queues
內的佇列名稱列表,可以配置多個。佇列名稱對應本章rabbitmq-common
模組內QueueEnum
列舉name
屬性。 - @RabbitHandler
RabbitMQ
訊息處理方法,該方法的引數要與rabbitmq-provider
傳送訊息時的型別保持一致,否則無法自動呼叫消費方法,也就無法完成訊息的消費。
#執行測試
我們接下來在rabbitmq-provider
模組src/test/java
下建立一個測試用例,訪問使用者註冊控制器請求路徑,如下所示:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RabbitmqProviderApplication.class)
public class UserTester
{
/**
* 模擬mvc測試物件
*/
private MockMvc mockMvc;
/**
* web專案上下文
*/
@Autowired
private WebApplicationContext webApplicationContext;
/**
* 所有測試方法執行之前執行該方法
*/
@Before
public void before() {
//獲取mockmvc物件例項
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
/**
* 測試新增使用者
* @throws Exception
*/
@Test
public void testUserAdd() throws Exception
{
mockMvc.perform(MockMvcRequestBuilders.post("/user/save")
.param("userName","yuqiyu")
.param("name","恆宇少年")
.param("age","23")
)
.andDo(MockMvcResultHandlers.log())
.andReturn();
}
}
複製程式碼
呼叫測試用例時會自動將引數儲存到資料庫,並且將使用者編號傳送到RabbitMQ
服務端,而RabbitMQ
根據交換配置以及佇列配置轉發訊息到消費者例項。
啟動 rabbitmq-consumer
我們先來把rabbitmq-consumer
專案啟動,控制檯輸出啟動日誌如下所示:
.....
51.194 INFO 2340 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'rabbitConnectionFactory' has been autodetected for JMX exposure
2017-12-03 16:58:51.196 INFO 2340 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'rabbitConnectionFactory': registering with JMX server as MBean [org.springframework.amqp.rabbit.connection:name=rabbitConnectionFactory,type=CachingConnectionFactory]
2017-12-03 16:58:51.216 INFO 2340 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647
2017-12-03 16:58:51.237 INFO 2340 --- [cTaskExecutor-1] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory#443ff8ef:0/SimpleConnection@4369ac5c [delegate=amqp://guest@127.0.0.1:5672/, localPort= 62107]
2017-12-03 16:58:51.287 INFO 2340 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 1111 (http)
2017-12-03 16:58:51.290 INFO 2340 --- [ main] c.h.r.c.RabbitmqConsumerApplication : Started RabbitmqConsumerApplication in 2.354 seconds (JVM running for 3.026)
2017-12-03 16:58:51.290 INFO 2340 --- [ main] c.h.r.c.RabbitmqConsumerApplication : 【【【【【訊息佇列-訊息消費者啟動成功.】】】】】
複製程式碼
該部分啟動日誌就是我們配置的RabbitMQ
初始化資訊,我們可以看到專案啟動時會自動與配置的RabbitMQ
進行關聯:
[delegate=amqp://guest@127.0.0.1:5672/, localPort= 62107]
複製程式碼
執行測試用例
接下來我們執行rabbitmq-provider
專案的測試用例,來檢視控制檯的輸出內容如下所示:
......
回撥id:e08f6d82-57bc-4c3f-9899-31c4b990c5be
訊息傳送成功
......
複製程式碼
已經可以正常的將訊息傳送到RabbitMQ
服務端,並且接收到了回撥通知,那麼我們的rabbitmq-consumer
專案是不是已經執行了訊息的消費呢?我們開啟rabbitmq-consumer
控制檯檢視輸出內容如下所示:
使用者:2,完成了註冊
複製程式碼
看以看到已經可以成功的執行UserConsumer
訊息監聽類內的監聽方法邏輯,到這裡訊息佇列路由一對一的方式已經講解完了。
總結
本章主要講解了RabbitMQ
在不同作業系統下的安裝方式,以及通過三個子模組形象的展示了訊息的分散式處理,整體流程:rabbitmq-provider -> RabbitMQ
服務端 -> rabbitmq-consumer,訊息的轉發是非常快的,RabbitMQ
在收到訊息後就會檢索當前服務端是否存在該訊息的消費者,如果存在將會馬上將訊息轉發。
本章原始碼已經上傳到碼雲: SpringBoot配套原始碼地址:gitee.com/hengboy/spr… SpringCloud配套原始碼地址:gitee.com/hengboy/spr… SpringBoot相關係列文章請訪問:目錄:SpringBoot學習目錄 QueryDSL相關係列文章請訪問:QueryDSL通用查詢框架學習目錄 SpringDataJPA相關係列文章請訪問:目錄:SpringDataJPA學習目錄 SpringBoot相關文章請訪問:目錄:SpringBoot學習目錄,感謝閱讀! 歡迎加入QQ技術交流群,共同進步。