出站消息转换

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 被错误覆盖时,这会导致问题。解决方法是使用头过滤器在将消息发送到出站端点之前移除该头。

但是,在某些情况下需要先前的行为——例如,当 String 载荷包含 JSON 时,SimpleMessageConverter 并不知道内容,并将 contentType 消息属性设置为 text/plain,但您的应用程序希望通过设置发送到出站端点的消息的 contentType 头来将其覆盖为 application/jsonObjectToJsonTransformer 默认就是这样做的。

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

从 5.1.9 版本开始,当产生回复并希望覆盖由转换器填充的头时,为 AmqpInboundGateway 提供了一个类似的 replyHeadersMappedLast 属性。有关更多信息,请参阅其 JavaDocs。