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;
}
}