Spring Cloud Feign 默认支持Spring MVC的注解 使用相同的HttpMessageConverters类转换
官方文档说明:
Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web.
但是我们一般在返回给前端JSON格式的时候 都会把相应的 NULL值转为相应的””,这使得Spring Cloud Feign也使用相同的Jackson配置,例如我们项目的配置
@Bean
public ObjectMapper jacksonObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// objectMapper.setSerializationInclusion(Include.NON_NULL);
objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer() {
@Override
public void serialize(Object value, JsonGenerator jg, SerializerProvider sp)
throws IOException, JsonProcessingException {
jg.writeString("");
sp.getDefaultNullKeySerializer();
}
});
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
return objectMapper;
}
出现的问题:
在服务通过Feign进行请求的时候,传NULL值引用类型值时,会出现类型转换异常,由于HttpMessageConverters直接把NULL转为了””。
解决思路:
自定义配置 Spring Cloud Feign Encoder与Decoder
官方文档说明:
Spring Cloud Netflix provides the following beans by default for feign (BeanType beanName: ClassName):
Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
Encoder feignEncoder: SpringEncoder
Logger feignLogger: Slf4jLogger
Contract feignContract: SpringMvcContract
Feign.Builder feignBuilder: HystrixFeign.Builder
Client feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the default feign client is used.
解决方法:
统一配置Feign 的Encoder和Decoder的Jackson转换方式
@Configuration
public class CustomFeignConfig {
@Bean
public Decoder feignDecoder() {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
ObjectFactory objectFactory = () -> new HttpMessageConverters(jacksonConverter);
return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
}
@Bean
public Encoder feignEncoder(){
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
ObjectFactory objectFactory = () -> new HttpMessageConverters(jacksonConverter);
return new SpringEncoder(objectFactory);
}
public ObjectMapper customObjectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
//Customize as much as you want
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
return objectMapper;
}
}