AMQP 消息头
概述
Spring Integration AMQP 适配器会自动映射所有 AMQP 属性和头信息。(这与 4.3 版本有所不同——之前,只有标准头信息会被映射)。默认情况下,这些属性是通过使用 DefaultAmqpHeaderMapper 复制到 Spring Integration MessageHeaders 和从 MessageHeaders 复制的。
你可以传入自己实现的 AMQP 特定头映射器,因为适配器具有支持这样做的属性。
AMQP MessageProperties 中的任何用户定义的头信息都会复制到 AMQP 消息中或从 AMQP 消息中复制出来,除非被 DefaultAmqpHeaderMapper 的 requestHeaderNames 或 replyHeaderNames 属性明确否定。默认情况下,对于出站映射器,不映射任何 x-* 头信息。有关原因,请参阅本节后面出现的注意事项。
要覆盖默认行为并恢复到 4.3 之前的 behavior,请在属性中使用 STANDARD_REQUEST_HEADERS 和 STANDARD_REPLY_HEADERS。
在映射用户定义的标头时,值也可以包含简单的通配符模式(例如 thing* 或 *thing)进行匹配。* 匹配所有标头。
从 4.1 版本开始,AbstractHeaderMapper(DefaultAmqpHeaderMapper 的父类)允许为 requestHeaderNames 和 replyHeaderNames 属性配置 NON_STANDARD_HEADERS 标记(除了现有的 STANDARD_REQUEST_HEADERS 和 STANDARD_REPLY_HEADERS),以映射所有用户定义的头信息。
org.springframework.amqp.support.AmqpHeaders 类标识了 DefaultAmqpHeaderMapper 使用的默认头信息:
- 
amqp_appId
- 
amqp_clusterId
- 
amqp_contentEncoding
- 
amqp_contentLength
- 
content-type(see The contentType Header)
- 
amqp_correlationId
- 
amqp_delay
- 
amqp_deliveryMode
- 
amqp_deliveryTag
- 
amqp_expiration
- 
amqp_messageCount
- 
amqp_messageId
- 
amqp_receivedDelay
- 
amqp_receivedDeliveryMode
- 
amqp_receivedExchange
- 
amqp_receivedRoutingKey
- 
amqp_redelivered
- 
amqp_replyTo
- 
amqp_timestamp
- 
amqp_type
- 
amqp_userId
- 
amqp_publishConfirm
- 
amqp_publishConfirmNackCause
- 
amqp_returnReplyCode
- 
amqp_returnReplyText
- 
amqp_returnExchange
- 
amqp_returnRoutingKey
- 
amqp_channel
- 
amqp_consumerTag
- 
amqp_consumerQueue
如本节前面所述,使用 * 作为头部映射模式是一种常见的复制所有头部的方法。但是,这可能会产生一些意外的副作用,因为某些 RabbitMQ 专有属性/头部也会被复制。例如,当您使用 联合时,接收到的消息可能有一个名为 x-received-from 的属性,其中包含发送消息的节点。如果您在入站网关的请求和回复头部映射中使用通配符 *,此头部将被复制,这可能会导致联合的一些问题。此回复消息可能会被联合回发送代理,该代理可能会认为消息正在循环,并因此默默地丢弃它。如果您希望使用通配符头部映射的便利性,您可能需要在下游流程中过滤掉一些头部。例如,为了避免将 x-received-from 头部复制回回复,您可以在将回复发送到 AMQP 入站网关之前使用 <int:header-filter … header-names="x-received-from">。或者,您可以明确列出那些您实际想要映射的属性,而不是使用通配符。由于这些原因,默认情况下,对于入站消息,映射器不会映射任何 x-* 头部。它也不会将 deliveryMode 映射到 amqp_deliveryMode 头部,以避免从入站消息传播到出站消息。相反,此头部被映射到 amqp_receivedDeliveryMode,在输出时不进行映射。
从 4.3 版本开始,可以通过在模式前加上 ! 来否定标头映射中的模式。否定的模式具有优先权,因此像 STANDARD_REQUEST_HEADERS,thing1,ba*,!thing2,!thing3,qux,!thing1 这样的列表不会映射 thing1(也不会映射 thing2 或 thing3)。标准标头加上 bad 和 qux 将被映射。否定技术可用于例如不为传入消息映射 JSON 类型标头,当 JSON 反序列化逻辑在下游接收方以不同方式处理时。为此目的,应为入站通道适配器/网关的标头映射器配置 !json_* 模式。
如果你有一个以 ! 开头的自定义标题,并且你希望映射它,则需要用 \ 转义它,如下所示:STANDARD_REQUEST_HEADERS,\!myBangHeader。名为 !myBangHeader 的标题现在已被映射。
从 5.1 版开始,DefaultAmqpHeaderMapper 将回退到将 MessageHeaders.ID 和 MessageHeaders.TIMESTAMP 映射到 MessageProperties.messageId 和 MessageProperties.timestamp,如果传出消息中不存在对应的 amqp_messageId 或 amqp_timestamp 标头。传入属性将像以前一样映射到 amqp_* 标头。当消息消费者使用有状态重试时,填充 messageId 属性是有用的。
contentType 标签
与其他头不同,AmqpHeaders.CONTENT_TYPE 不以 amqp_ 为前缀;这允许跨不同技术透明传递 contentType 头。例如,发送到 RabbitMQ 队列的入站 HTTP 消息。
contentType 标头映射到 Spring AMQP 的 MessageProperties.contentType 属性,然后该属性再映射到 RabbitMQ 的 content_type 属性。
在 5.1 版本之前,此头部还被映射为 MessageProperties.headers 地图中的一个条目;这是不正确的,而且该值可能是错误的,因为底层的 Spring AMQP 消息转换器可能会更改内容类型。这种更改会反映在一流的 content_type 属性中,但不会反映在 RabbitMQ 头部地图中。入站映射忽略了头部地图中的值。contentType 不再映射到头部地图中的条目。