Spring 与不同包中的模型进行消息传递
Spring messaging with models in different packages
这是我正在尝试做的事情:
应用程序 1(消费者)
com.producer.model.Event
- 简单的可序列化模型(id,名称)
应用程序 2(生产者)
com.consumer.integration.model.Event
- 简单的序列化模型(id,名称)
序列化配置
@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
现在当我生成一条消息时
@Override
public void publishEvent(Event event) {
log.debug("Publish event Event : {}", event);
jmsTemplate.convertAndSend(eventTopic, event);
}
消费者
@Override
@JmsListener(destination = "${jmsConfig.eventTopic}", containerFactory = "topicListenerFactory")
public void handleEvent(Event event) {
log.debug("Received an event {}", event);
}
消费方投诉机型包装不一样
MessageConversionException: Failed to resolve type id [com.producer.model.Event]
...
Caused by: java.lang.ClassNotFoundException: com.producer.model.Event
因此反序列化在消费者中失败,因为它找不到以 _type
值传递的包。
为什么我们还需要传递任何包裹相关信息?它泄露了不需要的信息...
处理这些情况的正确方法是什么。应该是比较常见的情况吧?
编辑:
在 Gary Russell 的帮助下,我解决了这个问题。这就是你想要做的。
使用所需的类型在生产者和消费者中定义映射器:
@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
HashMap<String, Class<?>> typeIdMappings = new HashMap<>();
typeIdMappings.put(Event.class.getSimpleName(), Event.class);
converter.setTypeIdMappings(typeIdMappings);
converter.setTypeIdPropertyName("_type");
return converter;
}
重要的是
setTypeIdPropertyName
匹配消费者和生产者
setTypeIdMappings
密钥在消费者和生产者中匹配
这样您就可以使用一个映射器在两个服务之间匹配多个对象。
见
/**
* Specify mappings from type ids to Java classes, if desired.
* This allows for synthetic ids in the type id message property,
* instead of transferring Java class names.
* <p>Default is no custom mappings, i.e. transferring raw Java class names.
* @param typeIdMappings a Map with type id values as keys and Java classes as values
*/
public void setTypeIdMappings(Map<String, Class<?>> typeIdMappings) {
在生产者端将源 class 映射到类型 ID,在消费者端将类型 ID 映射到目标 class。
(这就是它被称为 MappingJackson...
的原因)。
这是我正在尝试做的事情:
应用程序 1(消费者)
com.producer.model.Event
- 简单的可序列化模型(id,名称)
应用程序 2(生产者)
com.consumer.integration.model.Event
- 简单的序列化模型(id,名称)
序列化配置
@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
现在当我生成一条消息时
@Override
public void publishEvent(Event event) {
log.debug("Publish event Event : {}", event);
jmsTemplate.convertAndSend(eventTopic, event);
}
消费者
@Override
@JmsListener(destination = "${jmsConfig.eventTopic}", containerFactory = "topicListenerFactory")
public void handleEvent(Event event) {
log.debug("Received an event {}", event);
}
消费方投诉机型包装不一样
MessageConversionException: Failed to resolve type id [com.producer.model.Event]
...
Caused by: java.lang.ClassNotFoundException: com.producer.model.Event
因此反序列化在消费者中失败,因为它找不到以 _type
值传递的包。
为什么我们还需要传递任何包裹相关信息?它泄露了不需要的信息...
处理这些情况的正确方法是什么。应该是比较常见的情况吧?
编辑:
在 Gary Russell 的帮助下,我解决了这个问题。这就是你想要做的。
使用所需的类型在生产者和消费者中定义映射器:
@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
HashMap<String, Class<?>> typeIdMappings = new HashMap<>();
typeIdMappings.put(Event.class.getSimpleName(), Event.class);
converter.setTypeIdMappings(typeIdMappings);
converter.setTypeIdPropertyName("_type");
return converter;
}
重要的是
setTypeIdPropertyName
匹配消费者和生产者setTypeIdMappings
密钥在消费者和生产者中匹配
这样您就可以使用一个映射器在两个服务之间匹配多个对象。
见
/**
* Specify mappings from type ids to Java classes, if desired.
* This allows for synthetic ids in the type id message property,
* instead of transferring Java class names.
* <p>Default is no custom mappings, i.e. transferring raw Java class names.
* @param typeIdMappings a Map with type id values as keys and Java classes as values
*/
public void setTypeIdMappings(Map<String, Class<?>> typeIdMappings) {
在生产者端将源 class 映射到类型 ID,在消费者端将类型 ID 映射到目标 class。
(这就是它被称为 MappingJackson...
的原因)。