Spring Cloud Feign Jackson自定义配置

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<Object>() {
			@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转换方式

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<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
        return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
    }
    @Bean
    public Encoder feignEncoder(){
        HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
        ObjectFactory<HttpMessageConverters> 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;
    }
}

如果配置DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT 不起作用可以试试这种方式

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>(String.class) {
            @Override
            public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException {
               return StringUtils.trimToNull(jsonParser.getValueAsString());
            }
        });
    }
}

你可能感兴趣的:(springcloud2)