在仅开启了生产者确认机制的情况下,交换机接收到消息后,会直接给消息生产者发送确认消息,如果发现该消息不可路由,那么消息会被直接丢弃,此时生产者是不知道消息被丢弃这个事件的。那么如何让无法被路由的消息帮我想办法处理一下?最起码通知我一声,我好自己处理啊。通过设置mandatory参数可以在当消息传递过程中不可达目的地时将消息返回给生产者。
- 配置文件
spring.rabbitmq.publisher-returns=true
- 回退接口
@Component
@Slf4j
public class MyCallBack implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void init(){
//注入
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setReturnsCallback(this);
}
/*
* 交换机确认回调方法,发消息后,交换机接收到了就回调
* 1.1 correlationData:保存回调消息的ID及相关信息
* 1.2 b:交换机收到消息,为true
* 1.3 s:失败原因,成功为null
*
* 发消息,交换机接受失败,也回调
* 2.1 correlationData:保存回调消息的ID及相关信息
* 2.2 b:交换机没收到消息,为false
* 2.3 s:失败的原因
*
* */
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
String id = correlationData!=null ? correlationData.getId():"";
if (b){
log.info("交换机已经收到ID为:{}的信息",id);
}else {
log.info("交换机还未收到ID为:{}的消息,由于原因:{}",id,s);
}
}
//可以在当消息传递过程中不可达目的的时将消息返回给生产者
//只有不可达目的地的时候才可回退
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
log.error("消息{},被交换机{}退回,退回的原因:{},路由Key:{}",
new String(returnedMessage.getMessage().getBody())
, returnedMessage.getExchange()
, returnedMessage.getReplyText()
, returnedMessage.getRoutingKey());
}
}
- 发布测试
// 开始发消息 测试确认
@RestController
@Slf4j
@RequestMapping("/confirm")
public class ProducerController {
@Autowired
private RabbitTemplate rabbitTemplate;
//发消息
@GetMapping("/sendMessage/{message}")
public void sendMessage(@PathVariable String message){
CorrelationData correlationData = new CorrelationData("1");
rabbitTemplate.convertAndSend(ConfirmConfig.CONFIRM_EXCHANGE_NAME
,ConfirmConfig.CONFIRM_routing_key
,message+"key1",correlationData);
log.info("发送消息内容:{}",message+"key1");
CorrelationData correlationData2 = new CorrelationData("2");
rabbitTemplate.convertAndSend(ConfirmConfig.CONFIRM_EXCHANGE_NAME
,ConfirmConfig.CONFIRM_routing_key+"2"
,message+"key12",correlationData2);
log.info("发送消息内容:{}",message+"key12");
}
}
4.效果:实现回退消息成功!