Spring Boot RabbitMQ RabbitListener ListenerExecutionFailedException

问题描述 投票:0回答:2
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Failed to convert message
    at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:158) ~[spring-rabbit-3.1.0.jar:3.1.0]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1662) ~[spring-rabbit-3.1.0.jar:3.1.0]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1581) ~[spring-rabbit-3.1.0.jar:3.1.0]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1569) ~[spring-rabbit-3.1.0.jar:3.1.0]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1560) ~[spring-rabbit-3.1.0.jar:3.1.0]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListenerAndHandleException(AbstractMessageListenerContainer.java:1505) ~[spring-rabbit-3.1.0.jar:3.1.0]
...
Caused by: java.lang.SecurityException: Attempt to deserialize unauthorized class com.example.springboot.dto.User; add allowed class name patterns to the message converter or, if you trust the message orginiator, set environment variable 'SPRING_AMQP_DESERIALIZATION_TRUST_ALL' or system property 'spring.amqp.deserialization.trust.all' to true
    at org.springframework.amqp.utils.SerializationUtils.checkAllowedList(SerializationUtils.java:165) ~[spring-amqp-3.1.0.jar:3.1.0]
    at org.springframework.amqp.support.converter.AllowedListDeserializingMessageConverter.checkAllowedList(AllowedListDeserializingMessageConverter.java:61) ~[spring-amqp-3.1.0.jar:3.1.0]
    at org.springframework.amqp.support.converter.SimpleMessageConverter$1.resolveClass(SimpleMessageConverter.java:151) ~[spring-amqp-3.1.0.jar:3.1.0]
    at java.base/java.io.Ob

问题与 RabbitListener 有关。请帮忙。我不知道出了什么问题。

import com.example.springboot.dto.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class RabbitMQJsonConsumer {
    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitMQJsonConsumer.class);

    @RabbitListener(queues = {"${rabbitmq.queue.json.name}"})
    public void consumeJsonMessage(User user){
        LOGGER.info(String.format("Received JSON message -> %s", user.toString()));
    }
}

当我运行应用程序时,控制台不断生成这两个异常。我正在关注 Java 指南中的本教程:https://www.youtube.com/watch?v=0--Ll3WHMTQ

不知道和配置有没有关系。我尝试在 application.properties 中将 SecurityException 中提到的那些属性设置为 true,但没有帮助。

public MessageConverter converter(){
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public AmqpTemplate amqpTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(converter());
        return rabbitTemplate;
    }
spring spring-boot rabbitmq spring-rabbit
2个回答
0
投票

application.properties
既不是该例外中所述的环境,也不是系统属性。没有各自的 Spring Boot 属性。不过我们可以尝试在那里暴露它。而且它的价值有限,只有在您不提供自定义
MessageConverter
时才会应用它。

你的

rabbitTemplate.setMessageConverter(converter());
@RabbitListener
没有任何关系。

看看您是否可以将

Jackson2JsonMessageConverter
作为
@RabbitListener
配置端的 bean 提供。

与默认的

SimpleMessageConverter
(仅适用于 Java 序列化)不同,
Jackson2JsonMessageConverter
默认信任所有内容。

如果您发送 JSON,请务必考虑在消费者端也将其设为 JSON。


0
投票

只是在 @ArtemBilan 评论上添加注释,这将有助于理解此错误,文档指出

在调用监听器之前,管道中有两个转换步骤。第一个使用 MessageConverter 将传入的 Spring AMQP 消息转换为 spring-messaging 消息。当调用目标方法时,如有必要,消息负载将转换为方法参数类型。

因此传入消息的转换经历两个阶段:

a. AMQP Message -> Spring : MessageConverter (下面代码中的 simpleConverterMessage())

b. Spring -> 目标方法:方法参数转换器(下面代码中的methodMessageConverter())

@RabbitListener 使用选项 b 中的转换。文档指出: 在大多数情况下,没有必要自定义方法参数转换器,除非您想使用自定义 ConversionService。

为了解决因此引发的安全错误,我们将使用 methodMessageConverter() 自定义代码,如下所示:

 @Bean("methodConverter")
 public SimpleMessageConverter methodMessageConverter() {
        SimpleMessageConverter converter = new SimpleMessageConverter();
        converter.setAllowedListPatterns(List.of("**com.somecompany.someproject.somepackage.**"));
        return converter;
    }


@Bean
public MessageConverter simpleMessageConverter() {
    return new Jackson2JsonMessageConverter();
}

@Bean
public AmqpTemplate amqpTemplate(ConnectionFactory connectionFactory) {
    RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
    rabbitTemplate.setMessageConverter(simpleMessageConverter());
    rabbitTemplate.setReplyTimeout(replyTimeout);

    return rabbitTemplate;
}

@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory());
    factory.setMessageConverter(simpleMessageConverter());
    factory.setConcurrentConsumers(concurrentConsumers);
    factory.setMaxConcurrentConsumers(maxConcurrentConsumers);
    factory.setErrorHandler(errorHandler());
    return factory;
}

然后在使用 @RabbitListener 的文件使用者中使用以下实现:

 @RabbitListener(queues = {Constants.Queue_1, Constants.Queue_2}, messageConverter = "methodConverter")
    public void receiveTransactionRequest(FooRequest request) {
            /***your code***/
    }

我不想使用环境系统或系统属性选项,原因很简单,它需要运营团队进行大量更改,从而造成不必要的负担并且容易出错。

© www.soinside.com 2019 - 2024. All rights reserved.