我想知道Spring AMQP是否有可能在多个类中接收来自同一队列的消息,具体取决于有效负载类型。
我知道在类中使用@RabbitListener注释,然后在方法上放置@RabbitHandler,但我想在保留单个队列的同时将多个类中的消息处理的复杂性分开。
目前正在使用的版本:Spring AMQP v2.0.3以及RabbitMQ。
答案 0 :(得分:2)
嗯,这是不可能的。您希望它的方式不会成为队列。
这实际上是设计单个侦听器并根据payload
类型分发到其方法的架构决策。
作为一种解决方法,我建议您将逻辑从单个@RabbitListener
类委托给这些业务服务:
@RabbitListener(queues = "foo")
public class MyListener {
private final ServiceA serviceA;
private final ServiceB serviceB;
public MyListener(ServiceA serviceA, ServiceB serviceB) {
this.serviceA = serviceA;
this.serviceB = serviceB;
}
@RabbitHandler
public void handleA(A a) {
this.serviceA.handle(a);
}
@RabbitHandler
public void handleB(B b) {
this.serviceB.handle(b);
}
}
答案 1 :(得分:0)
是的,但是需要一些不同的方法: 您需要监听通用的消息类型,进行一些切换以及自己的反序列化。您当然可以完全将该代码隐藏在某个地方(基类,注释...)
下面的示例可以扩展为收听其他类型的声音。 上面的示例将过滤A和B DTO类型。
void receive(ADTO dto)
{
System.out.print(dto.url);
}
void receive(BDTO dto)
{
System.out.print(dto.url);
}
@RabbitListener(queues = "your.queue.name")
public void listenMesssage(Message message)
{
try
{
String typeId = message.getMessageProperties().getHeaders().get("__TypeId__").toString();
String contentType = message.getMessageProperties().getContentType();
if (contentType != "application/json" || typeId == null || !typeId.contains(ADTO.class.toString()))
{
//TODO log warning
System.out.print("type not supported by this service");
return;
}
Object receivedObject = new Jackson2JsonMessageConverter().fromMessage(message);
if (receivedObject instanceof ADTO)
{
receive((ADTO)receivedObject);
System.out.print("ADTO");
}
//else
或者,您也可以像这样进行序列化:
....
String typeId = message.getMessageProperties().getHeaders().get("__TypeId__").toString();
byte[] binMsg = message.getBody();
String strMsg = new String(binMsg, StandardCharsets.UTF_8);
ObjectMapper mapper = new ObjectMapper();
if (typeId.contains("ADTO"))
{
receive(mapper.readValue(strMsg, ADTO.class ));
}
else
...
答案 2 :(得分:0)
或者,我发现,如果您的AQMP和Rabbit版本足够高 (mine = spring-rabit 2.1.3,spring-starter-aqmp 2.1.2),您可以执行以下变形:
@RabbitListener(id="multi", queues = "somequeuename")
public class SomeService
{
@RabbitHandler
public void handleADTO(@Payload ADTO adto) {
System.out.print(adto.url);
}
@RabbitHandler
public void handleADTO2(@Payload ADTO2 adto) {
System.out.print(adto.url);
}
}
但是,开箱即用不起作用。您需要配置另一个“豆袋”:
@Bean
public SimpleRabbitListenerContainerFactory myFactory(
SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
@Bean
Jackson2JsonMessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
RabbitTemplate rabbitTemplate(Jackson2JsonMessageConverter converter, ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(new Jackson2JsonMessageConverter());
return template;
}
只需将其放入您的应用或其他类中即可。
另请参见
https://docs.spring.io/spring-amqp/docs/current/reference/html/