新鮮出爐,這是全網講的最詳細的springboot整合訊息服務了吧,建議收藏!
springboot整合activeMq
ActiveMq是Apache提供的開源訊息系統採用java實現,
很好地支援JMS(Java Message Service,即Java訊息服務) 規範
ActiveMq安裝:http://activemq.apache.org/components/classic/download/在官網下載安裝對應的版本
下載完成後解壓就可以使用
ActiveMq預設的埠號是8161,使用者名稱和密碼都是admin 在本機可以使用http://localhost:8161去訪問
springboot整合ActiveMq
1、匯入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency>
2、在properties檔案中配置activeMq
spring.activemq.broker-url=tcp://localhost:61616 #如果是點對點(queue),那麼此處預設應該是false,如果釋出訂閱,那麼一定設定為true spring.activemq.packages.trust-all=true spring.activemq.user=admin spring.activemq.password=admin
3、編寫queue(佇列)
@Component public class QueueBean{ //建立一個佇列例項 @Bean Queue queue(){ //這裡設定的訊息是佇列的名稱 return new ActiveMQQueue("hello.javaboy"); } }
4、建立訊息的傳送者以及消費者
@Component public class JmsComponent{ //springboot提供的訊息模板 @Autowired JmsMessagingTemplate jmsMessagingTemplate; //自己建立的佇列例項 @Autowired Queue queue; /** * 傳送訊息 * @param message */ public void send(Message message){ jmsMessagingTemplate.convertAndSend(this.queue,message); } /** * 接收訊息 * @param message */ //表示監聽該佇列名稱發來的訊息 @JmsListener(destination = "hello.javaboy") public void readMessage(Message message){ System.out.println(message); } }
5、上述Message實體類
public class Message implements Serializable { private String content;//訊息主體 private Date sendDate;//訊息傳送的時間 //省略get、set、tostring方法 }
6、進行訊息的傳送以及消費
在測試類中注入JmsComponent 呼叫send()方法進行訊息的轉發
@SpringBootTest class ActivemqApplicationTests { @Autowired JmsComponent jmsComponent; @Test void contextLoads() { Message message = new Message(); message.setContent("hello activeMq"); message.setSendDate(new Date()); jmsComponent.send(message); } }
首先啟動專案,在執行測試類進行訊息傳送:
控制檯會列印訊息內容:
springboot整合RabbitMQ
rabbitmq安裝比較繁瑣,這裡使用docker容器進行安裝,docker安裝非常方便,一條命令全部搞定
通過docker安裝rabbitmq
-P(大p)表示自動對映到主機埠
docker run -d --hostname my-rabbitmq --name some-rabbitmq -P rabbitmq:3-management
首先匯入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
編寫配置檔案:
#配置rabbitMQ spring.rabbitmq.host=localhost spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.port=32771
RabbitMQ 四種交換模式:
直連交換機:Direct exchange
扇形交換機:Fanout exchange
主體交換機:Topic exchange
首部交換機:Headers exchange
下面分別介紹4中交換模式:
1、Direct exchange
//Direct策略(只轉發給routingKey相匹配的使用者) @Configuration public class RabbitDirectConfig { public final static String DIRECTNAME = "javaboy-direct"; //訊息佇列 @Bean Queue queue(){ //name值為佇列名稱,routingKey會與他進行匹配 return new Queue("hello.RabbitMQ"); } @Bean Queue queue1(){ return new Queue("hello.RabbitMQ1"); } @Bean DirectExchange directExchange(){ //第一個引數為DIRECTNAME、第二個引數表示重啟後是否有效,第三引數表示長時間未使用是否刪除 return new DirectExchange(DIRECTNAME,true,false); } @Bean Binding binding(){ //將佇列queue和DirectExchange繫結在一起 return BindingBuilder.bind(queue()).to(directExchange()).with("direct"); } @Bean Binding binding1(){ //將佇列queue和DirectExchange繫結在一起 return BindingBuilder.bind(queue1()).to(directExchange()).with("direct"); } }
2、配置消費者DirectReceiver:
//配置消費者 @Component public class DirectReceiver { //只監聽queue()佇列的訊息 @RabbitListener(queues = "hello.RabbitMQ") public void hanlder(String msg){ System.out.println("hanlder>>>"+msg); } //只監聽queue1()佇列的訊息 @RabbitListener(queues = "hello.RabbitMQ1") public void hanlder1(String msg){ System.out.println("hanlder1>>>"+msg); } }
測試程式碼:
在springboot的測試類中注入RabbitTemplate(springboot提供的RabbitMQ模板)
@Autowired RabbitTemplate rabbitTemplate; @Test void contextLoads() { //兩個引數第一個是routingKey、第二個為訊息內容 rabbitTemplate.convertAndSend("hello.RabbitMQ","hello RabbitMQ test"); rabbitTemplate.convertAndSend("hello.RabbitMQ1","hello RabbitMQ test222"); }
啟動專案後,執行測試類可以看到只有與routingkey相匹配的消費者受到了對應的訊息:
2、Fanout exchange
Fanout策略(只要是與他繫結的佇列,都會收到訊息與routingKey無關)
1、配置RabbitFanoutConfig:
//Fanout策略(只要是與他繫結的佇列,都會收到訊息與routingKey無關) @Configuration public class RabbitFanoutConfig { public final static String FANOUTNAME = "javaboy-fanout"; //配置了兩個訊息佇列queueOne和queueTwo @Bean Queue queueOne(){ return new Queue("queue-one"); } @Bean Queue queueTwo(){ return new Queue("queue-two"); } @Bean FanoutExchange fanoutExchange(){ return new FanoutExchange(FANOUTNAME,true,false); } //將兩個佇列與FanoutExchange繫結 @Bean Binding bindingOne(){ return BindingBuilder.bind(queueOne()).to(fanoutExchange()); } @Bean Binding bindingTwo(){ return BindingBuilder.bind(queueTwo()).to(fanoutExchange()); } }
2、配置消費者FanoutReceiver:
//配置消費者 @Component public class FanoutReceiver { //兩個消費者分別監聽兩個不同的佇列 @RabbitListener(queues = "queue-one") public void hanlder1(String msg){ System.out.println("FanoutReceiver:hanlder1>>>"+msg); } @RabbitListener(queues = "queue-two") public void hanlder2(String msg){ System.out.println("FanoutReceiver:hanlder2>>>"+msg); } }
3、測試類:
@Test void rabbitFanout(){ //三個引數表示RabbitFanoutConfig的名稱、routingkey、訊息內容 rabbitTemplate.convertAndSend(RabbitFanoutConfig.FANOUTNAME,null,"hello fanout test"); }
該方式與routingkey無關所有寫null即可
檢視輸出:可以看到兩個消費者都收到了訊息
3、Topic exchange
topic策略可以根據routingKey的規則(萬用字元方式)進行去匹配佇列進行轉發規則為.#. *為單詞,#表示模糊匹配
例如routingkey為:xiaomi.# 那麼帶有xiaomi.開頭的佇列都會收到該訊息
routingkey為:#.phone.# 表示訊息的routingKey中帶有phone時 就會去匹配帶有phone的佇列
1、配置RabbitTopicConfig:
/topic策略可以根據routingKey的規則(萬用字元方式)進行去匹配佇列進行轉發規則為*.#.* //*為單詞,#表示模糊匹配 @Configuration public class RabbitTopicConfig { public final static String TOPICNAME = "javaboy-topic"; @Bean TopicExchange topicExchange(){ return new TopicExchange(TOPICNAME,true,false); } @Bean Queue xiaomi(){ return new Queue("xiaomi"); } @Bean Queue huawei(){ return new Queue("huawei"); } @Bean Queue phone(){ return new Queue("phone"); } @Bean Binding xiaomiBinding(){ //xiaomi.#:表示訊息的routingKey是以xiaomi開頭的就會路由到xiaomi的佇列 return BindingBuilder.bind(xiaomi()).to(topicExchange()).with("xiaomi.#"); } @Bean Binding huaweiBinding(){ return BindingBuilder.bind(huawei()).to(topicExchange()).with("huawei.#"); } @Bean Binding phoneBinding(){ //#.phone.#:表示訊息的routingKey中帶phone的都會路由到phone的佇列 return BindingBuilder.bind(phone()).to(topicExchange()).with("#.phone.#"); } }
2、配置消費者TopicReceiver:
@Component public class TopicReceiver { //分別監聽名稱為xiaomi、huawei、phone的佇列 @RabbitListener(queues = "xiaomi") public void handlerXM(String msg){ System.out.println("TopicReceiver:handlerXM>>>"+msg); } @RabbitListener(queues = "huawei") public void handlerHW(String msg){ System.out.println("TopicReceiver:handlerHW>>>"+msg); } @RabbitListener(queues = "phone") public void handlerPHONE(String msg){ System.out.println("TopicReceiver:handlerPHONE>>>"+msg); } }
3、測試類:
@Test void rabbitTopic(){ //根據匹配規則該訊息只能被xiaomi的佇列收到 rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"xiaomi.news","小米新聞"); //根據匹配規則該訊息只能被phone的佇列收到 rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"vivo.phone","vivo手機"); //根據匹配規則該訊息可以別huawei和phone兩個佇列收到 rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"huawei.phone","華為手機"); }
檢視輸出:
可以看到routingkey為huawei.phone的訊息匹配了兩個佇列,其他兩個都只匹配了一個佇列
4、Headers exchange
該模式是根據路由規則的header進行匹配的,在進行匹配的時候需要傳入一個map集合,routingkey去匹配map即可中的key value,匹配規則可以使any或者all,any表示只要包含任意資訊就可以,all表示所有資訊都必須匹配
1、配置RabbitHeaderConfig:
@Configuration public class RabbitHeaderConfig { public final static String HEADERNAME = "javaboy-header"; @Bean HeadersExchange headersExchange(){ return new HeadersExchange(HEADERNAME,true,false); } //分別建立兩個不同header的佇列 @Bean Queue queueName(){ return new Queue("name-queue"); } @Bean Queue queueAge(){ return new Queue("age-queue"); } @Bean Binding bindingName(){ Map<String,Object> map = new HashMap<>(); map.put("name","hello"); //表示如果routingKey匹配的map集合中的key value 就會將訊息轉發到對應的路由上 return BindingBuilder.bind(queueName()).to(headersExchange()).whereAny(map).match(); } @Bean Binding bindingAge(){ return BindingBuilder.bind(queueAge()).to(headersExchange()).where("age").exists(); } }
2、建立消費者HeaderReceiver:
@Component public class HeaderReceiver { @RabbitListener(queues = "name-queue") public void handlerName(byte[] msg){ System.out.println("HeaderReceiver:handlerName>>>>"+new String(msg,0,msg.length)); } @RabbitListener(queues = "age-queue") public void handlerAge(byte[] msg){ System.out.println("HeaderReceiver:handlerAge>>>>"+new String(msg,0,msg.length)); } }
3、測試程式碼:
@Test public void rabbitHeader(){ //設定訊息,並且設定header,setHeader("name","hello")分別表示map集合中的key、value Message nameMessage = MessageBuilder.withBody("hello name".getBytes()).setHeader("name","hello").build(); Message ageMessage = MessageBuilder.withBody("hello 99 age".getBytes()).setHeader("age","99").build(); rabbitTemplate.send(RabbitHeaderConfig.HEADERNAME,null,nameMessage); rabbitTemplate.send(RabbitHeaderConfig.HEADERNAME,null,ageMessage); }
檢視輸出:
改變setheader中的值檢視結果:
Message nameMessage = MessageBuilder.withBody("hello name".getBytes()).setHeader("name","javaboy").build();
可以看到因為key、value匹配不上只打印了一條訊息。
最後
大家看完有什麼不懂的可以在下方留言討論,也可以關注我私信問我,我看到後都會回答的。也歡迎大家關注我的公眾號:前程有光,金三銀四跳槽面試季,整理了1000多道將近500多頁pdf文件的Java面試題資料,文章都會在裡面更新,整理的資料也會放在裡面。謝謝你的觀看,覺得文章對你有幫助的話記得關注我點個贊支援一下!