RabbitMQ发布Java对象时出现反序列化未授权类错误求助
推送Java对象到RabbitMQ队列时遇到以下错误:
- 错误1:
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Failed to convert message
- 错误2:
Attempt to deserialize unauthorized class com.example.rabbitmq.model.MessageInfo; add allowed class name patterns to the message converter or, if you trust the message originator, set environment variable 'SPRING_AMQP_DESERIALIZATION_TRUST_ALL' or system property 'spring.amqp.deserialization.trust.all' to true.
用JSON字符串替代Java对象时,消息能正常发布和接收,但业务需求必须推送Java对象。
在RabbitMQ控制台查看消息的配置信息:
priority: 0 delivery_mode: 2 headers: content_type: application/x-java-serialized-object
相关代码
配置类
@Bean public Queue queue() { return new Queue(QUEUE); } @Bean public TopicExchange exchange() { return new TopicExchange(EXCHANGE); } @Bean public Binding binding(Queue queue, TopicExchange exchange) { return BindingBuilder .bind(queue) .to(exchange) .with(ROUTING_KEY); } @Bean public Jackson2JsonMessageConverter messageConverter() { Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter() ; return converter; } @Bean public AmqpTemplate template(ConnectionFactory connectionFactory) { RabbitTemplate template = new RabbitTemplate(connectionFactory); template.setMessageConverter(messageConverter()); return template; }
发布者代码
public String publishMessage(@RequestBody CustomMessage message) { System.out.println(" Message received == >"+message.getMessage()); MessageInfo msMessageInfo = MessageInfo.builder().messageId(UUID.randomUUID().toString()).message(message.getMessage()) .messageDate(new Date()) .build(); template.convertAndSend(RabbitMqExchangeConfig.EXCHANGE, RabbitMqExchangeConfig.ROUTING_KEY, msMessageInfo); return "Message Published"; }
接收者代码
@RabbitListener(queues = RabbitMqExchangeConfig.QUEUE) public void listener(MessageInfo message) { System.out.println(" --- > delivered messagd :: == > "+message); }
解决方案
方案1:指定消息转换器信任的类/包
你已经配置了Jackson2JsonMessageConverter,但控制台显示消息的content_type是Java序列化格式,说明接收端可能没正确使用JSON转换器,或者发送时实际用了Java序列化而非JSON。
修改消息转换器配置,添加信任的类或包:
@Bean public Jackson2JsonMessageConverter messageConverter() { Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(); // 信任整个包下的类 converter.addTrustedPackages("com.example.rabbitmq.model"); // 或者仅信任指定类 // converter.addTrustedClass(MessageInfo.class); return converter; }
同时确保接收端的容器工厂也使用该转换器:
@Bean public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) { SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); factory.setMessageConverter(messageConverter()); return factory; }
方案2:全局信任所有类(仅限信任消息来源的场景)
如果完全信任消息发送方,可以通过以下方式开启全局信任:
- JVM启动参数添加:
-Dspring.amqp.deserialization.trust.all=true - 设置环境变量:
SPRING_AMQP_DESERIALIZATION_TRUST_ALL=true
额外注意
从控制台的content_type来看,当前消息是Java序列化格式而非JSON,可能是发送端的RabbitTemplate没有正确注入配置的转换器,或者有其他配置覆盖了消息转换器。要确保发送和接收两端使用相同的消息转换器,避免序列化格式不匹配导致的问题。
内容的提问来源于stack exchange,提问作者karthik selvaraj

