SpringBoot+RabbitMQ完成應用通信
應用通信
作為?個消息隊列, RabbitMQ也可以?作應?程序之間的通信. 上述代碼?產(chǎn)者和消費者代碼放在不同的應?中即可完成不同應?程序的通信.
接下來我們來看, 基于SpringBoot+RabbitMQ完成應?間的通信.
需求描述
??下單成功之后, 通知物流系統(tǒng), 進?發(fā)貨。
訂單系統(tǒng)作為?個?產(chǎn)者, 物流系統(tǒng)作為?個消費者。
創(chuàng)建項目
創(chuàng)建空項目
創(chuàng)建Module(order-service)
添加依賴
創(chuàng)建Module(logistics-service)
添加依賴
消息類型為字符串
編寫訂單代碼
添加配置
spring: application: name: order-service rabbitmq: addresses: amqp://study:study@47.98.109.138:5672/order
聲明隊列
import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.QueueBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQConfig { @Bean("orderQueue") public Queue orderQueue() { return QueueBuilder.durable("order.create").build(); } }
生產(chǎn)訂單
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Random; import java.util.UUID; @RequestMapping("/order") @RestController public class OrderController { @Autowired private RabbitTemplate rabbitTemplate; @RequestMapping("create") public String create(){ String orderId= UUID.randomUUID().toString(); rabbitTemplate.convertAndSend("","order.create","訂單信息,訂單ID:"+orderId); return "下單成功"; } }
編寫物流代碼
添加配置
spring: application: name: logistics-service rabbitmq: addresses: amqp://study:study@47.98.109.138:5672/order server: port: 9090
聲明隊列
import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.QueueBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQConfig { @Bean("order.create") public Queue createOrder() { return QueueBuilder.durable("order.create").build(); } }
消費訂單
import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component public class OrderListener { @RabbitListener(queues = "order.create") public void handMessage(String orderInfo) { System.out.println("接收到訂單消息"+orderInfo); } }
生產(chǎn)訂單
消費訂單
可以看到,訂單已經(jīng)被成功消費了,結(jié)果符合預期。
消息類型為對象
下面的代碼是以上面代碼的基礎,并進行增添刪除編寫而成的。
新增Module
因為訂單系統(tǒng)和物流系統(tǒng)在生產(chǎn)和消費對象類型的消息時,會用到同一個結(jié)構(gòu)體,為了便于代碼編寫,新增Module,把OrderInfo放到新增的Module中。
import lombok.Data; @Data public class OrderInfo{ private String orderId; private String name; }
編寫訂單代碼
在order-service項目的OrderController中添加如下代碼:
@RequestMapping("create2") public String create2(){ OrderInfo orderInfo=new OrderInfo(); orderInfo.setOrderId(UUID.randomUUID().toString()); orderInfo.setName("商品"+new Random().nextInt(100)); rabbitTemplate.convertAndSend("","order.create",orderInfo); return "下單成功"; }
生產(chǎn)對象類型訂單消息
此時我們發(fā)現(xiàn)拋異常了,異常信息為SimpleMessageConverter只支持String, byte[] and Serializable類型的payloads,但是接收到的是order.model.OrderInfo對象。
解決辦法1(實現(xiàn)序列化接口)
修改order-service下的OrderInfo類
import lombok.Data; import java.io.Serializable; @Data public class OrderInfo implements Serializable { private String orderId; private String name; }
雖然成功生成了對象類型的訂單消息,但是我們看到消息的Payload并不直觀,下面我們將采用兩一種解決辦法。
解決辦法2(設置消息轉(zhuǎn)換類型)
修改order-service中的OrderInfo
import lombok.Data; @Data public class OrderInfo{ private String orderId; private String name; }
查看RabbitTemplated的setMessageConverter方法,查看MessageConverter接口的實現(xiàn)類,我們將使用Jackson2JsonMessageConverter。
修改order-service中的RabbitMQConfig
import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.QueueBuilder; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQConfig { @Bean("orderQueue") public Queue orderQueue() { return QueueBuilder.durable("order.create").build(); } @Bean public Jackson2JsonMessageConverter jsonMessageConverter(){ return new Jackson2JsonMessageConverter(); } @Bean public RabbitTemplate rabbitTemplate(ConnectionFactory factory, Jackson2JsonMessageConverter jsonMessageConverter){ RabbitTemplate rabbitTemplate = new RabbitTemplate(factory); rabbitTemplate.setMessageConverter(jsonMessageConverter); return rabbitTemplate; } }
再次生產(chǎn)對象類型訂單消息
此時再次查看隊列中的消息,我們可以看到消息的Payload是非常直觀的?。。?/p>
編寫物流代碼
修改logistics-service中的代碼
import logistics.model.OrderInfo; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component @RabbitListener(queues = "order.create") public class OrderListener { public void handMessage(String orderInfo) { System.out.println("接收到訂單消息"+orderInfo); } public void handMessage(OrderInfo orderInfo) { System.out.println("接收到訂單消息"+orderInfo); } }
消費對象類型訂單消息
但是過了許久,我們也沒有看到隊列中的消息被消費!??!
解決辦法
原因是因為@RabbitListener(queues = "order.create")注解聲明在類上面時,須結(jié)合@RabbitHandler注解來使用!?。?/p>
修改logistics-service中的代碼
import logistics.model.OrderInfo; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component @RabbitListener(queues = "order.create") public class OrderListener { @RabbitHandler public void handMessage(String orderInfo) { System.out.println("接收到訂單消息"+orderInfo); } @RabbitHandler public void handMessage(OrderInfo orderInfo) { System.out.println("接收到訂單消息"+orderInfo); } }
此時消費消息,但是發(fā)現(xiàn)又拋異常了
原因是因為,我們的確是針對生產(chǎn)對象類型消息的一方設置了MessageConverter,但是我們沒有給消費對象類型消息的一方設置MessageConverter,導致消費對象類型消息的一方?jīng)]有辦法正確解析出消息。
解決辦法,依舊是添加MessageConverter?。?!
修改logistics-service中的RabbitMQConfig
import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.QueueBuilder; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQConfig { @Bean("order.create") public Queue createOrder() { return QueueBuilder.durable("order.create").build(); } @Bean public Jackson2JsonMessageConverter jsonMessageConverter(){ return new Jackson2JsonMessageConverter(); } @Bean public RabbitTemplate rabbitTemplate(ConnectionFactory factory, Jackson2JsonMessageConverter jsonMessageConverter){ RabbitTemplate rabbitTemplate = new RabbitTemplate(factory); rabbitTemplate.setMessageConverter(jsonMessageConverter); return rabbitTemplate; } }
再次消費消息
此時我們可以看到,對象類型的訂單消息可以正常消費了,符合預期。
到此這篇關(guān)于SpringBoot+RabbitMQ完成應用通信的文章就介紹到這了,更多相關(guān)SpringBoot RabbitMQ通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java并發(fā)編程之詳解ConcurrentHashMap類
在之前的文章中已經(jīng)為大家介紹了java并發(fā)編程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口,本文為系列文章第八篇.需要的朋友可以參考下2021-06-06java 實現(xiàn)讀取txt文本數(shù)據(jù)并以數(shù)組形式一行一行取值
今天小編就為大家分享一篇java 實現(xiàn)讀取txt文本數(shù)據(jù)并以數(shù)組形式一行一行取值,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07springMVC之HandlerExceptionResolver使用
這篇文章主要介紹了springMVC之HandlerExceptionResolver使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11