Outbound Message Conversion

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

Spring AMQP 1.4 introduced the ContentTypeDelegatingMessageConverter, where the actual converter is selected based on the incoming content type message property. This can be used by inbound endpoints.

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

As of Spring Integration version 4.3, you can use the ContentTypeDelegatingMessageConverter on outbound endpoints as well, with the contentType header specifying which converter is used.

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

The following example configures a ContentTypeDelegatingMessageConverter, with the default converter being the SimpleMessageConverter (which handles Java serialization and plain text), together with a JSON converter:

<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 转换器。

Sending a message to ctRequestChannel with the contentType header set to application/json causes the JSON converter to be selected.

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

This applies to both the outbound channel adapter and gateway.

从版本 5.0 开始,添加到出站消息的`MessageProperties`中的标头绝不会被映射标头覆盖(默认情况下)。以前,只有当消息转换器是`ContentTypeDelegatingMessageConverter`时才会出现这种情况(在这种情况下,标头会首先映射,以便可以选择正确的转换器)。对于其他转换器(例如`SimpleMessageConverter`),映射标头会覆盖转换器添加的任何标头。当出站消息有一些残留的`contentType`标头时(可能来自入站通道适配器),却错误地覆盖了正确的出站`contentType`时,这会造成问题。解决方法是在向出站端点发送消息之前使用标头过滤器删除该标头。

Starting with version 5.0, headers that are added to the MessageProperties of the outbound message are never overwritten by mapped headers (by default). Previously, this was only the case if the message converter was a ContentTypeDelegatingMessageConverter (in that case, the header was mapped first so that the proper converter could be selected). For other converters, such as the SimpleMessageConverter, mapped headers overwrote any headers added by the converter. This caused problems when an outbound message had some leftover contentType headers (perhaps from an inbound channel adapter) and the correct outbound contentType was incorrectly overwritten. The work-around was to use a header filter to remove the header before sending the message to the outbound endpoint.

然而,在某些情况下希望保留以前的行为——例如,当包含 JSON 的`String`有效负载时,SimpleMessageConverter`不会识别该内容,并会将`contentType`消息属性设置为`text/plain,但您的应用程序希望通过设置发送到出站端点的消息的`contentType`标头将其覆盖为 application/json。`ObjectToJsonTransformer`会执行此操作(默认情况下)。

There are, however, cases where the previous behavior is desired — for example, when a String payload that contains JSON, the SimpleMessageConverter is not aware of the content and sets the contentType message property to text/plain but your application would like to override that to application/json by setting the contentType header of the message sent to the outbound endpoint. The ObjectToJsonTransformer does exactly that (by default).

现在,出站通道适配器和网关(以及基于 AMQP 的通道)上有一个名为`headersMappedLast`的属性。将其设置为`true`可以恢复覆盖转换器添加的属性的行为。

There is now a property called headersMappedLast on the outbound channel adapter and gateway (as well as on AMQP-backed channels). Setting this to true restores the behavior of overwriting the property added by the converter.

从版本 5.1.9 开始,当我们生成回复并且希望覆盖转换器填充的标头时,为`AmqpInboundGateway`提供了一个类似的`replyHeadersMappedLast`。有关详细信息,请参阅其 JavaDocs。

Starting with version 5.1.9, a similar replyHeadersMappedLast is provided for the AmqpInboundGateway when we produce a reply and would like to override headers populated by the converter. See its JavaDocs for more information.