以前用過ActiveMQ,最近了解下RabbitMQ的用法和原理,
下面直接開始,在瞭解代碼部分集成之前,讀者先自行了解下RabbitMQ的一些基本知識,以及RabbitMQ的安裝,這裏不再重複,推薦下這篇博客還是不錯的https://www.cnblogs.com/grasp/p/9448660.html
首先介紹幾個基本概念:
1、生產者:發送消息的程序
2、消費者:監聽接收消費消息的程序
3、消息:一串二進制數據流
4、隊列:消息的暫存區/存儲區
5、交換機:消息的中轉站,用於接收分發消息。其中有 fanout、direct、topic、headers 四種
6、路由:相當於密鑰/第三者,與交換機綁定即可路由消息到指定的隊列!
代碼部分
1.jar包的引入
<!--集成rabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>
2、配置配置文件addlication.yml文件
#----------------------------------RabbitMQ----------------------------------
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
3、配置RabbitConfig配置類:
我們需要以 Configuration 的方式配置 RabbitMQ 並以 Bean 的方式顯示注入 RabbitMQ 在發送接收處理消息時相關 Bean 組件配置
package com.dcx.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class RabbitConfig {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Value("${spring.rabbitmq.host}")
private String host;
@Value("${spring.rabbitmq.port}")
private int port;
@Value("${spring.rabbitmq.username}")
private String username;
@Value("${spring.rabbitmq.password}")
private String password;
public static final String EXCHANGE_A = "my-mq-exchange_A";
public static final String QUEUE_A = "QUEUE_A";
public static final String ROUTINGKEY_A = "spring-boot-routingKey_A";
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host,port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost("/");
connectionFactory.setPublisherConfirms(true);
return connectionFactory;
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
//必須是prototype類型
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
return template;
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
return new RabbitAdmin(connectionFactory);
}
/**
* 針對消費者配置
* 1. 設置交換機類型
* 2. 將隊列綁定到交換機
FanoutExchange: 將消息分發到所有的綁定隊列,無routingkey的概念
HeadersExchange :通過添加屬性key-value匹配
DirectExchange:按照routingkey分發到指定隊列
TopicExchange:多關鍵字匹配
*/
@Bean
public DirectExchange defaultExchange() {
return new DirectExchange(EXCHANGE_A);//交換器名稱、是否持久化、是否自動刪除
}
/**
* 獲取隊列A
* @return
*/
@Bean
public Queue queueA() {
return new Queue(QUEUE_A, true); //隊列名字,是否持久化
}
@Bean
public Binding binding() {
return BindingBuilder.bind(queueA()).to(defaultExchange()).with(RabbitConfig.ROUTINGKEY_A);
}
}
消息生產者MsgProducer
package com.dcx.common.rabbitmq;
import com.dcx.config.RabbitConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class MsgProducer implements RabbitTemplate.ConfirmCallback {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//由於rabbitTemplate的scope屬性設置爲ConfigurableBeanFactory.SCOPE_PROTOTYPE,所以不能自動注入
private RabbitTemplate rabbitTemplate;
/**
* 構造方法注入rabbitTemplate
*/
@Autowired
public MsgProducer(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
rabbitTemplate.setConfirmCallback(this); //rabbitTemplate如果爲單例的話,那回調就是最後設置的內容
}
public void sendMsg(String content) {
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
//把消息放入ROUTINGKEY_A對應的隊列當中去,對應的是隊列A
rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_A, RabbitConfig.ROUTINGKEY_A, content, correlationId);
}
/**
* 回調
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
logger.info(" 回調id:" + correlationData);
if (ack) {
logger.info("消息成功消費");
} else {
logger.info("消息消費失敗:" + cause);
}
}
}
消息消費者
package com.dcx.common.rabbitmq;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "QUEUE_A")
public class Receiver {
@RabbitHandler
public void process(String hello) {
System.out.println("Receiver : " + hello);
}
}
控制層接口測試
package com.dcx.modules.sys.controller;
import com.dcx.common.rabbitmq.MsgProducer;
import com.dcx.common.rabbitmq.Sender;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("rabbitmq")
@Api("RabbitMQ接口測試")
public class RabbitMQController {
@Autowired
private MsgProducer msgProducer;
@PostMapping(value = "/sendmsg")
@ApiOperation(value = "發送固定消息")
public String helloTest(){
msgProducer.sendMsg("1111111111111111111111");
return "success";
}
}
項目運行後,進行調用接口
最終控制檯打印結果
-------------------------------------------------------------------------分隔符---------------------------------------------------------------------------------
上面只是實現簡單的消息發送,接收功能