前言
MQ,即消息隊列Message Queue的縮寫。html
RabbitMQ 是MQ的一種,就像招商銀行是銀行的一種同樣。主要是用來實現應用程序的異步和解耦,同時也能起到消息緩衝,消息分發的做用。spring
消息中間件最主要的做用是解耦,中間件最標準的用法是生產者生產消息傳送到隊列,消費者從隊列中拿取消息並處理,生產者不用關心是誰來消費,消費者不用關心誰在生產消息,從而達到解耦的目的。在分佈式的系統中,消息隊列也會被用在不少其它的方面,好比:分佈式事務的支持,RPC的調用等等。windows
安裝
springboot集成
簡單的(一個生產者,一個消費者,使用TopicExchange)
###MAVEN依賴:springboot
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
###application.properties 根據本身的配置調整服務器
spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest
配置Queue,Exchange及其綁定關係
@Configuration public class RabbitConfig { @Bean public Queue commonQueue() { return new Queue("commonQueue"); } @Bean public TopicExchange commonExchange() { return new TopicExchange("topicExchange"); } @Bean public Binding commonBinding() { return BindingBuilder.bind(commonQueue()).to(commonExchange()).with("topic.unique.key"); } }
這裏我只配了一個隊列,並將其綁定到了指定的TopicExchange上,用於生產者和消費者創建聯繫。app
###生產者(發送消息) springboot已經爲咱們封裝好了Rabbit模板類RabbitTemplate,它能夠用來發送和接收消息,直接注入便可使用。 這裏咱們發送一條日期字符串到服務器。異步
@Component public class Producer { private final RabbitTemplate rabbitTemplate; @Autowired public Producer(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } public void send() { String msg = new Date().toString(); rabbitTemplate.convertAndSend("topicExchange", "topic.unique.key", msg); LoggerFactory.getLogger(this.getClass()).info("消息{}已發送!", msg); } }
注意:send()方法是自定義的,用來供外部調用,能夠帶參數。分佈式
若是有外部程序調用了生成者的send方法,根據exchange和queue能夠在服務器上直接查看。 測試類:spring-boot
@SpringBootTest @RunWith(SpringRunner.class) public class SimpleTest { @Autowired private Producer producer; @Test public void testSimple() { producer.send(); } }
服務器效果:
說明咱們的消息發送成功了,那麼如何獲取並處理呢?
###消費者 在springboot接收消息很是容易,只須要在方法上添加註解@RabbitListener
並經過queues
參數綁定監聽的隊列便可,因爲上例中咱們只有一個隊列commonQueue
,那麼咱們綁定它並把接收到的消息打印出來:
@Component public class Consumer extends RabbitProperties.Listener { private static final Logger LOGGER = LoggerFactory.getLogger(Consumer.class); private static final String COMMON_QUEUE = "commonQueue"; @RabbitListener(queues = COMMON_QUEUE) public void dealMessageOfCommonQueue(String msg) { LOGGER.info("接收到來自隊列{}的消息:{}", COMMON_QUEUE, msg); } }
啓動服務看看會不會從服務器中拿到剛纔發送的字符串: 看到打印出來了消息說明成功消費了它,此時若是再去服務器查看,會發現消息爲空,由於它已經被消費掉了。
注意:
- 處理消息的方法中,傳入了一個String類型參數,是由於很清楚生產者發送的消息是字符串類型。也能夠是其餘類型,對的上就行。
- 用Object類型接收的話,會傳入除了發送者發送的消息外還有一些配置信息。故不建議使用Object來入參。
- 此處爲了方便演示,將生產者和消費者寫在一個服務中了,它們能夠在不一樣的(微)服務中,此處應該想到前言中的
解耦
二字。