简体   繁体   English

RabbitMQ + Spring集成:从队列绑定到主题交换的消息转换

[英]RabbitMQ + Spring Integration: Message conversion from queue bound to a topic exchange

I have two components (let's call them producer and consumer) connected to the same RabbitMQ topic-based exchange. 我有两个组件(我们称之为生产者和消费者)连接到同一RabbitMQ基于主题的交换。

The producer can send two different message types; 生产者可以发送两种不同的消息类型; Foo and Bar (contents of each message is irrelevant, but let's just say that they both have an id field). FooBar (每条消息的内容无关紧要,但我们都说它们都有一个id字段)。 The routing key used for each message is msg.foo and msg.bar respectively. 用于每个消息的路由密钥分别是msg.foomsg.bar Rather than relying on the default Java serialization, the producer is using the Jackson2JsonMessageConverter . 生产者没有使用默认的Java序列化,而是使用Jackson2JsonMessageConverter

The consumer has a queue which is bound to the same exchange with a routing key of msg.# . 使用者有一个队列,该队列使用msg.#的路由密钥绑定到同一交换机。 Once consumed, all the consumer will want to do is print the id of each message in a log file. 一旦使用完,所有使用者将要做的就是在日志文件中打印每条消息的id In order to retrieve the value for the id field, the JSON payload needs to be transformed into some sort of object. 为了检索id字段的值,需要将JSON有效负载转换为某种对象。

The message classes ( Foo and Bar ) are not shared between the two components. 这两个组件之间不共享消息类( FooBar )。 The consumer's objects may have more or less fields in its representation of the message. 消费者的对象在其消息表示中可能具有更多或更少的字段。 This is fine, in that case any empty fields may be set to null. 很好,在这种情况下,任何空字段都可以设置为null。

Is there an elegant way to convert/serialize these messages from JSON to objects of type Foo and Bar ? 是否有一种优雅的方法将这些消息从JSON转换/序列化为FooBar类型的对象? The only solution I can come up with is to manually write code which reads the amqp_receivedRoutingKey or the json__TypeId__ headers in order to determine the object type. 我唯一能想到的解决方案是手动编写代码,以读取amqp_receivedRoutingKeyjson__TypeId__标头,以确定对象类型。 Example: 例:

@Bean
public IntegrationFlow inbound(ConnectionFactory connectionFactory, Queue queue) {
    return IntegrationFlows.from(Amqp.inboundAdapter(connectionFactory, queue))
        .handle(message -> {
            final byte[] payload = (byte[]) message.getPayload();
            final String payloadStr = new String(payload, Charset.defaultCharset());

            final String routingKey = (String) message.getHeaders().get("amqp_receivedRoutingKey");

            try {
                if (routingKey.equals("msg.foo")) {
                    final Foo foo = new Jackson2JsonObjectMapper().fromJson(payloadStr, Foo.class);

                    System.out.println("FOO id: " + foo.getId());
                } else if (routingKey.equals("msg.bar")) {
                    final Bar bar = new Jackson2JsonObjectMapper().fromJson(payloadStr, Bar.class);

                    System.out.println("BAR id: " + bar.getId());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        })
        .get();
}

Unfortunately is quite flaky and also quite ugly due to the repeated if / else clauses. 不幸的是,由于重复的if / else子句,它非常脆弱而且丑陋。 Are there any Spring Integration tricks I am missing which would make my code more readable? 我是否缺少任何Spring Integration技巧,这些技巧会使我的代码更具可读性?

I managed to find a similar question ( spring boot rabbitmq MappingJackson2MessageConverter custom object conversion ) but apart from the solution not working, it is very RabbitMQ specific. 我设法找到了一个类似的问题( 春季启动Rabbitmq MappingJackson2MessageConverter定制对象转换 ),但是除了解决方案不起作用之外,它还是RabbitMQ特有的。 I would rather be RabbitMQ agnostic and use standard AMQP classes/imports where possible. 我宁愿不熟悉RabbitMQ,并在可能的情况下使用标准AMQP类/导入。

It looks like you are missing the fact that Jackson2JsonMessageConverter populates appropriate headers in the AMQP message. 看起来您似乎缺少Jackson2JsonMessageConverter在AMQP消息中填充适当标头的事实。 And this one can reinstate POJO on the consumer side relying on those headers. 而且,该程序可以依靠这些标头在用户端恢复POJO。

So, consider to configure your Amqp.inboundAdapter(connectionFactory, queue) with a Jackson2JsonMessageConverter as well. 因此,考虑到配置Amqp.inboundAdapter(connectionFactory, queue)Jackson2JsonMessageConverter为好。

See more info about converter in the Docs: https://docs.spring.io/spring-amqp/docs/2.2.0.RC1/reference/html/#json-message-converter 在文档中查看有关转换器的更多信息: https : //docs.spring.io/spring-amqp/docs/2.2.0.RC1/reference/html/#json-message-converter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM