SpringCloud OpenFeign 自定義響應解碼器的問題記錄
一、JsonResult 在 OpenFeign 微服務調用的問題
我們在使用 Spring Cloud 微服務的時候,通常將返回結果使用一個JsonResult 類進行封裝,例如如下的格式:
public class JsonResult<T> { /* 響應碼,200為成功 */ private Integer code; /* 失敗時的具體失敗信息 */ private String message; /* 成功時的數(shù)據(jù)對象 */ private T data; }
而調用方在使用Spring Cloud OpenFeign定義的客戶端調用遠程服務時,由于遠程微服務接口的返回值也是 JsonResult 對象,這樣本地的接口也需要使用 JsonResult 進行接收,這增加了額外的Result類重新拆開等工作。
有沒有辦法實現(xiàn)一些自定義的邏輯,比如將統(tǒng)一返回的Result類重新拆開僅返回對應的業(yè)務對象,或者對特定的響應碼進行處理等等?
二、自定義 OpenFeign 響應解碼器
為了實現(xiàn)上述功能,我們就需要改造默認的Decoder。Spring Cloud OpenFeign允許我們在定義一個FeignClient 的時候,指定一個額外的配置類,比如:
@FeignClient( name = "xxx-base", path = "/api/base", configuration = CustomizedConfiguration.class /* 自定義配置類 */ ) public interface RemoteUserService { //.. }
我們可以在 CustomizedConfiguration 中定義一個自己的 Decoder 來覆蓋默認的配置。
Spring Cloud 對 Feign的封裝和默認配置可以查看官方文檔。
自定義的 Decoder 需要實現(xiàn)feign.codec.Decoder接口,也可以參考默認的Decoder的實現(xiàn)邏輯(org.springframework.cloud.openfeign.support.ResponseEntityDecoder),
下面的實現(xiàn)可以對統(tǒng)一返回值Result類的解包,并對異常返回進行處理:
public class CustomizedConfiguration{ @Bean public Decoder feignDecoder() { return new OpenFeignResultDecoder(); } }
public class OpenFeignResultDecoder implements Decoder { @Resource ObjectMapper objectMapper; @Override public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException { String resultJson = this.getResponseBody(response); try { JavaType rawType = objectMapper.getTypeFactory().constructType(type); JavaType resultType = objectMapper.getTypeFactory().constructParametricType(JsonResult.class, rawType.getRawClass()); JsonResult<?> jsonResult = objectMapper.readValue(resultJson, resultType ); if (jsonResult.getCode() != HttpStatus.OK.value()){ throw new DecodeException( response.status(), jsonResult.getMessage(), response.request()); } return jsonResult.getData(); } catch (Exception ex){ throw new IllegalArgumentException("對象轉換失敗: " + ex.getMessage()); } } /* * 將 response body 解析為 string */ private static String getResponseBody(Response response) throws IOException { Response.Body resBody = response.body(); if (Objects.isNull(resBody)){ throw new DecodeException( response.status(), "返回體為空", response.request()); } String jsonStr; char[] buffer = new char[1024*4]; int len; try ( Reader reader = resBody.asReader(StandardCharsets.UTF_8); StringWriter strWriter = new StringWriter() ){ while ((len = reader.read(buffer)) != -1){ strWriter.write(buffer, 0, len); } jsonStr= strWriter.toString(); } return jsonStr; } }
實現(xiàn)了Decoder之后,只需要將其配置到CustomizedConfiguration中即可。
三、為 FeignClient 注冊全局配置
注意如果CustomizedConfiguration添加了@Configuration的注解,則會成為Feign Client構建的默認配置,這樣就不需要在每個@FeignClient注解中都去指定配置類了:
@Configuration public class OpenFeignConfig { @Bean public Decoder feignDecoder() { return new OpenFeignResultDecoder(); } }
@FeignClient( name = "xxx-base", path = "/api/base" ) public interface RemoteUserService { //.. }
四、使用 OpenFeign 遠程服務示例
添加了自定義的Decoder之后,如果一個遠程接口的定義是這樣的:
@FeignClient( name = "xxx-base", path = "/api/base" ) public interface RemoteUserService { @GetMapping(value = "/user/detail/{userId}") public User getUserDetailById(@PathVariable Integer userId) }
// ... @Resource RemouteUserService userService public void demoUserService(int userId){ User user = userService.getUserDetailById(userId); // .... }
到此這篇關于SpringCloud OpenFeign 自定義響應解碼器的文章就介紹到這了,更多相關SpringCloud OpenFeign解碼器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring實戰(zhàn)之使用Expression接口進行表達式求值操作示例
這篇文章主要介紹了Spring實戰(zhàn)之使用Expression接口進行表達式求值操作,結合實例形式分析了Spring操作Expression接口實現(xiàn)表達式運算的操作技巧與相關注意事項,需要的朋友可以參考下2019-12-12SpringBoot @ConfigurationProperties注解的簡單使用
即便現(xiàn)在簡化了配置,但是一個獨立的配置文件總是易于理解而且使人安心的。Spring在構建完項目后,會默認在resources文件夾下創(chuàng)建一個application.properties文件,application.yml也是一樣的效果。@ConfigurationProperties可以獲取配置文件中的數(shù)據(jù),將其注入類。2021-05-05MyBatis入門實例教程之創(chuàng)建一個簡單的程序
這篇文章主要介紹了MyBatis入門創(chuàng)建一個簡單的程序,在?MySQL?中創(chuàng)建數(shù)據(jù)庫?mybatisdemo,編碼為?utf8,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2022-02-02