如何将消息直接绑定到我的对象类

时间:2016-09-24 04:50:29

标签: java spring-amqp spring-rabbitmq

我收到如下信息,其中包含2个HashMap(inputMap和outputMap)。这是使用ObjectMapper的正确方法吗?

示例消息:

在RabbitMQ中:

 {"ORCH_KEY":{"inputMap":{},"outputMap":{"activityId":"10001002","activityStatus":"SUCCESS"}}}

在配置代码中

SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory());

    Jackson2JsonMessageConverter messageConverter=new Jackson2JsonMessageConverter();
    DefaultClassMapper classMapper = new DefaultClassMapper();
    classMapper.setDefaultType(ExchangeDTO.class);
    messageConverter.setClassMapper(classMapper);
    factory.setMessageConverter(messageConverter);

消费者代码

 @RabbitListener(containerFactory = "adapterOPListenerContainerFactory", queues = Constants.ADAPTOR_OP_QUEUE)
    public void handleAdapterQueueMessage(HashMap<String, ExchangeDTO> adapterOutputMap) {

        logger.info("Adapter Handler::::::::::"+this.getClass().getCanonicalName());
        try {

            logger.info("Adapter Output Map:::::::::::" + adapterOutputMap);

            if(adapterOutputMap.size()==1){
                Iterator<Entry<String, ExchangeDTO>> iterator = adapterOutputMap.entrySet().iterator();
                Entry<String, ExchangeDTO> next = iterator.next();

                String ORCH_KEY =next.getKey();
                logger.info("Ochestration Key:::::::::::" + ORCH_KEY);

                ExchangeDTO exchangeDTO = next.getValue();
                logger.info("Size of OutputMap:::::"+exchangeDTO.getOutputMap().size());

ExchangeDTO类

public class ExchangeDTO implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;
private HashMap<String, Object> inputMap = new HashMap<String, Object>();
private HashMap<String, Object> outputMap = new HashMap<String, Object>();

public HashMap<String, Object> getInputMap() {
    return inputMap;
}

public void setInputMap(HashMap<String, Object> inputMap) {
    this.inputMap = inputMap;
}

public HashMap<String, Object> getOutputMap() {
    return outputMap;
}

public void setOutputMap(HashMap<String, Object> outputMap) {
    this.outputMap = outputMap;
}

}

我遇到如下错误:

  

java.util.LinkedHashMap无法强制转换为   com.bosch.bip.dto.ExchangeDTO

1 个答案:

答案 0 :(得分:1)

“在java代码中”是什么意思?对象映射器期待JSON字符串。

{"ORCH_KEY":{"inputMap":{},"outputMap":{"activityId":"10001002","activityStatus":"SUCCESS"}}}

如果您使用的是Spring AMQP Json转换器,则JSON已经转换为地图图。

{inputMap={}, outputMap={activityId=10001002, activityStatus=SUCCESS}}

看起来像toString()调用结果。

您需要使用自定义Jackson2JsonMessageConverter自定义ClassMapper,告知转换器您想要创建ExchangeDTO

您可以使用DefaultClassMapper;如果消息中没有信息来确定类型,则默认类映射器将回退到其默认类型:myDefaultClassMapper.setDefaultType(MyType.class);。然后将映射器注入消息转换器。

修改

我刚刚运行了测试,它对我来说效果很好(请注意,不需要自定义类映射器)...

public static class DTO {

    private Map<String, Object> inputMap;

    private Map<String, Object> outputMap;

    public Map<String, Object> getInputMap() {
        return this.inputMap;
    }

    public void setInputMap(Map<String, Object> inputMap) {
        this.inputMap = inputMap;
    }

    public Map<String, Object> getOutputMap() {
        return this.outputMap;
    }

    public void setOutputMap(Map<String, Object> outputMap) {
        this.outputMap = outputMap;
    }

    @Override
    public String toString() {
        return "DTO [inputMap=" + this.inputMap + ", outputMap=" + this.outputMap + "]";
    }

}

@RabbitListener(queues = QUEUE, containerFactory = "adapterOPListenerContainerFactory")
public void listen(HashMap<String, DTO> message) {
    System.out.println("Result:" + message.getClass() + ":" + message);
    latch.countDown();
}

@Bean
public SimpleRabbitListenerContainerFactory adapterOPListenerContainerFactory(ConnectionFactory connectionFactory) {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setMessageConverter(new Jackson2JsonMessageConverter());
    return factory;
}

... Received message: (Body:'{"MAP":{"inputMap":{"foo":"bar"},"outputMap":{"baz":"qux"}}}'

Result:class java.util.HashMap:{MAP=DTO [inputMap={foo=bar}, outputMap={baz=qux}]}

此机制(将参数类型传递给JSON转换器)需要Spring AMQP 1.6或更高版本 - 1.6.2是当前版本。

<强> EDIT2

对我来说很好......

@RabbitListener(queues = QUEUE, containerFactory = "adapterOPListenerContainerFactory")
public void listen(HashMap<String, DTO> dtos) {
    System.out.println("Result:" + dtos.getClass() + ":" + dtos);
    DTO dto = dtos.entrySet().iterator().next().getValue();
    System.out.println(dto);
    latch.countDown();
}

Result:class java.util.HashMap:{MAP=DTO [inputMap={foo=bar}, outputMap={baz=qux}]}
DTO [inputMap={foo=bar}, outputMap={baz=qux}]

您的地图值似乎未转换为DTO,而是转换为默认LinkedHashMap。如果您使用与我相同的配置,我不明白这是怎么可能的。

如果您可以在某个展示问题的地方发布一个小型测试项目,我可以看一看是什么问题。