如何更改消息类型检测策略?
How to change message type detection strategy?
我在应用程序 A 中使用自定义 RabbitMQ 客户端,在应用程序 B 中使用 Spring Amqp Library
。
我遇到了一个问题:如何决定 @RabbitListener
用于不同的消息类型?
问题:
我从应用程序 A 向应用程序 B 发送自定义消息。在一条消息中,我设置了自定义 header “类型” - 它不是默认值 属性 也不是默认值 Spring Amqp Header (这是“_ _ TypeId _ _”)——只是一个新的自定义 header。
在应用程序 B (spring amqp) 中,我必须决定使用哪个侦听器。据我了解,Spring Amqp 使用“_ _ TypeId _ _”作为“消息类型检测策略”的默认机制(我不知道如何正确调用它),但我想使用我自己的“策略” ”.
我找到了下一个技巧,但它看起来很奇怪而且不明显:
private void determineMessageType(Message message) {
MessageProperties props = message.getMessageProperties();
Map<String, Object> headers = props.getHeaders();
final String type = String.valueOf(headers.get("type"));
if ("popularity-report".equals(type)) {
props.getHeaders().put("__TypeId__",
PopularityReportCommand.class.getName());
}
}
我可以为 Spring Amqp 应用程序使用自定义类型检测策略吗?或者如何在 Spring Amqp 中正确解决这些问题?
提到的 _ _ TypeId _ _
仅用于 JSON 消息转换器。因此,如果在您真正从该制作人发送的部分中确实是您的情况,那么您可以查看 AbstractJackson2MessageConverter.setJavaTypeMapper(Jackson2JavaTypeMapper)
。默认的 DefaultJackson2JavaTypeMapper
有一个 属性 像这样:
public String getClassIdFieldName() {
return DEFAULT_CLASSID_FIELD_NAME;
}
这就是上面提到的名字:
public static final String DEFAULT_CLASSID_FIELD_NAME = "__TypeId__";
因此,如果您能够扩展此 DefaultJackson2JavaTypeMapper
并为您的自定义 header 映射器覆盖 getter,那么 Jackson2JsonMessageConverter
可以正确转换传入 JSON 数据转换为您的自定义 header 呈现的所需类型。然后 @RabbitListener
将接受该值。
但您仍然需要确保该映射器上的 typePrecedence
设置为 TYPE_ID
:
/**
* Set the precedence for evaluating type information in message properties.
* When using {@code @RabbitListener} at the method level, the framework attempts
* to determine the target type for payload conversion from the method signature.
* If so, this type is provided in the
* {@link MessageProperties#getInferredArgumentType() inferredArgumentType}
* message property.
* <p>
* By default, if the type is concrete (not abstract, not an interface), this will
* be used ahead of type information provided in the {@code __TypeId__} and
* associated headers provided by the sender.
* <p>
* If you wish to force the use of the {@code __TypeId__} and associated headers
* (such as when the actual type is a subclass of the method argument type),
* set the precedence to {@link Jackson2JavaTypeMapper.TypePrecedence#TYPE_ID}.
*
* @param typePrecedence the precedence.
* @since 1.6
*/
public void setTypePrecedence(TypePrecedence typePrecedence) {
否则它会参考 @RabbitListener
方法签名。
我在应用程序 A 中使用自定义 RabbitMQ 客户端,在应用程序 B 中使用 Spring Amqp Library
。
我遇到了一个问题:如何决定 @RabbitListener
用于不同的消息类型?
问题: 我从应用程序 A 向应用程序 B 发送自定义消息。在一条消息中,我设置了自定义 header “类型” - 它不是默认值 属性 也不是默认值 Spring Amqp Header (这是“_ _ TypeId _ _”)——只是一个新的自定义 header。
在应用程序 B (spring amqp) 中,我必须决定使用哪个侦听器。据我了解,Spring Amqp 使用“_ _ TypeId _ _”作为“消息类型检测策略”的默认机制(我不知道如何正确调用它),但我想使用我自己的“策略” ”.
我找到了下一个技巧,但它看起来很奇怪而且不明显:
private void determineMessageType(Message message) {
MessageProperties props = message.getMessageProperties();
Map<String, Object> headers = props.getHeaders();
final String type = String.valueOf(headers.get("type"));
if ("popularity-report".equals(type)) {
props.getHeaders().put("__TypeId__",
PopularityReportCommand.class.getName());
}
}
我可以为 Spring Amqp 应用程序使用自定义类型检测策略吗?或者如何在 Spring Amqp 中正确解决这些问题?
提到的 _ _ TypeId _ _
仅用于 JSON 消息转换器。因此,如果在您真正从该制作人发送的部分中确实是您的情况,那么您可以查看 AbstractJackson2MessageConverter.setJavaTypeMapper(Jackson2JavaTypeMapper)
。默认的 DefaultJackson2JavaTypeMapper
有一个 属性 像这样:
public String getClassIdFieldName() {
return DEFAULT_CLASSID_FIELD_NAME;
}
这就是上面提到的名字:
public static final String DEFAULT_CLASSID_FIELD_NAME = "__TypeId__";
因此,如果您能够扩展此 DefaultJackson2JavaTypeMapper
并为您的自定义 header 映射器覆盖 getter,那么 Jackson2JsonMessageConverter
可以正确转换传入 JSON 数据转换为您的自定义 header 呈现的所需类型。然后 @RabbitListener
将接受该值。
但您仍然需要确保该映射器上的 typePrecedence
设置为 TYPE_ID
:
/**
* Set the precedence for evaluating type information in message properties.
* When using {@code @RabbitListener} at the method level, the framework attempts
* to determine the target type for payload conversion from the method signature.
* If so, this type is provided in the
* {@link MessageProperties#getInferredArgumentType() inferredArgumentType}
* message property.
* <p>
* By default, if the type is concrete (not abstract, not an interface), this will
* be used ahead of type information provided in the {@code __TypeId__} and
* associated headers provided by the sender.
* <p>
* If you wish to force the use of the {@code __TypeId__} and associated headers
* (such as when the actual type is a subclass of the method argument type),
* set the precedence to {@link Jackson2JavaTypeMapper.TypePrecedence#TYPE_ID}.
*
* @param typePrecedence the precedence.
* @since 1.6
*/
public void setTypePrecedence(TypePrecedence typePrecedence) {
否则它会参考 @RabbitListener
方法签名。