Spring Cloud Netflix provides the following beans by default for feign (BeanType beanName: ClassName):Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)Encoder feignEncoder: SpringEncoderLogger feignLogger: Slf4jLoggerContract feignContract: SpringMvcContractFeign.Builder feignBuilder: HystrixFeign.BuilderClient feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the default feign client is used.
解决方法
统一配置Feign 的Encoder和Decoder的Jackson转换方式
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import feign.codec.Decoder;
import feign.codec.Encoder;
@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;
}
}
public ObjectMapper customObjectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
//Customize as much as you want
objectMapper.registerModule(new StringSanitizerModule());
return objectMapper;
}
public class StringSanitizerModule extends SimpleModule {
public StringSanitizerModule() {
addDeserializer(String.class, new StdScalarDeserializer(String.class) {
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException {
return StringUtils.trimToNull(jsonParser.getValueAsString());
}
});
}
}