为什么Jackson2JsonMessageConverter将List <string>转换为List <object>

时间:2016-05-24 13:00:52

标签: rabbitmq spring-amqp

我正在使用RabbitMQ处理Spring AMQP,我使用MessageConverter( Jackson2JsonMessageConverter)配置了ObjectMapper。如果我通过传递convertAndSend(,,,)从发件人类调用HashMap<String,Object>方法,则ReceiverhandleMessage()方法成功获得了类型HashMap的消息。但问题是,此HashMap包含List字符串List<String>。当我在HashMap中收到此Receiver时,我尝试通过密钥获取List<String>,但却发出错误List<Object> can't cast Object list to string list。这是我的Config类,发件人类和Receiver类

的代码
@Configuration
public class RabbitMQConfig {

    @Autowired
    Environment environment;

    final static String paymentQueue = "mobily-payment-queue";
    final static String mailQueue = "mobily-mail-queue";
    final static String orderQueue = "mobily-order-queue";
    final static String deductProductQueue = "mobily-deduct-product-queue";
    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(environment.getRequiredProperty("rabbitmq.host"),Integer.parseInt(environment.getRequiredProperty("rabbitmq.port")));
        connectionFactory.setUsername(environment.getRequiredProperty("rabbitmq.user"));
        connectionFactory.setPassword(environment.getRequiredProperty("rabbitmq.pass"));
        return connectionFactory;
    }

    @Bean 
    public MessageConverter jsonMessageConverter() { 
        final Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(); 


        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JodaModule());
        mapper.registerModule(new Hibernate4Module());
        mapper.setSerializationInclusion(Include.NON_NULL);
         converter.setJsonObjectMapper(mapper);
        return converter; 
     }


    @Bean
    public RabbitTemplate template(MessageConverter jsonMessageConverter) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setMessageConverter(jsonMessageConverter);
        return template;
    }

    @Bean
    public DirectExchange direct() {
        return new DirectExchange("mobily.direct");
    }

        @Bean
        public Queue paymentQueue(){
            return new Queue(paymentQueue);
        }

        @Bean
        public Queue deductProductQueue() {
            return new Queue(deductProductQueue);
        }

        @Bean
        public Queue orderQueue() {
            return new Queue(orderQueue);
        }

        @Bean
        public Queue mailQueue(){
            return new Queue(mailQueue);
        }

        @Bean
        public Binding paymentBinding(DirectExchange direct, Queue paymentQueue) {
            return BindingBuilder.bind(paymentQueue).to(direct).with(environment.getRequiredProperty("rabbitmq.payment.key"));
        }

        @Bean
        public Binding deductProductBinding(DirectExchange direct, Queue deductProductQueue) {
            return BindingBuilder.bind(deductProductQueue).to(direct).with(environment.getRequiredProperty("rabbitmq.deduct.product.key"));
        }

        @Bean
        public Binding orderBinding(DirectExchange direct, Queue orderQueue) {
            return BindingBuilder.bind(orderQueue).to(direct).with(environment.getRequiredProperty("rabbitmq.order.key"));
        }

        @Bean
        public Binding mailBinding(DirectExchange direct, Queue mailQueue) {
            return BindingBuilder.bind(mailQueue).to(direct).with(environment.getRequiredProperty("rabbitmq.mail.key"));
        }

        /*@Bean
        Receiver receiver() {
            return new Receiver();
        }*/

        @Bean
        PaymentReceiver paymentReceiver(){

            return new PaymentReceiver();
        }

        @Bean
        DeductProductReceiver deductProductReceiver(){

            return new DeductProductReceiver();
        }

        @Bean
        OrderReceiver orderReceiver(){
            return new OrderReceiver();
        }

        @Bean
        MailReceiver mailReceiver(){

            return new MailReceiver();
        }

        @Bean
        SimpleMessageListenerContainer deductProductContainer(ConnectionFactory connectionFactory, MessageListenerAdapter deductProductListenerAdapter) {
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.setQueueNames(deductProductQueue);
            container.setMessageListener(deductProductListenerAdapter);
            return container;


        }

        @Bean
        MessageListenerAdapter deductProductListenerAdapter(DeductProductReceiver deductProductReceiver,MessageConverter jsonMessageConverter) {
            return new MessageListenerAdapter(deductProductReceiver, jsonMessageConverter);
        }

        @Bean
        SimpleMessageListenerContainer paymentContainer(ConnectionFactory connectionFactory, MessageListenerAdapter paymentListenerAdapter) {
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.setQueueNames(paymentQueue);
            container.setMessageListener(paymentListenerAdapter);
            return container;


        }

        @Bean
        MessageListenerAdapter paymentListenerAdapter(PaymentReceiver paymentReceiver,MessageConverter jsonMessageConverter) {
            return new MessageListenerAdapter(paymentReceiver,jsonMessageConverter );
        }

        @Bean
        SimpleMessageListenerContainer orderContainer(ConnectionFactory connectionFactory, MessageListenerAdapter orderListenerAdapter) {
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.setQueueNames(orderQueue);
            container.setMessageListener(orderListenerAdapter);
            return container;


        }

        @Bean
        MessageListenerAdapter orderListenerAdapter(OrderReceiver orderReceiver,MessageConverter jsonMessageConverter) {
            return new MessageListenerAdapter(orderReceiver,jsonMessageConverter);
        }

        @Bean
        SimpleMessageListenerContainer mailContainer(ConnectionFactory connectionFactory, MessageListenerAdapter mailListenerAdapter) {
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.setQueueNames(mailQueue);
            container.setMessageListener(mailListenerAdapter);
            return container;


        }

        @Bean
        MessageListenerAdapter mailListenerAdapter(MailReceiver mailReceiver,MessageConverter jsonMessageConverter) {
            return new MessageListenerAdapter(mailReceiver,jsonMessageConverter);
        }




}

这是我的发件人类

HashMap<String, Object> mailMap=new HashMap<String, Object>();
CustomerAccountUser customerAccountUser=customerAccountUserService.getCustomerAccountUserByUsername(customerAccountPayments.getCustomerName());
             ArrayList<String> emailAddress=new ArrayList<String>();
             emailAddress.add(customerAccountUser.getEmail());
 template.convertAndSend(direct.getName(),environment.getRequiredProperty("rabbitmq.mail.key"),mailMap);

这是我的接收者

public void handleMessage(HashMap<String,Object> mailMap){

    try{
        System.out.println("mail queue..................................." + mailMap);
        String s1=(String)mailMap.get("subject");
        String s2=(String)mailMap.get("body");
        List<String> list=(List<String>)mailMap.get("emailAddress");
    }
}

这个错误

    e2016-05-24 17:02:47 ERROR stderr:71 - java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
2016-05-24 17:02:47 ERROR stderr:71 -   at com.mobily.service.EmailService.sendEmail(EmailService.java:24)
2016-05-24 17:02:47 INFO  stdout:71 -     values
2016-05-24 17:02:47 ERROR stderr:71 -   at com.mobily.customer.rabbitmq.reciever.MailReceiver.handleMessage(MailReceiver.java:27)
2016-05-24 17:02:47 ERROR stderr:71 -   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2016-05-24 17:02:47 ERROR stderr:71 -   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
2016-05-24 17:02:47 ERROR stderr:71 -   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2016-05-24 17:02:47 ERROR stderr:71 -   at java.lang.reflect.Method.invoke(Method.java:497)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:269)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.invokeListenerMethod(MessageListenerAdapter.java:387)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.onMessage(MessageListenerAdapter.java:298)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:757)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:680)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$001(SimpleMessageListenerContainer.java:93)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$1.invokeListener(SimpleMessageListenerContainer.java:183)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.invokeListener(SimpleMessageListenerContainer.java:1358)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:661)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1102)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:1086)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1100(SimpleMessageListenerContainer.java:93)
2016-05-24 17:02:47 ERROR stderr:71 -   at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1203)`enter code here`e

1 个答案:

答案 0 :(得分:2)

嗯,遗憾的是Jackson2JsonMessageConverter无法为您做到这一点。

它的逻辑基于三个消息标题:

public static final String DEFAULT_CLASSID_FIELD_NAME = "__TypeId__";

public static final String DEFAULT_CONTENT_CLASSID_FIELD_NAME = "__ContentTypeId__";

public static final String DEFAULT_KEY_CLASSID_FIELD_NAME = "__KeyTypeId__";

因此,它能做的最好的事情就像HashMap<Foo, Bar>。但是它无法构建正确的嵌套容器类型,因为消息头中没有这样的信息。

当然,你必须在handleMessage代码的下游进行一些进一步的转换(转换)逻辑。我的意思是不要投射到List<String>,而是迭代并投射每个项目。

虽然根据你的发送逻辑:

ArrayList<String> emailAddress=new ArrayList<String>();
emailAddress.add(customerAccountUser.getEmail());

您可以尝试使用arrayString[])代替List<String>。这应该可以正常工作,因为数组被认为是原始类型,而不是容器。