【SpringBoot2.0系列09】SpringBoot之rabbi
實現
1.1 rabbitmq簡介
RabbitMQ是由Erlang語言編寫的實現了高階訊息佇列協議(AMQP)的開源訊息代理軟體(也可稱為 面向訊息的中介軟體)。支援Windows、Linux/Unix、MAC OS X作業系統和包括JAVA在內的多種程式語言。
AMQP,即Advanced Message Queuing Protocol,一個提供統一訊息服務的應用層標準高階訊息佇列協議,是應用層協議的一個開放標準,為面向訊息的中介軟體設計。基於此協議的客戶端與訊息中介軟體可傳遞訊息,並不受 客戶端/中介軟體 不同產品,不同的開發語言等條件的限制
使用rabbitmq
主要三種分發模式
1.1.1 工作佇列模式(Work Queue)
避免立即做一個資源密集型任務,必須等待它完成,而是把這個任務安排到稍後再做。我們將任務封裝為訊息並將其傳送給佇列。後臺執行的工作程式將彈出任務並最終執行作業。當有多個worker同時執行時,任務將在它們之間共享。
image.png
1.1.2 分發模式(Fanout Exchange)
一個生產者,多個消費者,每一個消費者都有自己的一個佇列,生產者沒有將訊息直接傳送到佇列,而是傳送到了交換機,每個佇列繫結交換機,生產者傳送的訊息經過交換機,到達佇列,實現一個訊息被多個消費者獲取的目的。需要注意的是,如果將訊息傳送到一個沒有佇列繫結的exchange上面,那麼該訊息將會丟失,這是因為在rabbitMQ中exchange不具備儲存訊息的能力,只有佇列具備儲存訊息的能力。
image.png
image.png
1.1.3 萬用字元模式(Topic Exchange)
這種模式新增了一個路由鍵,生產者釋出訊息的時候新增路由鍵,消費者繫結佇列到交換機時新增鍵值,這樣就可以接收到需要接收的訊息。
符號“#”匹配一個或多個詞,符號“*”匹配不多不少一個詞
image.png
image.png
1.2、安裝rabbitmq
1.2.1 window
因為rabbitmq
是erlang
實現,所以我們需要先下載安裝erlang
,然後再下載rabbitmq
1.2.2 mac
在mac系統中可以直接使用brew
安裝,它會幫我們自動安裝管理依賴。
brew update brew install rabbitmq
這樣,我們就可以使用rabbit-server
啟動Rabbit服務了。
1.2.3 centos
在centos中可以使用yum
安裝
sudo yum install rabbitmq
1.3 springboot整合
首先新建一個專案名為rabbit-producer 訊息生產者工程
並且新增依賴。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> </dependencies>
在yml配置rabbitmq地址
# rabbitmq配置spring: rabbitmq: addresses: 127.0.0.1 username: guest password: guest:
同理建立rabbit-consumer
訊息消費者工程
1、普通工作佇列模式
首先在rabbit-producer
工程中新建RabbitConfig
檔案,用於配置我們rabbitmq相關的資源
程式碼如下
package com.yukong.rabbitproducer;import org.springframework.amqp.core.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @author yukong * @date 2018/8/22 * @description rabbitmq配置類 */@Configurationpublic class RabbitConfig { /** * 定義佇列名 */ private final static String STRING = "string"; /** * 定義string佇列 * @return */ @Bean public Queue string() { return new Queue(STRING); }
定義了名為string的佇列。然後我們建立生產者RabbitProducer
package com.yukong.rabbitproducer;import org.springframework.amqp.core.AmqpTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.xml.ws.Action;import java.text.SimpleDateFormat;import java.util.Date;/** * @author yukong * @date 2018/8/22 * @description rabbit訊息生產者 */@Componentpublic class RabbitProducer { @Autowired private AmqpTemplate rabbitTemplate; public void stringSend() { Date date = new Date(); String dateString = new SimpleDateFormat("YYYY-mm-DD hh:MM:ss").format(date); System.out.println("[string] send msg:" + dateString); // 第一個引數為剛剛定義的佇列名稱 this.rabbitTemplate.convertAndSend("string", dateString); } }
這裡注入一個AmqpTemplate
來發布訊息
接下來我們需要在rabbit-consumer
工程配置一下消費者。
建立StringConsumer
package com.yukong.rabbitmqconsumer;import org.springframework.amqp.core.AmqpTemplate;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;/** * @author yukong * @date 2018/8/22 * @description rabbitmq消費者 @RabbitListener(queues = "simpleMsg") 監聽名simpleMsg的佇列 */@Component@RabbitListener(queues = "string")public class StringConsumer { @Autowired private AmqpTemplate rabbitmqTemplate; /** * 訊息消費 * @RabbitHandler 代表此方法為接受到訊息後的處理方法 */ @RabbitHandler public void recieved(String msg) { System.out.println("[string] recieved message:" + msg); } }
每一個註解的作用程式碼裡面的註釋說的很詳細了我就不重複說了。
然後我們來測試,
首先在生產者工程新建一個測試類,用於生產訊息。
程式碼如下
package com.yukong.rabbitproducer;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublic class RabbitProducerApplicationTests { @Autowired private RabbitProducer producer; @Test public void testStringSend() { for (int i = 0; i < 10; i++) { producer.stringSend(); } } }
首先啟動生產者工程的測試類。然後再啟動消費者工程。
image.png
訊息生產成功,一共十條。
啟動消費者工程。
image.png
消費者成功消費訊息。
2、 fanout模式
fanout屬於廣播模式,只要跟它繫結的佇列都會通知並且接受到訊息。
我們同理在RabbitConfig
中配置一下fanout模式的佇列跟交換機。
//=================== fanout 模式 ==================== @Bean public Queue fanoutA() { return new Queue("fanout.a"); } @Bean public Queue fanoutB() { return new Queue("fanout.b"); } @Bean public Queue fanoutC() { return new Queue("fanout.c"); } /** * 定義個fanout交換器 * @return */ @Bean FanoutExchange fanoutExchange() { // 定義一個名為fanoutExchange的fanout交換器 return new FanoutExchange("fanoutExchange"); } /** * 將定義的fanoutA佇列與fanoutExchange交換機繫結 * @return */ @Bean public Binding bindingExchangeWithA() { return BindingBuilder.bind(fanoutA()).to(fanoutExchange()); } /** * 將定義的fanoutB佇列與fanoutExchange交換機繫結 * @return */ @Bean public Binding bindingExchangeWithB() { return BindingBuilder.bind(fanoutB()).to(fanoutExchange()); } /** * 將定義的fanoutC佇列與fanoutExchange交換機繫結 * @return */ @Bean public Binding bindingExchangeWithC() { return BindingBuilder.bind(fanoutC()).to(fanoutExchange()); }
在程式碼中我們配置了三個佇列名、一個fanout交換機,並且將這三個佇列繫結到了fanout交換器上。只要我們往這個交換機生產新的訊息,那麼這三個佇列都會收到。
接下來,我們在RabbitProducer
中新增fanout的生產方法。
public void fanoutSend() { Date date = new Date(); String dateString = new SimpleDateFormat("YYYY-mm-DD hh:MM:ss").format(date); System.out.println("[fanout] send msg:" + dateString); // 注意 第一個引數是我們交換機的名稱 ,第二個引數是routerKey 我們不用管空著就可以,第三個是你要傳送的訊息 this.rabbitTemplate.convertAndSend("fanoutExchange", "", dateString); }
同理我們需要在消費者工程新建三個消費者的類
程式碼分別如下
@Component@RabbitListener(queues = "fanout.a")public class FanoutAConsumer { @Autowired private AmqpTemplate rabbitmqTemplate; /** * 訊息消費 * @RabbitHandler 代表此方法為接受到訊息後的處理方法 */ @RabbitHandler public void recieved(String msg) { System.out.println("[fanout.a] recieved message:" + msg); } }
@Component@RabbitListener(queues = "fanout.b")public class FanoutBConsumer { @Autowired private AmqpTemplate rabbitmqTemplate; /** * 訊息消費 * @RabbitHandler 代表此方法為接受到訊息後的處理方法 */ @RabbitHandler public void recieved(String msg) { System.out.println("[fanout.b] recieved message:" + msg); } }
@Component@RabbitListener(queues = "fanout.c")public class FanoutCConsumer { @Autowired private AmqpTemplate rabbitmqTemplate; /** * 訊息消費 * @RabbitHandler 代表此方法為接受到訊息後的處理方法 */ @RabbitHandler public void recieved(String msg) { System.out.println("[fanout.c] recieved message:" + msg); } }
然後編寫一個名為testFanout()
的方法啟動我們的fanout生產方法,
@Test public void testFanoutSend() { producer.fanoutSend(); }
image.png
然後重啟消費者工程
image.png
三個佇列的消費都成功接收到訊息。
3、topic模式,
同樣,配置topic佇列跟交換器,注意的是這裡需要多配置一個bindingKey
//#################topic模式######################## @Bean public Queue topiocA() { return new Queue("topic.a"); } @Bean public Queue topicB() { return new Queue("topic.b"); } @Bean public Queue topicC() { return new Queue("topic.c"); } /** * 定義個topic交換器 * @return */ @Bean TopicExchange topicExchange() { // 定義一個名為fanoutExchange的fanout交換器 return new TopicExchange("topicExchange"); } /** * 將定義的topicA佇列與topicExchange交換機繫結 * @return */ @Bean public Binding bindingTopicExchangeWithA() { return BindingBuilder.bind(topiocA()).to(topicExchange()).with("topic.msg"); } /** * 將定義的topicB佇列與topicExchange交換機繫結 * @return */ @Bean public Binding bindingTopicExchangeWithB() { return BindingBuilder.bind(topicB()).to(topicExchange()).with("topic.#"); } /** * 將定義的topicC佇列與topicExchange交換機繫結 * @return */ @Bean public Binding bindingTopicExchangeWithC() { return BindingBuilder.bind(topicC()).to(topicExchange()).with("topic.*.z"); }
topicA的key為topic.msg 那麼他只會接收包含topic.msg的訊息
topicB的key為topic.#那麼他只會接收topic開頭的訊息
topicC的key為topic.*.Z那麼他只會接收topic.B.z這樣格式的訊息
同理在RabbitProducer
完成topic生產方法
public void topicTopic1Send() { Date date = new Date(); String dateString = new SimpleDateFormat("YYYY-mm-DD hh:MM:ss").format(date); dateString = "[topic.msg] send msg:" + dateString; System.out.println(dateString); // 注意 第一個引數是我們交換機的名稱 ,第二個引數是routerKey topic.msg,第三個是你要傳送的訊息 // 這條資訊將會被 topic.a topic.b接收 this.rabbitTemplate.convertAndSend("topicExchange", "topic.msg", dateString); } public void topicTopic2Send() { Date date = new Date(); String dateString = new SimpleDateFormat("YYYY-mm-DD hh:MM:ss").format(date); dateString = "[topic.good.msg] send msg:" + dateString; System.out.println(dateString); // 注意 第一個引數是我們交換機的名稱 ,第二個引數是routerKey ,第三個是你要傳送的訊息 // 這條資訊將會被topic.b接收 this.rabbitTemplate.convertAndSend("topicExchange", "topic.good.msg", dateString); } public void topicTopic3Send() { Date date = new Date(); String dateString = new SimpleDateFormat("YYYY-mm-DD hh:MM:ss").format(date); dateString = "[topic.m.z] send msg:" + dateString; System.out.println(dateString); // 注意 第一個引數是我們交換機的名稱 ,第二個引數是routerKey ,第三個是你要傳送的訊息 // 這條資訊將會被topic.b、topic.b接收 this.rabbitTemplate.convertAndSend("topicExchange", "topic.m.z", dateString); }
然後在消費者工程新建佇列佇列的消費類
@Component@RabbitListener(queues = "topic.a")public class TopicAConsumer { @Autowired private AmqpTemplate rabbitmqTemplate; /** * 訊息消費 * @RabbitHandler 代表此方法為接受到訊息後的處理方法 */ @RabbitHandler public void recieved(String msg) { System.out.println("[topic.a] recieved message:" + msg); } }
@Component@RabbitListener(queues = "topic.b")public class TopicBConsumer { @Autowired private AmqpTemplate rabbitmqTemplate; /** * 訊息消費 * @RabbitHandler 代表此方法為接受到訊息後的處理方法 */ @RabbitHandler public void recieved(String msg) { System.out.println("[topic.b] recieved message:" + msg); } }
@Component@RabbitListener(queues = "topic.c")public class TopicCConsumer { @Autowired private AmqpTemplate rabbitmqTemplate; /** * 訊息消費 * @RabbitHandler 代表此方法為接受到訊息後的處理方法 */ @RabbitHandler public void recieved(String msg) { System.out.println("[topic.c] recieved message:" + msg); } }
同理為topic新建測試方法
@Test public void testTopic() { producer.topicTopic1Send(); producer.topicTopic2Send(); producer.topicTopic3Send(); }
image.png
訊息成功發出。
啟動消費者工程,看看訊息是不是按照規則被髮送訊息
image.png
作者:餘空啊
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4550/viewspace-2816369/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【SpringBoot2.0系列12】SpringBoot之JavaMail傳送,支援FreeMark模板渲染Spring BootJavaAI
- SpringBoot2.0應用(四):SpringBoot2.0之spring-data-jpaSpring Boot
- SpringBoot2.0應用(五):SpringBoot2.0整合MyBatisSpring BootMyBatis
- SpringBoot2.0應用(二):SpringBoot2.0整合ActiveMQSpring BootMQ
- SpringBoot2.0應用(三):SpringBoot2.0整合RabbitMQSpring BootMQ
- SpringBoot2.0之Servlet容器變成UndertowSpring BootServlet
- SpringBoot2.0應用(一):SpringBoot2.0簡單介紹Spring Boot
- springboot2.0 整合springDataJpaSpring Boot
- springboot2.0整合webserviceSpring BootWeb
- springboot2.0整合rabbitmqSpring BootMQ
- SpringBoot2.0 整合 springmvcSpring BootSpringMVC
- springboot2.0 配置redis哨兵Spring BootRedis
- SpringBoot2.0 優雅停機Spring Boot
- SpringBoot2.0原始碼分析(一):SpringBoot簡單分析Spring Boot原始碼
- 正火的SpringBoot2.0更新了啥?Spring Boot
- springboot2.0 獲取啟動埠號Spring Boot
- SpringBoot2.0原始碼分析(二):整合ActiveMQ分析Spring Boot原始碼MQ
- SpringBoot2.0原始碼分析(三):整合RabbitMQ分析Spring Boot原始碼MQ
- springboot2.0使用外部tomcat進行啟動方法Spring BootTomcat
- springboot系列文章之SpringBootApplication註解Spring BootAPP
- SpringBoot2.0原始碼分析(四):spring-data-jpa分析Spring Boot原始碼
- SpringBoot2.0 redis生成組建和讀寫配置檔案Spring BootRedis
- springboot2.0以上排程器配置執行緒池Spring Boot執行緒
- SpringBoot2.x系列教程(三十六)SpringBoot之Tomcat配置Spring BootTomcat
- springboot2.0整合OAuth2並使用JWT作為token。Spring BootOAuthJWT
- springboot系列文章之啟動原理詳解Spring Boot
- Spring全家桶系列–SpringBoot之入門JPASpring Boot
- springboot系列文章之使用單元測試Spring Boot
- 補習系列(10)-springboot 之配置讀取Spring Boot
- 這是一篇優雅的Springboot2.0使用手冊Spring Boot
- springboot系列文章之 整合redis 服務 (Lettuce & Jedis)Spring BootRedis
- SpringBoot系列之YAML配置用法學習筆記Spring BootYAML筆記
- SpringBoot系列之整合阿里canal監聽MySQL BinlogSpring Boot阿里MySql
- springboot系列文章之過濾器 vs 攔截器Spring Boot過濾器
- springboot系列文章之實現跨域請求(CORS)Spring Boot跨域CORS
- 【SpringBoot DB 系列】Jooq 之新增記錄使用姿勢Spring Boot
- SpringBoot系列Mybatis之轉義符的使用姿勢Spring BootMyBatis
- spring boot 系列之八:SpringBoot處理定時任務Spring Boot