Spring Integration Java DSL — 如何配置 JSON 转换器以采用 Spring boot 的全局设置?



我正在使用集成流来调用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,我只看到ObjectToJsonTransformerMappingJackson2HttpMessageConverter之间的区别,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

最新更新