我一直致力于使用AMQP在两个微服务之间设置异步消息传递的“铺平道路”。我们希望促进为每个服务使用单独的域对象,这意味着每个服务必须定义自己通过队列传递的任何对象的副本。
我们在生产者和消费者方都使用Jackson2JsonMessageConverter
,我们正在使用Java DSL将流量连接到队列或从队列连接。
我确信有一种方法可以做到这一点,但它正在逃避我:我希望消费者方忽略从生产者传递的__TypeID__
标题,因为消费者可能有不同的表示形式那个事件(它可能会在不同的java包中)。
似乎已完成工作,如果使用注释@RabbitListener
,则会派生inferredArgumentType
参数并覆盖标题信息。这正是我想要做的,但我想使用Java DSL来做。我还没有找到一个干净的方式来做这件事,也许我只是遗漏了一些明显的东西。在使用以下DSL时,似乎可以直接推导出类型:
return IntegrationFlows
.from(
Amqp.inboundAdapter(factory, queueRemoteTaskStatus())
.concurrentConsumers(10)
.errorHandler(errorHandler)
.messageConverter(messageConverter)
)
.channel(channelRemoteTaskStatusIn())
.handle(listener, "handleRemoteTaskStatus")
.get();
但是,这会导致ClassNotFound
异常。到目前为止,我找到解决此问题的唯一方法是设置自定义消息转换器,这需要明确定义类型。
public class ForcedTypeJsonMessageConverter extends Jackson2JsonMessageConverter {
ForcedTypeJsonMessageConverter(final Class<?> forcedType) {
setClassMapper(new ClassMapper() {
@Override
public void fromClass(Class<?> clazz, MessageProperties properties) {
//this class is only used for inbound marshalling.
}
@Override
public Class<?> toClass(MessageProperties properties) {
return forcedType;
}
});
}
}
我真的希望这是派生的,所以开发人员不必真正处理这个问题。
有更简单的方法吗?
答案 0 :(得分:1)
最简单的方法是使用DefaultJackson2JavaTypeMapper
(TypeIdMapping
)配置Jackson转换器的setIdClassMapping()
。
在发送系统上,映射foo:com.one.Foo
和接收系统地图foo:com.two.Foo
。
然后,__TypeId__
标头获得foo
,接收系统会将其映射到Foo
的表示。
修改强>
另一种选择是将afterReceiveMessagePostProcessor
添加到入站通道适配器的侦听器容器中 - 它可以更改__TypeId__
标头。