为什么带有Jackson2JsonMessageConverter的AmqpChannelFactoryBean不存储类型?

时间:2017-10-10 07:48:46

标签: spring-integration spring-amqp spring-integration-amqp

我尝试使用与RabbitMQ的Spring集成,使用RabbitMQ支持的Spring集成通道。 (由于某种原因,似乎几乎没有记录,这是新的吗?)。

为此,我似乎可以使用AmqpChannelFactoryBean来创建一个频道。 要设置消息转换,我使用Jackson2JsonMessageConverter。

当我使用带有POJO有效负载的GenericMessage时,它拒绝从Java反序列化它,主要是因为它不知道类型。我原本希望将类型自动放在标题上,但在标题上只有__TypeId__=org.springframework.messaging.support.GenericMessage

在Spring启动时,我的配置类如下所示:

@Configuration
public class IntegrationConfiguration {

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

    @Bean
    public AmqpChannelFactoryBean myActivateOutChannel(CachingConnectionFactory connectionFactory,
        MessageConverter messageConverter) {

        AmqpChannelFactoryBean factoryBean = new AmqpChannelFactoryBean(true);
        factoryBean.setConnectionFactory(connectionFactory);
        factoryBean.setQueueName("myActivateOut");
        factoryBean.setPubSub(false);
        factoryBean.setAcknowledgeMode(AcknowledgeMode.AUTO);
        factoryBean.setDefaultDeliveryMode(MessageDeliveryMode.PERSISTENT);
        factoryBean.setMessageConverter(messageConverter);
        return factoryBean;
    }

    @Bean
    @ServiceActivator(inputChannel = "bsnkActivateOutChannel", autoStartup="true")
    public MessageHandler mqttOutbound() {

        return m -> System.out.println(m);
    }

}

发送方式如下:

private final MessageChannel myActivateOutChannel;

@Autowired
public MySender(MessageChannel myActivateOutChannel) {
    this.myActivateOutChannel = myActivateOutChannel;
}

@Override
public void run(ApplicationArguments args) throws Exception {
    MyPojo pojo = new MyPojo();
    Message<MyPojo> msg = new GenericMessage<>(pojo);

    myActivateOutChannel.send(msg);
}

如果我设置了自己的类映射器,事情就会发挥作用。但如果我设置这样的东西,我将不得不使用许多MessageConverters。 E.g。

    converter.setClassMapper(new ClassMapper() {

        @Override
        public void fromClass(Class< ? > clazz, MessageProperties properties) {
        }

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

    });

我使用这个错了吗?我错过了一些配置吗?还有其他建议吗?

谢谢! :)

注意:更多地关注事物,我猜测了Spring集成&#39;方法是在每一侧添加一个Spring集成JSON转换器,这意味着每个RabbitMQ队列还增加两个额外的直接通道? 这对我来说是错误的,因为我已经获得了三倍的频道(6!for in / out),但可能是因为该框架应该如何使用?通过直接渠道结合所有简单的步骤? (在这种情况下,我是否保持RabbitMQ频道提供的持久性?或者,如果我需要,我是否需要一些事务处理机制?或者直接通道的工作原理是什么?)

我现在也注意到Spring-integration MessageConverter和Spring-amqp MessageConverter都有。后者是我使用的那个。对方会按照我想要的方式工作吗?快速浏览代码表明它没有将对象类型存储在消息头中吗?

1 个答案:

答案 0 :(得分:1)

在4.3版之前,amqp支持的通道仅支持可序列化的有效负载;解决方法是使用通道适配器(支持映射)。

INT-3975引入了一个新属性extractPayload,它会将邮件标头映射到rabbitmq标头,而邮件正文只是有效负载而不是序列化GenericMessage

extractPayload设置为true可以解决您的问题。