在 RabbitMQ 中,@Header
是 Spring AMQP 提供的一种注解,用于从消息的 Headers 中提取特定的属性或元数据。通过 @Header
,开发者可以方便地获取消息的附加信息(如路由键、消息标签、自定义头等),而无需手动解析消息的完整结构。
以下是对 @Header
的原理机制和用法的详细说明:
1. @Header
的作用
@Header
注解用于从消息的 Headers 中提取指定的属性值,并将其注入到方法参数中。它通常用于以下场景:
- 获取消息的元数据(如
deliveryTag
、routingKey
等)。 - 获取自定义的 Header 值。
- 获取死信队列的附加信息(如
x-death
)。
2. @Header
的原理
在 Spring AMQP 中,@Header
的工作原理如下:
- 消息接收:
当消费者接收到消息时,Spring AMQP 会将消息的 Headers 解析为一个Map<String, Object>
结构。 - 参数绑定:
在方法调用时,Spring AMQP 会根据@Header
注解指定的名称,从 Headers 中提取对应的值,并将其绑定到方法参数上。 - 类型转换:
Spring AMQP 会自动将提取的值转换为方法参数的类型(如String
、Long
、List
等)。
3. @Header
的用法
(1)获取内置 Header
RabbitMQ 消息的 Headers 中包含一些内置属性,可以通过 @Header
直接获取。例如:
AmqpHeaders.DELIVERY_TAG
:消息的唯一标识(deliveryTag
),用于手动确认消息。AmqpHeaders.RECEIVED_ROUTING_KEY
:消息的路由键。AmqpHeaders.CONSUMER_QUEUE
:消息所在的队列名称。
示例:
@RabbitHandler
public void onMessage(String message,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
@Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey) {
System.out.println("Received message: " + message);
System.out.println("Delivery tag: " + deliveryTag);
System.out.println("Routing key: " + routingKey);
}
(2)获取自定义 Header
如果消息中包含自定义的 Header,可以通过 @Header
提取。
示例:
@RabbitHandler
public void onMessage(String message,
@Header("custom-header") String customHeader) {
System.out.println("Received message: " + message);
System.out.println("Custom header: " + customHeader);
}
(3)获取死信队列的 x-death
信息
当消息被转发到死信队列时,RabbitMQ 会在 Headers 中添加 x-death
属性,记录消息的死信原因和原始队列信息。
示例:
@RabbitHandler
public void onAmusementMsg(String message,
@Header("x-death") List<Map<String, Object>> death) {
System.out.println("Received dead letter message: " + message);
if (death != null) {
for (Map<String, Object> deathRecord : death) {
System.out.println("Death reason: " + deathRecord.get("reason"));
System.out.println("Original queue: " + deathRecord.get("queue"));
}
}
}
4. x-death
的结构
x-death
是一个 List<Map<String, Object>>
结构,每个 Map
代表一条死信记录。常见的字段包括:
reason
:死信原因(如expired
、rejected
等)。queue
:原始队列名称。exchange
:原始交换机名称。routing-keys
:原始路由键。time
:消息死亡时间。
示例 x-death
内容:
[
{
"reason": "expired",
"queue": "order.queue",
"exchange": "order.exchange",
"routing-keys": ["order.create"],
"time": "2023-10-01T12:00:00Z"
}
]
5. 注意事项
- Header 名称区分大小写:
确保@Header
注解中的名称与消息 Header 中的名称完全一致。 - 默认值:
如果指定的 Header 不存在,方法参数会设置为null
。可以通过@Header(name = "headerName", required = false)
设置非必填。 - 类型匹配:
确保方法参数的类型与 Header 值的类型兼容,否则会抛出类型转换异常。
6. 完整示例
以下是一个完整的示例,展示如何使用 @Header
获取消息的 deliveryTag
和 x-death
信息:
@RabbitListener(queues = "myQueue")
public class MyMessageListener {
@RabbitHandler
public void onAmusementMsg(String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long tag,
@Header("x-death") List<Map<String, Object>> death) {
try {
System.out.println("Received message: " + message);
System.out.println("Delivery tag: " + tag);
if (death != null) {
for (Map<String, Object> deathRecord : death) {
System.out.println("Death reason: " + deathRecord.get("reason"));
System.out.println("Original queue: " + deathRecord.get("queue"));
}
}
// 手动确认消息
channel.basicAck(tag, false);
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结
@Header
是 Spring AMQP 提供的一种便捷方式,用于从消息的 Headers 中提取元数据或自定义属性。- 通过
@Header
,可以轻松获取消息的deliveryTag
、routingKey
、x-death
等信息。 - 结合
@RabbitHandler
和@RabbitListener
,可以实现灵活的消息处理逻辑。
通过合理使用 @Header
,可以简化代码并提高消息处理的灵活性和可维护性。