Spring boot Spring AMQP-发布服务器确认在发布到不存在的队列时返回ack ed

Spring boot Spring AMQP-发布服务器确认在发布到不存在的队列时返回ack ed,spring-boot,spring-amqp,spring-rabbit,Spring Boot,Spring Amqp,Spring Rabbit,如果我在RabbitMQ上使用publisher confirms并返回回调,我将永远不会收到返回的消息。 从Spring AMQP文档: - Publish to an exchange but there is no matching destination queue. - Publish to a non-existent exchange. The first case is covered by publisher returns, as described in Publisher

如果我在RabbitMQ上使用publisher confirms并返回回调,我将永远不会收到返回的消息。 从Spring AMQP文档:

- Publish to an exchange but there is no matching destination queue.
- Publish to a non-existent exchange.
The first case is covered by publisher returns, as described in Publisher Confirms and Returns.
所以,若我发布到existexchange,而不是existqueue,我想我会得到返回的消息。但返回回调从未调用。 我需要设置其他内容吗?
我正在使用RabbitMQ 3.8.0和Spring Boot 2.2.1

application.yml

spring:
  rabbitmq:
    publisher-confirms: true
    publisher-returns: true
    template:
      mandatory: true
制作人

@服务
公共类PublisherConfigProducer{
私有静态最终记录器log=LoggerFactory.getLogger(PublisherConfirmProducer.class);
@自动连线
私人兔样板兔样板;
@施工后
构造后的私有void(){
this.rabbitTemplate.setConfirmCallback((相关、确认、原因)->{
if(相关性!=null){
日志信息(“收到”+(确认?“确认”):“nack”)+“用于相关性:”+相关性);
}
});
this.rabbitTemplate.setReturnCallback((消息、replyCode、replyText、exchange、routingKey)->{
log.info(“返回:“+message+”\nreplyCode:“+replyCode+”\nreplyText:“+replyText
+“\nexchange/rk:”+exchange+“/”+routingKey);
});
}
//小心:将被静默删除,因为交换存在,但不存在
//路由到队列,但已确认。如何知道我已发布到不存在的队列?
public void sendMessage_ValidExchange_InvalidQueue(DummyMessage消息){
CorrelationData CorrelationData=新的CorrelationData(“消息相关性”+message.getContent());
this.rabbitTemplate.convertAndSend(“x.test”,“无效路由密钥”、消息、correlationData);
}
}
主应用程序

@springboot应用程序
公共类RabbitMQProducertWO应用程序实现CommandLineRunner{
公共静态void main(字符串[]args){
run(RabbitmqProducerTwoApplication.class,args);
}
@自动连线
私人出版商确认制作人;
@凌驾
公共无效运行(字符串…参数)引发异常{
var dummyMessage_2=新的dummyMessage(“消息2”,2);
producer.sendMessage_ValidExchange_InvalidQueue(dummyMessage_2);
}
}
记录结果

2019-11-29 04:45:23.796  INFO 8352 --- [           main] c.c.r.RabbitmqProducerTwoApplication     : Starting RabbitmqProducerTwoApplication on timpamungkas with PID 8352 (D:\workspace\eclipse\my-courses\rabbitmq-1.2\rabbitmq-producer-two\bin\main started by USER in D:\workspace\eclipse\my-courses\rabbitmq-1.2\rabbitmq-producer-two)
2019-11-29 04:45:23.800  INFO 8352 --- [           main] c.c.r.RabbitmqProducerTwoApplication     : No active profile set, falling back to default profiles: default
2019-11-29 04:45:24.952  INFO 8352 --- [           main] c.c.r.RabbitmqProducerTwoApplication     : Started RabbitmqProducerTwoApplication in 1.696 seconds (JVM running for 3.539)
2019-11-29 04:45:24.990  INFO 8352 --- [           main] o.s.a.r.c.CachingConnectionFactory       : Attempting to connect to: [localhost:5672]
2019-11-29 04:45:25.024  INFO 8352 --- [           main] o.s.a.r.c.CachingConnectionFactory       : Created new connection: rabbitConnectionFactory#599f571f:0/SimpleConnection@86733 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 50688]
2019-11-29 04:45:25.058  INFO 8352 --- [nectionFactory1] c.c.r.producer.PublisherConfirmProducer  : Received  ack for correlation: CorrelationData [id=Correlation for message Message 2]

为加里编辑

RabbitMqConfig.java

@配置
公共类RabbitmqConfig{
@豆子
公共Jackson2JsonMessageConverter转换器(){
返回新的Jackson2JsonMessageConverter();
}
@豆子
公共RabbitTemplate RabbitTemplate(连接工厂连接工厂,Jackson2JsonMessageConverter转换器){
RabbitTemplate=新的RabbitTemplate(connectionFactory);
模板.setMessageConverter(转换器);
返回模板;
}
}

返回消息后,您将收到肯定的确认

你所拥有的在我看来是正确的。它非常类似于,因此应该以相同的方式工作


什么类型的交换是
x.test
?哪些队列绑定到它,使用哪些路由密钥


如果您在查看该示例后仍然无法使其正常工作,请将项目发布到某个地方,我来看看。

实现看起来是正确的,只需实现您自己的私有回调类并扩展ConfirmCallback以注册回调,在初始化RabbitTemplate时设置ConfirmCallback

 private static class PublisherCallback implements RabbitTemplate.ConfirmCallback {
    
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        System.out.println("Confirm message returned " + correlationData.toString() + " Ack " + ack + " cause " + cause);
    }

}

rabbitTemplate.setConfirmCallback(new PublisherCallback());

什么类型的交换是
x.test
?什么队列绑定到它,使用什么路由键?嗨,Gary。“x.test”是直接交换,通过路由键“test”绑定到“q.test”。我可以让它工作后,一些尝试。我有一个RabbitMQConfig.java,它返回rabbitmplate(参见上面的代码)。为了使返回回调有效,我必须在配置中对返回rabbitmplate的Bean进行注释。有趣的是,如果我不注释Bean,则会触发确认回调,但不会触发返回回调。这是预期的行为吗?顺便说一句,我真的很佩服你为春季amqp所做的一切!这真的帮了我很大的忙!谢谢3000@gary russellI如果你不介意的话,我已经把代码放在这里了。非常感谢
spring.rabbitmq.template.*
属性在自动配置
rabbitmplate时由Boot使用。因为您有自己的bean,所以自动配置被禁用,因此
强制属性不被应用;当您定义自己的模板bean时,您需要自己设置
强制
属性。此外,Boot将检测您的消息转换器并自动将其连接到模板中,因此您真的不需要自己的bean。