【问题标题】:Spring Integration - AMQP Inferred Types In Java DSL?Spring 集成 - Java DSL 中的 AMQP 推断类型?
【发布时间】:2017-12-22 19:22:36
【问题描述】:

我一直在为使用 AMQP 在两个微服务之间建立异步消息传递“铺平道路”。我们希望促进对每个服务使用单独的域对象,这意味着每个服务必须定义自己的跨队列传递的任何对象的副本。

我们在生产者和消费者端都使用Jackson2JsonMessageConverter,并且我们使用 Java DSL 将流与队列连接起来。

我确信有办法做到这一点,但它让我无法理解:我希望消费者端忽略从生产者传递的 __TypeID__ 标头,因为消费者可能对该事件有不同的表示(它很可能在不同的 java 包中)。

似乎已经完成了一些工作,如果使用注释@RabbitListener,则派生inferredArgumentTypeargument 并将覆盖标头信息。这正是我想做的,但我想使用 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;
            }
        });
    }
}

我真的很想派生这个,所以开发人员不必真正处理这个问题。

有没有更简单的方法来做到这一点?

【问题讨论】:

  • 抱歉,我遗漏了一些东西,但我看不出在该流定义中如何“直截了当地”推导出类型?谢谢
  • 在转换器的类型映射器中使用类型 ID 映射 (setIdClassMapping)。看我的回答。
  • 我猜“直截了当”是错误的术语,如果内容类型是 application/json,我正在寻找类型的隐式处理,而不必为特定类型显式定义映射策略。这与此处讨论的想法相似:github.com/spring-cloud/spring-cloud-stream/issues/156。如果我删除了生产者端的 typeId,只留下应用程序/json,那么“开箱即用”编组会很好。
  • 类型如何隐含在消息流中?通过@RabbitListener,我们知道方法参数的类型。在使用入站负载创建通用消息时,无法推断负载的类型,因为创建消息的组件与使用消息的方法完全分离。因此,您必须使用负载类型的某种提示来配置转换器。我在答案中添加了另一个选项。
  • 感谢完全有道理,感谢您的解释

标签: spring-integration spring-integration-dsl


【解决方案1】:

最简单的方法是将 Jackson 转换器的 DefaultJackson2JavaTypeMapper 配置为 TypeIdMapping (setIdClassMapping())。

在发送系统上映射foo:com.one.Foo,在接收系统上映射foo:com.two.Foo

然后,__TypeId__ 标头得到 foo,接收系统会将其映射到 Foo 的表示形式。

编辑

另一种选择是将afterReceiveMessagePostProcessor 添加到入站通道适配器的侦听器容器中 - 它可以更改__TypeId__ 标头。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-03
    • 2020-07-11
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2020-11-06
    相关资源
    最近更新 更多