我在接收RabbitMQ的消息时遇到了问题。 我正在发送如下信息
HashMap<Object, Object> senderMap=new HashMap<>();
senderMap.put("STATUS", "SUCCESS");
senderMap.put("EXECUTION_START_TIME", new Date());
rabbitTemplate.convertAndSend(Constants.ADAPTOR_OP_QUEUE,senderMap);
如果我们在RabbitMQ中看到,我们将获得一个完全合格的类型。
在当前情况下,我们为同一个消费者提供了n个生产者。如果我使用任何映射器,它会导致异常。 我将如何发送消息以使其不包含任何type_id,我可以将消息作为消息对象接收,之后我可以将其绑定到接收方中的自定义对象。
我收到的信息如下。 能告诉我如何使用 Jackson2MessageConverter ,以便消息直接从Receiver端绑定到我的Object / HashMap。此外,我现在已从发件人中删除了Type_ID。
如何在RabbitMQ中查看消息
优先级:0 delivery_mode:2个标题:
ContentTypeId :java.lang.Object KeyTypeId :java.lang.Object content_encoding:UTF-8 content_type:application / json { “Execution_start_time”:1473747183636, “状态”: “SUCCESS”}
@Component
public class AdapterOutputHandler {
private static Logger logger = Logger.getLogger(AdapterOutputHandler.class);
@RabbitListener(containerFactory="adapterOPListenerContainerFactory",queues=Constants.ADAPTOR_OP_QUEUE)
public void handleAdapterQueueMessage(HashMap<String,Object> message){
System.out.println("Receiver:::::::::::"+message.toString());
}
}
连接
@Bean(name="adapterOPListenerContainerFactory")
public SimpleRabbitListenerContainerFactory adapterOPListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
Jackson2JsonMessageConverter messageConverter = new Jackson2JsonMessageConverter();
DefaultClassMapper classMapper = new DefaultClassMapper();
messageConverter.setClassMapper(classMapper);
factory.setMessageConverter(messageConverter);
}
异常
Caused by: org.springframework.amqp.support.converter.MessageConversionException: failed to convert Message content. Could not resolve __TypeId__ in header and no defaultType provided
at org.springframework.amqp.support.converter.DefaultClassMapper.toClass(DefaultClassMapper.java:139)
我不想使用发件人的__TYPE__ID,因为他们是同一个队列的多个发件人,只有一个使用者。
答案 0 :(得分:4)
导致异常
什么例外?
TypeId :com.diff.approach.JobListenerDTO
这意味着您正在发送DTO,而不是您在问题中描述的哈希映射。
如果要删除typeId标头,可以使用消息后处理器...
rabbitTemplate.convertAndSend(Constants.INPUT_QUEUE, dto, m -> {
m.getMessageProperties.getHeaders().remove("__TypeId__");
return m;
});
(如果您不使用Java 8,则为, new MessagePostProcessor() {...}
。
修改强>
您使用的是什么版本的Spring AMQP?使用1.6,您甚至不必删除__TypeId__
标题 - 框架会查看侦听器参数类型并告诉Jackson转换器类型,以便它自动转换为该类型(如果可以)。正如你在这里看到的那样;它可以正常工作,而无需删除类型ID ...
package com.example;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class So39443850Application {
private static final String QUEUE = "so39443850";
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(So39443850Application.class, args);
context.getBean(RabbitTemplate.class).convertAndSend(QUEUE, new DTO("baz", "qux"));
context.getBean(So39443850Application.class).latch.await(10, TimeUnit.SECONDS);
context.getBean(RabbitAdmin.class).deleteQueue(QUEUE);
context.close();
}
private final CountDownLatch latch = new CountDownLatch(1);
@RabbitListener(queues = QUEUE, containerFactory = "adapterOPListenerContainerFactory")
public void listen(HashMap<String, Object> message) {
System.out.println(message.getClass() + ":" + message);
latch.countDown();
}
@Bean
public Queue queue() {
return new Queue(QUEUE);
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(new Jackson2JsonMessageConverter());
return template;
}
@Bean
public SimpleRabbitListenerContainerFactory adapterOPListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(new Jackson2JsonMessageConverter());
return factory;
}
public static class DTO {
private String foo;
private String baz;
public DTO(String foo, String baz) {
this.foo = foo;
this.baz = baz;
}
public String getFoo() {
return this.foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public String getBaz() {
return this.baz;
}
public void setBaz(String baz) {
this.baz = baz;
}
}
}
结果:
class java.util.HashMap:{foo=baz, baz=qux}
中对此进行了描述
在1.6之前的版本中,转换JSON的类型信息必须在消息头中提供,或者需要自定义ClassMapper。从版本1.6开始,如果没有类型信息头,则可以从目标方法参数推断出类型。
您还可以将自定义ClassMapper
配置为始终返回HashMap
。
答案 1 :(得分:0)
收到消息时想要使用“a”不同的Java calss吗?
使用自定义ClassMapper
收到消息时想要使用“很多”不同的Java calss吗?如:
BatchUpdateTask
提供自定义@Bean @MyAmqpMsgListener
void handlerMsg(
// Main message class, by MessageConverter
@Payload MyMsg myMsg,
// Secondary message class - by MessageConverter->ConversionService
@Payload Map<String, String> map,
org.springframework.messaging.Message<MyMsg> msg,
org.springframework.amqp.core.Message amqpMsg
) {
// ...
}
,Converter
,ConversionService
:
RabbitListenerAnnotationBeanPostProcessor
参考文献: