Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java rabbitmq的Spring引导受信任包_Java_Spring_Spring Boot_Rabbitmq - Fatal编程技术网

Java rabbitmq的Spring引导受信任包

Java rabbitmq的Spring引导受信任包,java,spring,spring-boot,rabbitmq,Java,Spring,Spring Boot,Rabbitmq,我们正在构建一个Spring引导应用程序(2.0.4-RELEASE),它通过RabbitMQ接收消息。因此,application.properties包含与兔子相关的配置: spring.rabbitmq.addresses=**** spring.rabbitmq.username=**** spring.rabbitmq.password=**** spring.rabbitmq.listener.simple.concurrency=2 spring.rabbitmq.listener

我们正在构建一个Spring引导应用程序(2.0.4-RELEASE),它通过RabbitMQ接收消息。因此,
application.properties
包含与兔子相关的配置:

spring.rabbitmq.addresses=****
spring.rabbitmq.username=****
spring.rabbitmq.password=****
spring.rabbitmq.listener.simple.concurrency=2
spring.rabbitmq.listener.simple.prefetch=5
spring.rabbitmq.listener.simple.retry.enabled=true
spring.rabbitmq.listener.simple.retry.max-attempts=5
配置:

@Bean
public TopicExchange fileUpdate() {
    return new TopicExchange("my.fancy.exchange", true, false);
}

@Bean
public Queue fileUpload() {
    return new Queue("myFancyQueue", true);
}

@Bean
public Binding bindingUpload(Queue queue, TopicExchange eventExchange) {
    return BindingBuilder.bind(queue).to(eventExchange).with("");
}
信息消费者:

@RabbitListener(queues = "myFancyQueue")
public void receive(Object message) {
    ...
}
接收特定类型的消息时(例如,
\uuuuuutypeid\uuuu:my.fancy.package.Clazz
)会引发以下错误:

原因:java.lang.IllegalArgumentException:类“my.fancy.package.Clazz”不是 在受信任的包中:[java.util,java.lang]。如果你相信这一点 类可以安全地反序列化,请提供其名称。如果 序列化仅由受信任的源完成,您还可以启用 信任所有(*)

据我所知,activeMQ通过
application.properties
as为其提供了一个配置选项

spring.activemq.packages.trust-all=

但我找不到任何适用于rabbitMQ的类似选项。到目前为止,我一直在使用解决我的问题的变通方法,但当然,在配置文件中有这样一个选项会很好

到目前为止,我的解决方案是:

添加到配置类:

@Bean
public MessageConverter jsonMessageConverter() {
    Jackson2JsonMessageConverter jsonMessageConverter = new Jackson2JsonMessageConverter(new ObjectMapper());
    jsonMessageConverter.setClassMapper(new ImporterClassMapper(FileUploadMessage.class));        
    return jsonMessageConverter;
}

@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
    RabbitTemplate template = new RabbitTemplate(connectionFactory);
    template.setMessageConverter(jsonMessageConverter());
    return template;
}
以及将消息更改为消费者

@Resource(name = "jsonMessageConverter")
private MessageConverter messageConverter;

@RabbitListener(queues = "${uploaded.files.queue}")
public void receive(Message message) {
    FileUploadMessage uploadMessage = (FileUploadMessage) messageConverter.fromMessage(message);
    ...
}
此外,还添加了一个类映射器,该类映射器允许导入未知类型,并设置导入时消息应转换为的默认类型:

public class ImporterClassMapper implements ClassMapper, InitializingBean {

    private volatile Class<?> defaultType;

    public ImporterClassMapper(Class<?> defaultType) {
        this.defaultType = defaultType;
    }    

    @Override
    public void afterPropertiesSet() throws Exception {
        // nothing to do
    }

    @Override
    public void fromClass(Class<?> clazz, MessageProperties properties) {
        // avoid setting __TypeId__ header so consumers from other modules can implement their own DTOs
    }

    @Override
    public Class<?> toClass(MessageProperties properties) {
        return this.defaultType;
    }

    public void setClass(Class<?> type) {
        this.defaultType = type;
    }
}
公共类ImporterClassMapper实现类映射器,初始化bean{
私有易失性类defaultType;
公共导入类映射器(类defaultType){
this.defaultType=defaultType;
}    
@凌驾
public void afterPropertieSet()引发异常{
//无事可做
}
@凌驾
来自类的公共void(类clazz、MessageProperties){
//避免设置uuu TypeId_uuuuuu头,以便来自其他模块的使用者可以实现他们自己的DTO
}
@凌驾
公共类到类(MessageProperties属性){
返回此.defaultType;
}
公共类(类类型){
this.defaultType=type;
}
}

关于如何改进此解决方案,有什么建议吗?

我通过在正在使用的Spring AMQP类映射器上设置受信任的包,修复了相同的错误

@Configuration
public class RabbitConfig {

    @Bean
    @Scope("prototype")
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(SimpleRabbitListenerContainerFactory factory, ObjectMapper objectMapper) {
        factory.setMessageConverter(jsonToMapMessageConverter(objectMapper));
        return factory;
    }

    @Bean
    public MessageConverter jsonToMapMessageConverter(ObjectMapper objectMapper) {
        Jackson2JsonMessageConverter messageConverter = new ImplicitJsonMessageConverter(objectMapper);
        DefaultClassMapper classMapper = new DefaultClassMapper();
        classMapper.setTrustedPackages("*");
        classMapper.setDefaultType(Map.class);
        messageConverter.setClassMapper(classMapper);
        return messageConverter;
    }

    public static class ImplicitJsonMessageConverter extends Jackson2JsonMessageConverter {    
        public ImplicitJsonMessageConverter(ObjectMapper jsonObjectMapper) {
            super(jsonObjectMapper, "*");
        }    
        @Override
        public Object fromMessage(Message message) throws MessageConversionException {
            message.getMessageProperties().setContentType("application/json");
            return super.fromMessage(message);
        }
    }
}

我认为使用JSON发送/接收任意类型是推荐的方法……是的,类型当然是用JSON传输的。然而,它们提供了一个TypeId。然后DefaultClassMapper将始终尝试将JSON强制转换为类型,如果使用者不知道类型,则抛出异常,尽管这花了我一段时间——是的,这是一种更好的方法。阻止我实现自定义类映射器。谢谢
@Configuration
public class RabbitConfig {

    @Bean
    @Scope("prototype")
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(SimpleRabbitListenerContainerFactory factory, ObjectMapper objectMapper) {
        factory.setMessageConverter(jsonToMapMessageConverter(objectMapper));
        return factory;
    }

    @Bean
    public MessageConverter jsonToMapMessageConverter(ObjectMapper objectMapper) {
        Jackson2JsonMessageConverter messageConverter = new ImplicitJsonMessageConverter(objectMapper);
        DefaultClassMapper classMapper = new DefaultClassMapper();
        classMapper.setTrustedPackages("*");
        classMapper.setDefaultType(Map.class);
        messageConverter.setClassMapper(classMapper);
        return messageConverter;
    }

    public static class ImplicitJsonMessageConverter extends Jackson2JsonMessageConverter {    
        public ImplicitJsonMessageConverter(ObjectMapper jsonObjectMapper) {
            super(jsonObjectMapper, "*");
        }    
        @Override
        public Object fromMessage(Message message) throws MessageConversionException {
            message.getMessageProperties().setContentType("application/json");
            return super.fromMessage(message);
        }
    }
}