Rabbitmq Spring AMQP-发送和接收消息

Rabbitmq Spring AMQP-发送和接收消息,rabbitmq,spring-amqp,spring-rabbit,Rabbitmq,Spring Amqp,Spring Rabbit,我在接收来自RabbitMQ的消息时遇到了一个问题。 我正在发送一条如下的消息 HashMap<Object, Object> senderMap=new HashMap<>(); senderMap.put("STATUS", "SUCCESS"); senderMap.put("EXECUTION_START_TIME", new Date()); rabbitTemplate.convertAndSe

我在接收来自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);
例外情况

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)
我不想使用发件人的\uuuu TYPE\uu ID,因为他们是同一队列的多个发件人,只有一个使用者。

这导致了一个例外

什么例外

类型ID:com.diff.approach.JobListenerDTO

这意味着您发送的是DTO,而不是问题中描述的哈希映射

如果要删除typeId标头,可以使用消息后处理器

rabbitTemplate.convertAndSend(Constants.INPUT_QUEUE, dto, m -> {
    m.getMessageProperties.getHeaders().remove("__TypeId__");
    return m;
});
(或
,如果您没有使用Java 8,则使用新的MessagePostProcessor(){…}

编辑

您使用的是哪个版本的Spring AMQP?在1.6版本中,您甚至不必删除
\uuuuuu TypeId\uuuuuu
头-框架查看侦听器参数类型并告诉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;
        }

    }

}
这在…中描述

在1.6之前的版本中,转换JSON的类型信息必须在消息头中提供,或者需要自定义类映射器。从版本1.6开始,如果没有类型信息头,则可以从目标方法参数推断类型

您还可以配置自定义的
类映射器
以始终返回
HashMap

  • 在接收消息时要使用不同的Java Cals吗

    使用自定义

  • 要在接收消息时使用“许多”不同的Java CALS吗?例如:

    @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
    ) {
        // ...
    }
    
参考资料:

  • 调试源代码

信息不足会导致异常。添加stacktrace pleaseActually头在rabbitmq中包含一个名为type\ u id\的属性。这不应该。如何发送类型id属性不存在的消息
优先级:0传递模式:2\uuuuuTypeID\uuuuuuuuuu:com.diff.approach.JobListenerDTO**content\u编码:UTF-8 content\u type:application/json
谢谢Gary,还有一个问题,如何接收此消息<代码>标题:\ uuuu ContentTypeId\ uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuukeytypid\ uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu{byte[]body=message.getBody();}如何从byte[]转换要返回hashmap??不要将代码放在注释中-它不可读-改为编辑您的问题。您需要侦听器容器工厂中的
Jackson2JsonMessageConverter
。您好Gary,我已经添加了我的接收器代码,请您建议如何使用
Jackson2JsonMessageConverter
版本的Spring AMQP-
1.6.1.发行版de>Spring RabbitMQ的版本-
1.5.6.发行版
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}
@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
) {
    // ...
}
@Bean
FormattingConversionServiceFactoryBean rabbitMqCs(
        Set<Converter> converters
) {
    FormattingConversionServiceFactoryBean fac = new FormattingConversionServiceFactoryBean();
    fac.setConverters(converters);
    return fac;
}
@Bean
DefaultMessageHandlerMethodFactory messageHandlerMethodFactory(
        @Qualifier("rabbitMqCs")
        FormattingConversionService rabbitMqCs
) {
    DefaultMessageHandlerMethodFactory defaultFactory = new DefaultMessageHandlerMethodFactory();
    defaultFactory.setConversionService(rabbitMqCs);
    return defaultFactory;
}

// copied from RabbitBootstrapConfiguration
@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public RabbitListenerAnnotationBeanPostProcessor rabbitListenerAnnotationProcessor(
        MessageHandlerMethodFactory handlerFac
) {
    RabbitListenerAnnotationBeanPostProcessor bpp = new RabbitListenerAnnotationBeanPostProcessor();
    bpp.setMessageHandlerMethodFactory(handlerFac);
    return bpp;
}

@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME)
public RabbitListenerEndpointRegistry defaultRabbitListenerEndpointRegistry() {
    return new RabbitListenerEndpointRegistry();
}