SpringCloud Feign Jackson自定义配置方式
作者:zhaoyang10
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: 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<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()); } }); } }
Feign自定义配置应用
环境
nacos: 1.3.1
启动nacos
cd /usr/local/nacos/bin
sh startup.sh -m standalone
自定义Feign的配置
1)添加依赖
加入nacos-discovery发现服务的依赖、web、actuator用于监控检查,添加openfeign依赖才能使用Feign功能
2)修改配置文件
配置nacos注册中心地址,因为不提供服务,所以不需要再注册中心注册因此register-enabled=false
3)添加Feign支持
配置FeignConfiguration类文件
Spring Cloud Netflix默认的SpringMvcController将替换为feign.Contract.Default
用feign.Contract.Default将契约改为Feign原生的默认契约,就可以使用feign自带的注解了
4)自定义Feign接口
Feign接口文件需和启动类再同一包目录下,使用@FeignClient注解配置所需要调用服务,此处nacos-provider是需要在注册中心提供服务
因为上面配置了feign.Contract.Deafault,所以在接口中可以使用Feign原生的注解@RequestLine
添加HelloController类文件
此处使用接口MyFeignClient调用hello方法获取到nacos-provider客户端提供的服务
Feign中记录日志
1)添加配置项
在配置文件中添加记录日志的包,* 而每个FeignClient都需要单独配置,它只能响应debug级别的日志
2)设置日志等级
在FeignConfiguration类文件中配置日志等级
日志等级:
NONE
:不记录(默认)BASIC
:只记录请求方法、URL、响应状态码和执行时间HEADERS
:记录基本信息,请求和响应标题FULL
: 记录请求和响应标题、正文和行数据
测试Feign自定义的配置
启动nacos-provider、feign-config客户端,进入nacos查询nacos-provider服务是否注册
进入浏览器端键入地址http://localhost:2334/hello,就能访问到nacos-provider提供的服务内容
查看日志
控制台会输出如下信息
[MyFeignClient#hello] <— HTTP/1.1 200 (405ms)
2020-08-13 16:16:23.021 DEBUG 3680 — [nio-2334-exec-1] com.kk.feign.MyFeignClient : [MyFeignClient#hello] content-length: 16
2020-08-13 16:16:23.021 DEBUG 3680 — [nio-2334-exec-1] com.kk.feign.MyFeignClient : [MyFeignClient#hello] content-type: text/plain;charset=UTF-8
2020-08-13 16:16:23.021 DEBUG 3680 — [nio-2334-exec-1] com.kk.feign.MyFeignClient : [MyFeignClient#hello] date: Thu, 13 Aug 2020 08:16:23 GMT
2020-08-13 16:16:23.021 DEBUG 3680 — [nio-2334-exec-1] com.kk.feign.MyFeignClient : [MyFeignClient#hello]
2020-08-13 16:16:23.021 DEBUG 3680 — [nio-2334-exec-1] com.kk.feign.MyFeignClient : [MyFeignClient#hello] Hello Gateway A!
2020-08-13 16:16:23.021 DEBUG 3680 — [nio-2334-exec-1] com.kk.feign.MyFeignClient : [MyFeignClient#hello] <— END HTTP (16-byte body)
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。