SpringCloud Feign Jackson自定義配置方式
Feign Jackson自定義配置
Spring Cloud Feign 默認支持Spring MVC的注解 使用相同的HttpMessageConverters類轉(zhuǎn)換
官方文檔說明:
Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web.
但是我們一般在返回給前端JSON格式的時候 都會把相應的 NULL值轉(zhuǎn)為相應的"",這使得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;
?? ?}出現(xiàn)的問題
在服務(wù)通過Feign進行請求的時候,傳NULL值引用類型值時,會出現(xiàn)類型轉(zhuǎn)換異常,由于HttpMessageConverters直接把NULL轉(zhuǎn)為了""。
解決思路
自定義配置 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.
解決方法
統(tǒng)一配置Feign 的Encoder和Decoder的Jackson轉(zhuǎn)換方式
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自定義配置應用
環(huán)境
nacos: 1.3.1
啟動nacos
cd /usr/local/nacos/bin
sh startup.sh -m standalone
自定義Feign的配置
1)添加依賴
加入nacos-discovery發(fā)現(xiàn)服務(wù)的依賴、web、actuator用于監(jiān)控檢查,添加openfeign依賴才能使用Feign功能

2)修改配置文件
配置nacos注冊中心地址,因為不提供服務(wù),所以不需要再注冊中心注冊因此register-enabled=false

3)添加Feign支持

配置FeignConfiguration類文件
Spring Cloud Netflix默認的SpringMvcController將替換為feign.Contract.Default
用feign.Contract.Default將契約改為Feign原生的默認契約,就可以使用feign自帶的注解了

4)自定義Feign接口
Feign接口文件需和啟動類再同一包目錄下,使用@FeignClient注解配置所需要調(diào)用服務(wù),此處nacos-provider是需要在注冊中心提供服務(wù)
因為上面配置了feign.Contract.Deafault,所以在接口中可以使用Feign原生的注解@RequestLine

添加HelloController類文件
此處使用接口MyFeignClient調(diào)用hello方法獲取到nacos-provider客戶端提供的服務(wù)

Feign中記錄日志
1)添加配置項
在配置文件中添加記錄日志的包,* 而每個FeignClient都需要單獨配置,它只能響應debug級別的日志

2)設(shè)置日志等級
在FeignConfiguration類文件中配置日志等級

日志等級:
NONE:不記錄(默認)BASIC:只記錄請求方法、URL、響應狀態(tài)碼和執(zhí)行時間HEADERS:記錄基本信息,請求和響應標題FULL: 記錄請求和響應標題、正文和行數(shù)據(jù)
測試Feign自定義的配置
啟動nacos-provider、feign-config客戶端,進入nacos查詢nacos-provider服務(wù)是否注冊

進入瀏覽器端鍵入地址http://localhost:2334/hello,就能訪問到nacos-provider提供的服務(wù)內(nèi)容

查看日志
控制臺會輸出如下信息

[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)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java實現(xiàn)一次性壓縮多個文件到zip中的方法示例
這篇文章主要介紹了java實現(xiàn)一次性壓縮多個文件到zip中的方法,涉及java針對文件批量壓縮相關(guān)的文件判斷、遍歷、壓縮等操作技巧,需要的朋友可以參考下2019-09-09
關(guān)于使用ContextClassLoader遇到的問題
這篇文章主要介紹了關(guān)于使用ContextClassLoader遇到的問題,ContextClassLoader是通過Thread.currentThread().getContextClassLoader()返回該線程上下文的ClassLoader,需要的朋友可以參考下2023-10-10
SpringBoot使用Shiro實現(xiàn)動態(tài)加載權(quán)限詳解流程
本文小編將基于?SpringBoot?集成?Shiro?實現(xiàn)動態(tài)uri權(quán)限,由前端vue在頁面配置uri,Java后端動態(tài)刷新權(quán)限,不用重啟項目,以及在頁面分配給用戶?角色?、?按鈕?、uri?權(quán)限后,后端動態(tài)分配權(quán)限,用戶無需在頁面重新登錄才能獲取最新權(quán)限,一切權(quán)限動態(tài)加載,靈活配置2022-07-07
Intellij Idea修改代碼方法參數(shù)自動提示快捷鍵的操作
這篇文章主要介紹了Intellij Idea修改代碼方法參數(shù)自動提示快捷鍵的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01

