使用Spring4 + ActiveMQ
,我想从队列接收JMS消息,并自动转换为POJO。
所以我将MappingJackson2MessageConverter
添加到DefaultJmsListenerContainerFactory
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// some other config
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("???");
factory.setMessageConverter(converter);
return factory;
}
这是我的听众配置
@JmsListener(destination = "queue.fas.flight.order", containerFactory = "jmsListenerContainerFactory")
public void processOrder(OrderRegisterDto registerParam) {
System.out.println(registerParam.toString());
}
问题是,我不知道如何设置TypeIdPropertyName
。队列不受我的控制,其他人则发送JSON
。
我想要一个通用转换器。所以我使用String
接收消息,并手动将其转换为POJO。
@JmsListener(destination = "xxxx", containerFactory = "xxxxx")
public void order(String registerParam) {
try{
OrderRegisterDto dto = objectMapper.readValue(registerParam,OrderRegisterDto.class);
}catch (IOException e){
// TODO
}
}
还有更好的方法吗?
答案 0 :(得分:7)
转换器希望发件人在邮件属性中提供转换的类型信息。
String typeId = message.getStringProperty(this.typeIdPropertyName);
typeId可以是类名,也可以是typeId映射图中条目的键。
如果您的消息不包含任何类型信息,则需要对转换器进行子类化并覆盖getJavaTypeForMessage()
以返回目标类的杰克逊JavaType
,例如:
return TypeFactory.defaultInstance().constructType(Foo.class);
如果它是常量而不依赖于消息中的某些信息,则可以在子类中创建静态字段。
答案 1 :(得分:0)
这项工作:
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setConcurrency("3-10");
// Este es el convertidor por defeto de Spring.
SimpleMessageConverter s = new SimpleMessageConverter();
MappingJackson2MessageConverter s2 = new MappingJackson2MessageConverter();
s2.setTargetType(MessageType.BYTES);
s2.setTypeIdPropertyName("DocumentType");
factory.setMessageConverter(s2); // or "s"
return factory;
}
这是听众:
@JmsListener(containerFactory = "jmsListenerContainerFactory", destination = ORDER_QUEUE)
@Payload final ) {
public void receiveMessage(Session ses, @Payload final Message<Product> message, @Headers final Map<String, Object> headers) {
}
和Javascript STOMP客户端:
var product = {
productId : "111",
name : "laptop",
quantity: 2
}
var beforeSend = JSON.stringify(product);
stompClient.send(destinationProductProd_02,{"DocumentType":"org.jms.model.Product"}, beforeSend); // OK
注意我将“DocumentType”STOMP标头添加到要发送的消息中。您需要发送Java类的完整包路径。
答案 2 :(得分:0)
似乎没有简单的解决方案在 @JmsListener 中自动将JSON转换为POJO,而消息中没有“ type header”。但是可以使用Jackson的ObjectMapper在您的代码中明确地做到这一点:
@Autowired
private ObjectMapper objectMapper;
@JmsListener(destination = "...", containerFactory = "...")
public void processOrder(String payload) {
OrderRegisterDto dto = objectMapper.readValue(payload, OrderRegisterDto.class);
System.out.println(dto.toString());
}
别忘了在配置中删除 MappingJackson2MessageConverter :
MappingJackson2MessageConverter转换器=新的MappingJackson2MessageConverter();factory.setMessageConverter(converter);