如何使用 Spring Cloud Netflix Feign 设置自定义 Jackson ObjectMapper
How to set custom Jackson ObjectMapper with Spring Cloud Netflix Feign
我 运行 需要为第三方定义一次性的 @FeignClient API。在此客户端中,我想使用不同于我的@Primary 的自定义 Jackson ObjectMapper。我知道可以覆盖 spring 的假配置默认值,但是我不清楚如何仅通过这个特定的客户端简单地覆盖 ObjectMapper。
根据 documentation,您可以为您的 Feign 客户端提供自定义解码器,如下所示。
Feign 客户端界面:
@FeignClient(value = "foo", configuration = FooClientConfig.class)
public interface FooClient{
//Your mappings
}
Feign 客户端自定义配置:
@Configuration
public class FooClientConfig {
@Bean
public Decoder feignDecoder() {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jacksonConverter);
ObjectFactory<HttpMessageConverters> objectFactory = () -> httpMessageConverters;
return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
}
public ObjectMapper customObjectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
//Customize as much as you want
return objectMapper;
}
}
关注@NewBie的回答,我可以给更好的...
@Bean
public Decoder feignDecoder() {
return new JacksonDecoder();
}
如果您想在 feign 客户端中使用 jackson 消息转换器,请使用 JacksonDecoder,因为 SpringDecoder 会增加 feignclient 调用的平均延迟在生产中。
<!-- feign-jackson decoder -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>10.1.0</version>
</dependency>
如下定义一个自定义解码器,用@Configuration
注释并设置为假客户端界面的参数,configuration = CustomFeignClientConfig.class
@Configuration
public class CustomFeignClientConfig {
@Bean
public Decoder feignDecoder() {
return (response, type) -> {
String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
JavaType javaType = TypeFactory.defaultInstance().constructType(type);
return new ObjectMapper().readValue( bodyStr, javaType);
};
}
}
@NewBie 的回答存在严重的性能问题。 new HttpMessageConverters
过程中,会执行loadclass,导致大量线程阻塞。如果您使用过此代码,请修改如下:
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
改为
HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jacksonConverter);
ObjectFactory<HttpMessageConverters> objectFactory = () -> httpMessageConverters;
您可以使用JMeter和Arthas重现该现象,修改后的程序有了很大的提升。
我 运行 需要为第三方定义一次性的 @FeignClient API。在此客户端中,我想使用不同于我的@Primary 的自定义 Jackson ObjectMapper。我知道可以覆盖 spring 的假配置默认值,但是我不清楚如何仅通过这个特定的客户端简单地覆盖 ObjectMapper。
根据 documentation,您可以为您的 Feign 客户端提供自定义解码器,如下所示。
Feign 客户端界面:
@FeignClient(value = "foo", configuration = FooClientConfig.class)
public interface FooClient{
//Your mappings
}
Feign 客户端自定义配置:
@Configuration
public class FooClientConfig {
@Bean
public Decoder feignDecoder() {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jacksonConverter);
ObjectFactory<HttpMessageConverters> objectFactory = () -> httpMessageConverters;
return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
}
public ObjectMapper customObjectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
//Customize as much as you want
return objectMapper;
}
}
关注@NewBie的回答,我可以给更好的...
@Bean
public Decoder feignDecoder() {
return new JacksonDecoder();
}
如果您想在 feign 客户端中使用 jackson 消息转换器,请使用 JacksonDecoder,因为 SpringDecoder 会增加 feignclient 调用的平均延迟在生产中。
<!-- feign-jackson decoder -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>10.1.0</version>
</dependency>
如下定义一个自定义解码器,用@Configuration
注释并设置为假客户端界面的参数,configuration = CustomFeignClientConfig.class
@Configuration
public class CustomFeignClientConfig {
@Bean
public Decoder feignDecoder() {
return (response, type) -> {
String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
JavaType javaType = TypeFactory.defaultInstance().constructType(type);
return new ObjectMapper().readValue( bodyStr, javaType);
};
}
}
@NewBie 的回答存在严重的性能问题。 new HttpMessageConverters
过程中,会执行loadclass,导致大量线程阻塞。如果您使用过此代码,请修改如下:
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
改为
HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jacksonConverter);
ObjectFactory<HttpMessageConverters> objectFactory = () -> httpMessageConverters;
您可以使用JMeter和Arthas重现该现象,修改后的程序有了很大的提升。