我有两个组件(分别称为生产者和消费者)连接到同一RabbitMQ基于主题的交换。
生产者可以发送两种不同的消息类型; Foo
和Bar
(每条消息的内容无关紧要,但我们都说它们都具有一个id
字段)。用于每个消息的路由密钥分别为msg.foo
和msg.bar
。生产者没有使用默认的Java序列化,而是使用Jackson2JsonMessageConverter
。
使用者有一个队列,该队列使用msg.#
的路由键绑定到同一交换机。一旦使用完毕,所有使用者将要做的就是在日志文件中打印每条消息的id
。为了检索id
字段的值,需要将JSON有效负载转换为某种对象。
这两个组件之间没有共享消息类(Foo
和Bar
)。消费者的对象在其消息表示中可能具有更多或更少的字段。很好,在这种情况下,任何空字段都可以设置为null。
是否存在一种优雅的方法将这些消息从JSON转换/序列化为Foo
和Bar
类型的对象?我唯一能想到的解决方案是手动编写读取amqp_receivedRoutingKey
或json__TypeId__
标头的代码,以确定对象类型。示例:
@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();
}
不幸的是,由于重复使用if
/ else
子句,因此非常不完整,也很丑陋。我是否缺少任何Spring Integration技巧,这些技巧会使我的代码更具可读性?
我设法找到了一个类似的问题(spring boot rabbitmq MappingJackson2MessageConverter custom object conversion),但是除了解决方案不起作用之外,它还是RabbitMQ特有的。我宁愿不熟悉RabbitMQ,并尽可能使用标准AMQP类/导入。
答案 0 :(得分:0)
您似乎错过了Jackson2JsonMessageConverter
填充AMQP消息中相应标题的事实。并且可以依靠这些标头在消费者端恢复POJO。
因此,请考虑同时为Amqp.inboundAdapter(connectionFactory, queue)
配置Jackson2JsonMessageConverter
。
在文档中查看有关转换器的更多信息:https://docs.spring.io/spring-amqp/docs/2.2.0.RC1/reference/html/#json-message-converter