自定义对象映射器 bean 更改打开 Feign 客户端的默认属性/自动配置的 objectMapper bean
Posted
技术标签:
【中文标题】自定义对象映射器 bean 更改打开 Feign 客户端的默认属性/自动配置的 objectMapper bean【英文标题】:Custom object mapper bean changing the default properties of open Feign Client / auto configured objectMapper bean 【发布时间】:2020-07-21 00:37:04 【问题描述】:我有 spring 的 open feign 客户端配置,如下所示:
public class AppFeignConfiguration
@Bean
public ErrorDecoder errorDecoder()
return new FeignErrorDecoder();
@Bean
public Logger.Level logger()
return Logger.Level.FULL;
@Bean
public Request.Options options()
return new Request.Options( 30000, 30000 );
我在@FeignClient
中将其作为配置提供,如下所示
@FeignClient ( value = "apigateway-service", configuration = AppFeignConfiguration.class)
我相信 FeignClient 具有反序列化响应的默认配置(可能是具有某些属性的 ObjectMapper)。
到目前为止一切顺利。一切都按预期工作。
然后我创建了一个自定义对象映射器并将其作为 bean 返回,如下所示:
@Configuration
public class ObjectMapperConfig
@Bean ( name = "plainObjectMapper")
public ObjectMapper plainObjectMapper()
return new ObjectMapper();
现在的问题是,这弄乱了FeignClient
的默认反序列化配置。
意思是,如果没有自定义 plainObjectMapper
,它过去可以正常工作,没有任何 json 解析错误。但是在将自定义 plainObjectMapper
创建为 bean 之后,FeignClient
会抛出异常,说明一些未知属性或其他内容。
nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized field "xyz" (class abc.def.ghi.class), not marked as ignorable; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException
我通过删除自定义 plainObjectMapper
确认了这一点,它和以前一样工作正常。
这似乎很奇怪!我给 bean 起了一个自定义名称,它不应该与 springboot 创建的 bean 混淆。
我该如何克服这种冲突?
【问题讨论】:
【参考方案1】:这并不完全正确。
如果您查看FeignClientsConfiguration
source,您可以看到它的编码器依赖于HttpMessageConverters
类。
那么,HttpMessageConvertersAutoConfiguration
(source) 本身依赖于JacksonAutoConfiguration
。
仅当上下文中没有手动创建的对象映射器时,后者才会创建默认的 ObjectMapper
bean(请参阅 @ConditionalOnMissingBean
on the corresponding method) - 在这种情况下,不同的 bean 名称无关紧要。
所以,Feign 会隐含地依赖这个自动配置的ObjectMapper
,但只有在你创建自己的之前。然后它开始使用你的。与许多其他春豆一样。
如果你真的需要拥有自己的ObjectMapper
bean,那么你需要正确配置它。但是您可以通过配置属性自定义自动配置的 - 请参阅docs。
【讨论】:
但是@amseager,springboot自己创建了一个ObjectMapper的bean。这怎么不污染 FeignClient 的 ObjectMapper? 经过一番研究,我发现ObjectMapper
是由一个或另一个自动配置创建的,如果它不存在的话。如果我创建一个相同的文件,所有需要对象映射器的依赖项都将使用我创建的那个。整个应用程序中只有一个 ObjectMapper bean。当我们需要多个具有不同属性的 bean 时,这不会引起问题吗?
是的,在许多其他库(包括spring-cloud-openfeign
)使用的常规 Spring Boot 应用程序中只有一个 ObjectMapper
自动配置 bean。由于@ConditionalOn...
注释,它不会在您手动执行时创建。这就是弹簧靴的魔力结束的地方。因此,作为最简单的解决方案,我不建议您尽可能创建自己的 ObjectMapper
bean(或多个 bean),而是自定义默认值。
我明白了。但这不是缺陷吗?我的意思是为其他目的定制的 bean 正在污染其他一些autoconfigured bean
的属性。现在,如果我想继续使用自动配置和自定义 bean,我必须从自动配置中复制所有属性。
自定义默认 ObjectMapper
根本不是解决方案,因为这仍然会影响使用此 bean 的所有其他内容。这是春天的愚蠢,ObjectMapper
s 不应该这样分享。当您的应用程序使用 REST、Feign、RabbitMQ 等,并且还需要自定义 ObjectMapper
时,几乎不可能只自定义默认值以适应所有这些不同的需求。以上是关于自定义对象映射器 bean 更改打开 Feign 客户端的默认属性/自动配置的 objectMapper bean的主要内容,如果未能解决你的问题,请参考以下文章
Spring 4 中 Websockets 的自定义对象映射器