Outbound Message Conversion

Spring AMQP 1.4 引入了`ContentTypeDelegatingMessageConverter`,该转换器会根据传入的内容类型消息属性选择实际转换器。传入端点可以使用此转换器。

从 Spring Integration 版本 4.3 开始,您还可以将`ContentTypeDelegatingMessageConverter`用于出站端点,其中`contentType`标头指定要使用的转换器。

以下示例配置了一个`ContentTypeDelegatingMessageConverter`,默认转换器为`SimpleMessageConverter`(该转换器处理 Java 序列化和纯文本),还配置了一个 JSON 转换器:

<amqp:outbound-channel-adapter id="withContentTypeConverter" channel="ctRequestChannel"
                               exchange-name="someExchange"
                               routing-key="someKey"
                               amqp-template="amqpTemplateContentTypeConverter" />

<int:channel id="ctRequestChannel"/>

<rabbit:template id="amqpTemplateContentTypeConverter"
        connection-factory="connectionFactory" message-converter="ctConverter" />

<bean id="ctConverter"
        class="o.s.amqp.support.converter.ContentTypeDelegatingMessageConverter">
    <property name="delegates">
        <map>
            <entry key="application/json">
                <bean class="o.s.amqp.support.converter.Jackson2JsonMessageConverter" />
            </entry>
        </map>
    </property>
</bean>

向`ctRequestChannel`发送一条消息,并将`contentType`标头设置为`application/json`,会选择 JSON 转换器。

这适用于出站通道适配器和网关。

从版本 5.0 开始,添加到出站消息的`MessageProperties`中的标头绝不会被映射标头覆盖(默认情况下)。以前,只有当消息转换器是`ContentTypeDelegatingMessageConverter`时才会出现这种情况(在这种情况下,标头会首先映射,以便可以选择正确的转换器)。对于其他转换器(例如`SimpleMessageConverter`),映射标头会覆盖转换器添加的任何标头。当出站消息有一些残留的`contentType`标头时(可能来自入站通道适配器),却错误地覆盖了正确的出站`contentType`时,这会造成问题。解决方法是在向出站端点发送消息之前使用标头过滤器删除该标头。 然而,在某些情况下希望保留以前的行为——例如,当包含 JSON 的`String`有效负载时,SimpleMessageConverter`不会识别该内容,并会将`contentType`消息属性设置为`text/plain,但您的应用程序希望通过设置发送到出站端点的消息的`contentType`标头将其覆盖为 application/jsonObjectToJsonTransformer`会执行此操作(默认情况下)。 现在,出站通道适配器和网关(以及基于 AMQP 的通道)上有一个名为`headersMappedLast`的属性。将其设置为`true`可以恢复覆盖转换器添加的属性的行为。 从版本 5.1.9 开始,当我们生成回复并且希望覆盖转换器填充的标头时,为`AmqpInboundGateway`提供了一个类似的`replyHeadersMappedLast。有关详细信息,请参阅其 JavaDocs。