本文基于上一篇博文springboot rabbitMQ 死信队列进行改动
消息发送确认
发送的消息怎么样才算失败或成功?如何确认?
RabbitTemplate.ReturnCallback
通过实现 ReturnCallback 接口,当消息路由不到队列时触发该回调。
RabbitTemplate.ConfirmCallback
通过实现 ConfirmCallback 接口,消息发送到 Broker 后触发回调,确认消息是否到达 Broker 服务器,即确认是否正确到达 Exchange 中。
代码示例
生产者
配置文件有所改动
spring.rabbitmq.host=192.168.130.128
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
#开启消息确认机制
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true
#设置交换器名称
mq.config.exchange=direct_exchange
#设置队列的路由键
mq.config.queue.routing.key=test_key
实现ConfirmCallback接口
package com.sunyuqi.config;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
@Component
public class MyConfirmCallback implements RabbitTemplate.ConfirmCallback {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
System.out.println("消息发送到exchange成功,id: "+ correlationData.getId());
}
else {
System.out.println("消息发送到exchange失败,原因: "+cause);
}
}
}
实现ReturnCallback接口
package com.sunyuqi.config;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyReturnCallback implements RabbitTemplate.ReturnCallback {
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
String correlationId = message.getMessageProperties().getMessageId();
String msg = new String(message.getBody());
System.out.println("[消息ID:"+correlationId+" ,内容:"+ msg+"]发送失败, 应答码:"+replyCode+" 原因:"+replyText+" 交换机: "+exchange+" 路由键: "+routingKey);
}
}
生产者类
package com.sunyuqi.routing;
import com.sunyuqi.config.MyConfirmCallback;
import com.sunyuqi.config.MyReturnCallback;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class ProducerApp {
@Autowired
private RabbitTemplate rabbitTemplate;
//exChange 交换器
@Value("${mq.config.exchange}")
private String exChange;
//routingkey 路由键
@Value("${mq.config.queue.routing.key}")
private String routingKey;
/**
* 发送消息的方法
* @param msg
*/
@Autowired
private MyConfirmCallback myconfirmCallback;
@Autowired
private MyReturnCallback myReturnCallback;
public void send(Message msg){
//向消息队列发送消息
//参数1:交换器名称
//参数2:路由键
//参数3:消息
this.rabbitTemplate.setMandatory(true);
this.rabbitTemplate.setConfirmCallback(myconfirmCallback);
this.rabbitTemplate.setReturnCallback(myReturnCallback);
this.rabbitTemplate.convertAndSend(exChange,routingKey,msg,new CorrelationData(UUID.randomUUID().toString()));
}
}
测试类
package sunyuqi;
import com.alibaba.fastjson.JSON;
import com.sunyuqi.SpringbootdemoApplication;
import com.sunyuqi.entity.Student;
import com.sunyuqi.routing.ProducerApp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.UUID;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootdemoApplication.class)
public class QueueTest {
@Autowired
private ProducerApp producerApp;
@Test
public void test(){
Student student = new Student();
student.setId(1L);
student.setAge(18);
student.setName("jac");
student.setSex("男");
String s = JSON.toJSONString(student);
Message message = MessageBuilder.withBody(s.getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_JSON)
.setContentEncoding("utf-8")
.setMessageId(UUID.randomUUID().toString()).build();
producerApp.send(message);
}
}
消费者代码不变,启动消费者引导类
运行测试类,消息发送成功,打印成功信息。
此时修改生产者配置文件
#设置交换器名称
mq.config.exchange=direct_exchange1
再次运行测试类,找不到交换机,即无法正确到达交换机
再次修改生产者配置文件
#设置交换器名称
mq.config.exchange=direct_exchange
#设置队列的路由键
mq.config.queue.routing.key=test_key1
能够正确到达交换机,但是无法路由到队列,触发ReturnCallback