如何使用Spring Boot读取RabbitMQ死信函的x-death标头?

时间:2016-06-02 02:11:03

标签: spring spring-amqp spring-rabbitmq

我正在尝试按照此answer中的描述实现死信消息的重新路由。我正在使用Spring配置。我不知道如何读取标头以获取原始路由密钥和原始队列。以下是我的配置:

@Configuration
public class NotifEngineRabbitMQConfig {
    @Bean
    public MessageHandler handler(){
        return new MessageHandler();
    }
    @Bean
    public Jackson2JsonMessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
    @Bean
    public MessageListenerAdapter messageListenerAdapter(){
        return new MessageListenerAdapter(handler(), messageConverter());
    }

    /**
     * Listens for incoming messages
     * Allows multiple queue to listen to
     * */
    @Bean
    public SimpleMessageListenerContainer simpleMessageListenerContainer(){
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.addQueueNames(QUEUE_TO_LISTEN_TO.split(","));
        container.setMessageListener(messageListenerAdapter());
        container.setConnectionFactory(rabbitConnectionFactory());
        container.setDefaultRequeueRejected(false);
        return container;
    }

    @Bean
    public ConnectionFactory rabbitConnectionFactory(){
        CachingConnectionFactory factory = new CachingConnectionFactory(HOST);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);
        return factory;
    }

}

2 个答案:

答案 0 :(得分:2)

使用“旧式”Pojo消息传递(带MessageListenerAdapter)时,标头不可用。您需要实现MessageListener,以便您访问标题。

但是,在这种情况下,您需要自己调用转换器,如果使用请求/回复消息,则会丢失适配器中的回复机制,您必须自己发送回复。

或者,您可以使用自定义消息转换器,并在调用标准转换器后使用标题“增强”转换后的对象。

请考虑将newer style POJO messaging@RabbitListener一起使用 - 它可让您访问标题并具有请求/回复功能。

以下是一个例子:

@SpringBootApplication
public class So37581560Application {

    public static void main(String[] args) {
        SpringApplication.run(So37581560Application.class, args);
    }

    @Bean
    public FooListener fooListener() {
        return new FooListener();
    }

    public static class FooListener {

        @RabbitListener(queues="foo")
        public void pojoListener(String body, 
                   @Header(required = false, name = "x-death") List<String> xDeath) {
            System.out.println(body + ":" + (xDeath == null ? "" : xDeath));
        }

    }

}

结果:

Foo:[{reason=expired, count=1, exchange=, time=Thu Jun 02 08:44:19 EDT 2016, routing-keys=[bar], queue=bar}]

答案 1 :(得分:0)

加里的答案是正确的。只是一点点细节,xDeath的类型最好是ArrayList<HashMap<String,*>>而不是List<String> xDeath。然后,您可以通过执行以下操作来访问任何字段:xDeath.first().get("count")