Spring boot整合RabbitMQ
在阅读这篇之前请先完成RabbitMQ的基础知识学习。
文章目录
依赖
<!--RabbitMQ 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置
spring:
rabbitmq:
host: MQ服务器地址
port: 端口号
username: 账号
password: 密码
基础发送和接受消息
创建队列、交换机、绑定信息
@Configuration
public class Demo1QueueConfig {
/**
* 创建一个队列,这里是最基础的创建队列只指定了队列名称
*/
@Bean
public Queue getDemo1Consumer() {
return new Queue("hello");
}
}
生产者
/**
* 注入Springboot的MQ操作模板
*/
@Resource
private RabbitTemplate rabbitTemplate;
@GetMapping("/demo1")
public String demo1(String message) {
//发送消息
rabbitTemplate.send("hello", new Message(message.getBytes()));
log.info("发送消息成功:{}", message);
return "发送成功";
}
消费者
@Slf4j
@Component
public class Demo1Consumer {
/**
* 创建消费者接收消息,并指定队列名称
*/
@RabbitListener(queues = "hello")
public void message(String message) {
log.info("消费者收到消息:{}", message);
}
}
手动应答
配置
spring:
rabbitmq:
#消费者手动确认
listener:
simple:
acknowledge-mode: manual
创建队列、交换机、绑定信息
@Configuration
public class Demo2QueueConfig {
/**
* 创建一个队列,这里是最基础的创建队列只指定了队列名称
*/
@Bean
public Queue getDemo2QueueConfig() {
return new Queue("ack_queue");
}
}
生产者
/**
* 注入Springboot的MQ操作模板
*/
@Resource
private RabbitTemplate rabbitTemplate;
/**
* demo2
*/
@GetMapping("/demo2")
public String demo2(String message) {
//发送消息
rabbitTemplate.send("ack_queue", new Message(message.getBytes()));
log.info("手动应答发送消息成功:{}", message);
return "发送成功";
}
消费者
@Slf4j
@Component
public class Demo2Consumer {
/**
* 手动应答消费者
*/
@RabbitListener(queues = "ack_queue")
public void message(Channel channel, Message message) throws Exception {
log.info("手动应答消费者收到消息:{}", message.getBody());
Thread.sleep(10000);
/*
用于肯定确认应答,告诉MQ已经处理完成
1.消息标记 tag
2.是否批量应答未应答消息,true 代表批量应答比如说channe上有传送tag的消息5,6,7,8当前tag是8那么此时5-8的这些还未应答的消息都会被确认收到消息应答;false同上面相比只会应答tag=8的消息5,6,7这三个消息依然不会被确认收到消息应答。下面的批量否认确定同此。
*/
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
/*
用于否定确认
1.消息标记 tag
2.指定是否批量否定确认
3.决定被否定确认的消息是否应重新入队(requeue)供其他消费者再次消费
*/
// channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
log.info("手动应答消费应答了消息");
}
}
队列持久化
创建队列、交换机、绑定信息
@Configuration
public class Demo3QueueConfig {
/**
* 创建一个队列,true让其持久化
*/
@Bean
public Queue getDemo3QueueConfig() {
return new Queue("durable_queue", true);
}
}
消息持久化
生产者
/**
* 注入Springboot的MQ操作模板
*/
@Resource
private RabbitTemplate rabbitTemplate;
/**
* demo3 消息持久化
*/
@GetMapping("/demo3")
public String demo3(String message) {
//设置消息持久化
MessageProperties messageProperties = new MessageProperties();
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
//发送消息
rabbitTemplate.send("ack_queue", new Message(message.getBytes(), messageProperties));
log.info("消息持久化发送消息成功:{}", message);
return "发送成功";
}
不公平分发和预取值
消费者
@Slf4j
@Component
public class Demo4Consumer {
@RabbitListener(queues = "demo4_queue")
public void message(Channel channel, Message message) throws Exception {
log.info("消费者收到消息:{}", message.getBody());
/**
* 只能处理一条消息,在未应答前MQ不会给该消费者发送下一条消息
*/
channel.basicQos(1);
log.info("手动应答消费应答了消息");
}
}
发布确认
配置
spring:
rabbitmq:
#开启发布确认,异步回调
publisher-confirm-type: correlated
生产者
/**
* 注入Springboot的MQ操作模板
*/
@Resource
private RabbitTemplate rabbitTemplate;
/**
* demo5 发布确认
* 注入发布确认回调
*/
@Resource
private Demo5CallBack demo5CallBa
/**
* 依赖注入 rabbitTemplate 之后再设置它的回调对象
*/
@PostConstruct
public void init() {
//设置发布确认回调
rabbitTemplate.setConfirmCallback(demo5CallBack);
/**
* demo5 发布确认
*/
@GetMapping("/demo5")
public String demo5(String message) {
//发送消息
CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("ack_queue", new Message(message.getBytes()), correlationData1);
log.info("发布确认发送消息成功:{}", message);
return "发送成功";
}
监听回调
@Component
@Slf4j
public class Demo5CallBack implements RabbitTemplate.ConfirmCallback {
/**
* 交换机不管是否收到消息的一个回调方法
* @param correlationData 消息相关数据
* @param ack 交换机是否收到消息
* @param cause 未收到原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
String id=correlationData!=null?correlationData.getId():"";
if(ack){
log.info("交换机已经收到 id 为:{}的消息",id);
}else{
log.info("交换机还未收到 id 为:{}消息,由于原因:{}",id,cause);
}
}
}
消息回退
配置
spring:
rabbitmq:
host: 192.168.10.100
port: 5672
username: admin
password: 123
#开启发布确认,异步回调
publisher-confirm-type: correlated
#开启消息退回
publisher-returns: true
template:
mandatory: true
生产者
/**
* 注入Springboot的MQ操作模板
*/
@Resource
private RabbitTemplate rabbitTemplate;
/**
* demo6 发布回退
* 注入发布回退回调
*/
@Resource
private Demo6CallBack demo6CallBac
/**
* 依赖注入 rabbitTemplate 之后再设置它的回调对象
*/
@PostConstruct
public void init() {
//设置发布确认回调
rabbitTemplate.setReturnCallback(demo6CallBack);
/**
* demo6 发布回退
*/
@GetMapping("/demo6")
public String demo6(String message) {
//发送消息
CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("ddddd", new Message(message.getBytes()), correlationData1);
log.info("发布回退发送消息成功:{}", message);
return "发送成功";
}
监听回调
@Component
@Slf4j
public class Demo6CallBack implements RabbitTemplate.ReturnCallback {
/**
* 当消息无法路由的时候的回调方法
*
* @param message 退回的消息对象本身
* @param replyCode RabbitMQ返回的错误码
* @param replyText RabbitMQ返回的错误信息
* @param exchange 消息原本试图发送到的交换器名称
* @param routingKey 消息发送时附带的路由键
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.error(" 消 息 {}, 被交换机 {} 退回,退回原因 :{}, 路 由 key:{}", new String(message.getBody()), exchange,
replyText, routingKey);
}
}
fanout(广播类型)交换机
创建队列、交换机、绑定信息
@Configuration
public class Demo7QueueConfig {
/**
* 创建一个fanout交换机
*/
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange("FanoutExchange", false, false);
}
/**
* 创建三个队列
*/
@Bean
Queue fanoutQueueA() {
return new Queue("FanoutA", false, false, false);
}
@Bean
Queue fanoutQueueB() {
return new Queue("FanoutB", false, false, false);
}
@Bean
Queue fanoutQueueC() {
return new Queue("FanoutC", false, false, false);
}
/**
* 将创建的队列绑定到创建的交换机上
*/
@Bean
Binding fanoutBindingA() {
return BindingBuilder.bind(fanoutQueueA()).to(fanoutExchange());
}
@Bean
Binding fanoutBindingB() {
return BindingBuilder.bind(fanoutQueueB()).to(fanoutExchange());
}
@Bean
Binding fanoutBindingC() {
return BindingBuilder.bind(fanoutQueueC()).to(fanoutExchange());
}
}
生产者
/**
* demo7 fanout(广播类型)
*/
@GetMapping("/demo7")
public String demo7(String message) {
//发送消息
CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("FanoutExchange", "", new Message(message.getBytes()),
correlationData1);
log.info("fanout(广播类型)发送消息成功:{}", message);
return "发送成功";
}
消费者
@Slf4j
@Component
public class Demo7Consumer {
@RabbitListener(queues = "FanoutA")
public void messageFanoutA(Message message) throws Exception {
log.info("FanoutA消费者收到消息:{}", message.getBody());
}
@RabbitListener(queues = "FanoutB")
public void messageFanoutB(Message message) throws Exception {
log.info("FanoutB消费者收到消息:{}", message.getBody());
}
@RabbitListener(queues = "FanoutC")
public void messageFanoutC(Message message) throws Exception {
log.info("FanoutC消费者收到消息:{}", message.getBody());
}
}
direct(直接类型)交换机
创建队列、交换机、绑定信息
/**
* direct(直接类型)交换机
*
* @author zjy
* @date 2024/04/20 17:00
*/
@Configuration
public class Demo8QueueConfig {
/**
* 创建一个direct交换机
*/
@Bean
DirectExchange directExchange() {
return new DirectExchange("DirectExchange", false, false);
}
/**
* 创建两个队列
*/
@Bean
Queue directQueueA() {
return new Queue("directA", false, false, false);
}
@Bean
Queue directQueueB() {
return new Queue("directB", false, false, false);
}
/**
* 将创建的队列绑定到创建的交换机上
*/
@Bean
Binding directBindingA() {
return BindingBuilder.bind(directQueueA()).to(directExchange()).with("a");
}
@Bean
Binding directBindingB() {
return BindingBuilder.bind(directQueueB()).to(directExchange()).with("b");
}
}
生产者
/**
* demo8 direct(直接类型)
*/
@GetMapping("/demo8")
public String demo8(String message) {
//发送消息
CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("DirectExchange", "a", new Message(message.getBytes()),
correlationData1);
log.info("direct(直接类型)发送消息成功:{}", message);
return "发送成功";
}
消费者
@Slf4j
@Component
public class Demo8Consumer {
@RabbitListener(queues = "directA")
public void messageDirectA(Message message) throws Exception {
log.info("DirectA消费者收到消息:{}", message.getBody());
}
@RabbitListener(queues = "directB")
public void messageDirectB(Message message) throws Exception {
log.info("DirectB消费者收到消息:{}", message.getBody());
}
}
Topics(复杂匹配)交换机
创建队列、交换机、绑定信息
@Configuration
public class Demo9QueueConfig {
/**
* 创建一个Topics(复杂匹配)交换机
*/
@Bean
TopicExchange topicsExchange() {
return new TopicExchange("TopicExchange", false, false);
}
/**
* 创建两个队列
*/
@Bean
Queue topicQueueA() {
return new Queue("TopicA", false, false, false);
}
@Bean
Queue topicQueueB() {
return new Queue("TopicB", false, false, false);
}
/**
* 将创建的队列绑定到创建的交换机上
*/
@Bean
Binding topicBindingA() {
return BindingBuilder.bind(topicQueueA()).to(topicsExchange()).with("*.a");
}
@Bean
Binding topicBindingB() {
return BindingBuilder.bind(topicQueueB()).to(topicsExchange()).with("#");
}
}
生产者
@GetMapping("/demo9")
public String demo9(@RequestParam String routingKey, @RequestParam String message) {
//发送消息
CorrelationData correlationData1 = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("TopicExchange", routingKey, new Message(message.getBytes()),
correlationData1);
log.info("Topics(复杂匹配)发送消息成功:{}", message);
return "发送成功";
}
消费者
@Slf4j
@Component
public class Demo9Consumer {
@RabbitListener(queues = "TopicA")
public void messageDirectA(Message message) throws Exception {
log.info("TopicA消费者收到消息:{}", message.getBody());
}
@RabbitListener(queues = "TopicB")
public void messageDirectB(Message message) throws Exception {
log.info("TopicB消费者收到消息:{}", message.getBody());
}
}
死信队列
创建队列、交换机、绑定信息
@Configuration
public class Demo10QueueConfig {
/**
* 创建一个正常交换机
*/
@Bean
DirectExchange normalExchange() {
return new DirectExchange("NormalExchange", false, false);
}
/**
* 创建一个死信交换机
*/
@Bean
DirectExchange deathExchange() {
return new DirectExchange("DeathExchange", false, false);
}
/**
* 创建死信队列
*/
@Bean
Queue deathQueue() {
return new Queue("deathQueue", false, false, false);
}
/**
* 将死信队列绑定到创建的死信交换机
*/
@Bean
Binding deathBinding() {
return BindingBuilder.bind(deathQueue()).to(deathExchange()).with("death");
}
/**
* 创建正常队列并绑定死信交换机
*/
@Bean
Queue normalQueue() {
//交换机设置死信交换机
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-dead-letter-exchange", "DeathExchange");
//正常队列设置死信 routing-key 参数 key 是固定值
arguments.put("x-dead-letter-routing-key", "death");
return new Queue("normalQueue", false, false, false, arguments);
}
/**
* 将正常队列绑定到创建的正常交换机
*/
@Bean
Binding normalBinding() {
return BindingBuilder.bind(normalQueue()).to(normalExchange()).with("death");
}
}
生产者
/**
* demo10 死信队列
*/
@GetMapping("/demo10")
public String demo10(String message) {
//设置消息1秒过期
MessageProperties messageProperties = new MessageProperties();
messageProperties.setExpiration("1000");
//发送消息
rabbitTemplate.convertAndSend("NormalExchange", "death",
new Message(message.getBytes(), messageProperties));
log.info("死信队列发送消息成功:{}", message);
return "发送成功";
}
消费者
@Slf4j
@Component
public class Demo10Consumer {
@RabbitListener(queues = "deathQueue")
public void deathQueue(Message message) throws Exception {
log.info("死信队列消费者收到消息:{}", message.getBody());
}
}
延迟队列
创建队列、交换机、绑定信息
@Configuration
public class Demo11QueueConfig {
/**
* 创建一个延迟交换机
*/
@Bean
public CustomExchange delayExchange() {
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
// 属性参数 交换机名称 交换机类型 是否持久化 是否自动删除 配置参数
return new CustomExchange("delay_exchange", "x-delayed-message", false, false, args);
}
/**
* 延时队列
*/
@Bean
public Queue delayQueue() {
// 属性参数 队列名称 是否持久化
return new Queue("delay_queue", false);
}
/**
* 给延时队列绑定交换机
*/
@Bean
public Binding cfgDelayBinding() {
return BindingBuilder.bind(delayQueue()).to(delayExchange()).with("delay_key").noargs();
}
}
生产者
/**
* demo11 延迟队列
*/
@GetMapping("/demo11")
public String demo11(Integer s, String message) {
//设置消息1秒过期
MessageProperties messageProperties = new MessageProperties();
// 配置消息的过期时间
messageProperties.setDelay(s * 1000);
//发送消息
rabbitTemplate.convertAndSend("delay_exchange", "delay_key",
new Message(message.getBytes(), messageProperties));
log.info("延迟队列发送消息成功:{}", message);
return "发送成功";
}
消费者
@Slf4j
@Component
public class Demo11Consumer {
@RabbitListener(queues = "delay_queue")
public void deathQueue(Message message) throws Exception {
log.info("延迟队列消费者收到消息:{}", message.getBody());
}
}