带注解方法的消息转换

在调用监听器之前,管道中有两个转换步骤。第一步使用MessageConverter将传入的 Spring AMQP Message 转换为 Spring 消息 Message。当调用目标方法时,消息负载将根据需要转换为方法参数类型。

第一步的默认MessageConverter是 Spring AMQP SimpleMessageConverter,它处理转换为Stringjava.io.Serializable对象。所有其他类型保持为byte[]。在下文中,我们将其称为“消息转换器”。

第二步的默认转换器是GenericMessageConverter,它委托给转换服务(DefaultFormattingConversionService的实例)。在下文中,我们将其称为“方法参数转换器”。

要更改消息转换器,可以将其作为属性添加到容器工厂 Bean 中。以下示例显示了如何操作

@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    ...
    factory.setMessageConverter(new Jackson2JsonMessageConverter());
    ...
    return factory;
}

这配置了一个 Jackson2 转换器,它期望存在头信息来指导转换。

您也可以使用ContentTypeDelegatingMessageConverter,它可以处理不同内容类型的转换。

从 2.3 版本开始,您可以通过在messageConverter属性中指定 Bean 名称来覆盖工厂转换器。

@Bean
public Jackson2JsonMessageConverter jsonConverter() {
    return new Jackson2JsonMessageConverter();
}

@RabbitListener(..., messageConverter = "jsonConverter")
public void listen(String in) {
    ...
}

这样避免了仅仅为了更改转换器而必须声明不同的容器工厂。

在大多数情况下,无需自定义方法参数转换器,除非例如您想要使用自定义ConversionService

在 1.6 之前的版本中,必须在消息头中提供用于转换 JSON 的类型信息,或者需要自定义ClassMapper。从 1.6 版本开始,如果没有类型信息头,则可以从目标方法参数推断类型。

此类型推断仅适用于方法级别的@RabbitListener

有关更多信息,请参见Jackson2JsonMessageConverter

如果您希望自定义方法参数转换器,可以按如下方式操作

@Configuration
@EnableRabbit
public class AppConfig implements RabbitListenerConfigurer {

    ...

    @Bean
    public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        factory.setMessageConverter(new GenericMessageConverter(myConversionService()));
        return factory;
    }

    @Bean
    public DefaultConversionService myConversionService() {
        DefaultConversionService conv = new DefaultConversionService();
        conv.addConverter(mySpecialConverter());
        return conv;
    }

    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
    }

    ...

}
对于多方法监听器(请参见多方法监听器),方法选择基于消息转换**之后**的消息负载。只有在选择方法后才会调用方法参数转换器。