我正在使用集成流来调用RESTful Web服务,如下所示:
@Bean
IntegrationFlow flow() throws Exception {
return IntegrationFlows.from("inputChannel")
.handle(Http.outboundGateway("http://provider1.com/...")
.httpMethod(HttpMethod.GET)
.expectedResponseType(ItemDTO[].class))
.get();
}
事实上,上面的代码运行良好。正如我从文档中了解到的那样,Spring 集成的 http outbound-gateway 使用 RestTemplate 的实例将 Http 响应体转换为 ItemDTO
数组。
现在让我们考虑以下代码:
@Bean
IntegrationFlow flow() throws Exception {
return IntegrationFlows.from("inputChannel")
.handle(Http.outboundGateway("http://provider2.com/...")
.httpMethod(HttpMethod.GET)
.expectedResponseType(String.class))
.<String,String>transform(m -> sirenToHal(m))
.transform(Transformers.fromJson(ItemDTO[].class))
.get();
}
在这种情况下,Http 响应体被转换为字符串,该字符串被传递给转换器(例如,在我的实际项目中,我使用 JOLT 从警报器文档转换为 HAL——JSON 资源表示)。然后,我实例化一个转换器来处理 JSON 到 java 对象的映射。令人惊讶的是,上面的代码失败了(例如,在我的项目中,转换器抛出了一个UnrecognizedPropertyException
)。
失败的原因似乎是转换器使用的对象映射器的配置方式与 RestTemplate 不同。我想知道为什么转换器不使用与 RestTemplate 实例相同的 ObjectMapper,或者至少为什么它们不使用相同的配置(即 Spring boot 的全局配置)。无论如何,是否有任何配置对象映射器供转换器使用?
更新
我发现了如何配置转换器的对象映射器。
首先,我们创建并配置 Jackson 的 ObjectMapper 实例,如下所示:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// + any other additional configuration setting
然后,我们按如下方式实例化转换器(替换上面代码中的相应行):
.transform(Transformers.fromJson(ItemDTO[].class, new Jackson2JsonObjectMapper(mapper)))
我仍然认为转换器使用的 ObjectMapper 应该采用 Spring boot 的全局配置。
这是一个有趣的观点,但是由于您没有将RestTemple
注入Http.outboundGateway()
,甚至也没有MappingJackson2HttpMessageConverter
,我只看到ObjectToJsonTransformer
和MappingJackson2HttpMessageConverter
之间的区别,Spring 集成只使用new ObjectMapper()
,当 Spring Web 在其代码中执行此操作时:
public MappingJackson2HttpMessageConverter() {
this(Jackson2ObjectMapperBuilder.json().build());
}
即使 Spring Boot 自动配置 Bean ObjectMapper
我也没有看到这个硬代码对所有这些功能的任何引用。
因此,请确认Jackson2ObjectMapperBuilder.json().build()
在那里也适合您,并随时提出JIRA票证,以协调Spring Integration ObjectMapper
基础架构与Spring Web。
更新
好吧,对我来说,我似乎发现了区别。我是对的 - Jackson2ObjectMapperBuilder
:
// Any change to this method should be also applied to spring-jms and spring-messaging
// MappingJackson2MessageConverter default constructors
private void customizeDefaultFeatures(ObjectMapper objectMapper) {
if (!this.features.containsKey(MapperFeature.DEFAULT_VIEW_INCLUSION)) {
configureFeature(objectMapper, MapperFeature.DEFAULT_VIEW_INCLUSION, false);
}
if (!this.features.containsKey(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
configureFeature(objectMapper, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}
因此,我们还必须将此选项应用于Spring Integration。另请参阅MappingJackson2MessageConverter
。
JIRA关于此事:https://jira.spring.io/browse/INT-4001