出站消息转换

Spring AMQP 1.4 引入了ContentTypeDelegatingMessageConverter,其中实际的转换器是根据传入的 content type 消息属性选择的。这可以被入站端点使用。

从 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 获取更多信息。