跳到主要内容

注解方法的消息转换

DeepSeek V3 中英对照 Message Conversion for Annotated Methods

在调用监听器之前,管道中有两个转换步骤。第一步使用 MessageConverter 将传入的 Spring AMQP Message 转换为 Spring-messaging 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;
}
java

这将配置一个 Jackson2 转换器,该转换器期望存在头部信息以指导转换。

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

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

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

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

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

在大多数情况下,不需要自定义方法参数转换器,除非,例如,你想要使用自定义的 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());
}

...

}
java
important

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