SpringCloud OpenFeign 參數(shù)傳遞和響應(yīng)處理的詳細(xì)步驟
一、OpenFeign 參數(shù)傳遞和響應(yīng)處理
1.1、feign 客戶端參數(shù)傳遞
1.1.1、零散類型參數(shù)傳遞
OpenFeign 對(duì)零散類型參數(shù)傳遞有以下限制
- querystring 方式傳遞參數(shù)(例如 "/user?name=cyk" ):在 openfeign 接口聲明中必須要給參數(shù)加入 @RequestParam 注解/
- restful 路徑傳參(例如 "/user/{id}/{name}" ):在 openfeign 接口聲明中必須要給參數(shù)加入注解 @PathVariable 注解.
為什么 openfeign 要這樣區(qū)分呢?
因?yàn)?openfeign 是 偽HttpClient 對(duì)象,我們?cè)谶h(yuǎn)程調(diào)用他的客戶端提供的接口時(shí),并不知道你到底是路徑傳參還是問號(hào)傳參,因此需要通過注解的方式來指明傳參方式(就像 Spring Web 一樣,只不過 Spring Web 中如果沒指明傳參類型,底層會(huì)按默認(rèn)方式走,而 openfeign 則沒有).
1. 例如 querystring 方式傳參
a)遠(yuǎn)程調(diào)用方
@RestController @RequestMapping("/user") public class UserController { @Autowired private ProductClient productClient; @GetMapping("/test1") public String test1(Long id) { String info = productClient.getInfo(id); System.out.println(info); return "user ok! \n" + info; } }
b)服務(wù)提供方
@RestController @RequestMapping("/product") public class ProductController { @GetMapping("/get_info") public String getInfo(Long id) { return "product ok! id=" + id; } }
c)feign 客戶端
@FeignClient(value = "product", configuration = LoadBalancerClientConfiguration.class) public interface ProductClient { @GetMapping("/product/get_info") String getInfo(@RequestParam("id") Long id); }
d)測試結(jié)果:
2. 例如路徑方式傳參
a)遠(yuǎn)程調(diào)用方
@RestController @RequestMapping("/user") public class UserController { @Autowired private ProductClient productClient; @GetMapping("/test2") public String test2(String name) { String info = productClient.getName(name); System.out.println(info); return "user ok! \n" + info; } }
b)服務(wù)提供方
@RestController @RequestMapping("/product") public class ProductController { @GetMapping("/{name}") public String getName(@PathVariable("name") String name) { return "product ok! name=" + name; } }
c)feign 客戶端
@FeignClient(value = "product", configuration = LoadBalancerClientConfiguration.class) public interface ProductClient { @GetMapping("/product/{name}") String getName(@PathVariable("name") String name); }
d)測試結(jié)果:
擴(kuò)展:restful 和 問號(hào)傳參的區(qū)別
RESTful 風(fēng)格是一種基于 HTTP 協(xié)議的 API 設(shè)計(jì)風(fēng)格,它通過使用不同的 HTTP 方法(GET、POST、PUT、DELETE 等)和不同的 URL 來表示不同的操作和資源。RESTful 風(fēng)格的優(yōu)點(diǎn)包括:
- 清晰、簡潔的 URL 設(shè)計(jì):RESTful 風(fēng)格的 URL 通常比較簡潔,易于理解和記憶,能夠清晰地表達(dá)出資源的結(jié)構(gòu)和操作。
- 良好的可擴(kuò)展性:RESTful 風(fēng)格的設(shè)計(jì)允許你在原有的 API 上添加新的資源和方法,而不會(huì)對(duì)原有的 API 造成影響。
- 支持緩存:RESTful 風(fēng)格的 API 可以利用 HTTP 緩存機(jī)制,提高 API 的響應(yīng)速度和性能。
- 跨平臺(tái)、跨語言:RESTful 風(fēng)格的 API 可以被不同的平臺(tái)和語言調(diào)用,具有很好的兼容性和可集成性。
問號(hào)傳參風(fēng)格是一種通過在 URL 中使用問號(hào)傳參的方式來傳遞參數(shù)的 API 設(shè)計(jì)風(fēng)格。它的優(yōu)點(diǎn)包括:
- 動(dòng)態(tài)參數(shù)傳遞:問號(hào)傳參風(fēng)格允許你在 URL 中直接傳遞參數(shù),可以方便地實(shí)現(xiàn)動(dòng)態(tài)參數(shù)的傳遞。
- 支持復(fù)雜參數(shù)類型:問號(hào)傳參風(fēng)格可以支持復(fù)雜的數(shù)據(jù)類型,例如對(duì)象、數(shù)組等,能夠更好地滿足復(fù)雜參數(shù)傳遞的需求。
- 易于開發(fā)和實(shí)現(xiàn):問號(hào)傳參風(fēng)格的 API 開發(fā)起來相對(duì)簡單,容易實(shí)現(xiàn)和調(diào)試。
總的來說,如果你需要設(shè)計(jì)一個(gè)簡單的 API,并且對(duì)性能和擴(kuò)展性要求不高,問號(hào)傳參風(fēng)格可能是一個(gè)不錯(cuò)的選擇。而如果你需要設(shè)計(jì)一個(gè)復(fù)雜的 API,需要支持緩存、擴(kuò)展性、跨平臺(tái)和跨語言等要求,那么 RESTful 風(fēng)格可能更適合你的需求。
1.1.2、對(duì)象參數(shù)傳遞
對(duì)象參數(shù)傳遞方式有兩種,一種是 form 表單提交,另一種是 application/json 方式(推薦),這里主要講第二種方式(實(shí)際開發(fā)中用的).
openfeign 接口要求對(duì)象傳參必須要使用 @RequestBody 注解指明類型.
原因:這就像是我們給后端傳遞一個(gè) json 格式數(shù)據(jù)類型,然后后端使用 一個(gè)對(duì)象接收參數(shù),并通過 @RequestBody 指明他是 json 格式.
注意:openfeign 中對(duì)象傳參只能使用 POST,并且也符合使用習(xí)慣,最主要是因?yàn)?GET 請(qǐng)求傳對(duì)象會(huì)報(bào)錯(cuò) Method Not Allowed.
1. 對(duì)象參數(shù)傳遞案例
a)遠(yuǎn)程調(diào)用方
@RestController @RequestMapping("/user") public class UserController { @Autowired private ProductClient productClient; @GetMapping("/test3") public String test3(@RequestBody User user) { user.setUsername(user.getUsername()); user.setPassword(user.getPassword()); String userinfo = productClient.getUser(user); return "user ok! \n" + userinfo; } }
b)服務(wù)提供方
@RestController @RequestMapping("/product") public class ProductController { @PostMapping("/get_user") public String getUser(@RequestBody User user) { return "product ok! " + user.toString(); } }
c)feign 客戶端
@FeignClient(value = "product", configuration = LoadBalancerClientConfiguration.class) public interface ProductClient { //注意:openfeign 中對(duì)象傳參只能使用 POST,并且也符合使用習(xí)慣 //GET 請(qǐng)求傳對(duì)象會(huì)報(bào)錯(cuò): Method Not Allowed @PostMapping("/product/get_user") String getUser(@RequestBody User user); }
d)測試結(jié)果:
1.1.3、數(shù)組參數(shù)傳遞
數(shù)組參數(shù)傳遞要求在 feign 客戶端接口使用 @RequestParam 注解指明參數(shù)類型.
原因:數(shù)組參數(shù)傳遞,實(shí)際上就是 querystring 方式傳參,例如 " /user/?name=123&name=456&name=789 ",其中 name 就是數(shù)組.
1. 數(shù)組傳參案例
a)遠(yuǎn)程調(diào)用方
@RestController @RequestMapping("/user") public class UserController { @Autowired private ProductClient productClient; @GetMapping("/test4") public String test4(String[] arr) { String result = productClient.getArr(arr); return "user ok! \n" + result; } }
b)服務(wù)提供方
@RestController @RequestMapping("/product") public class ProductController { @GetMapping("/get_arr") public String getArr(@RequestParam("arr") String[] arr) { return "product ok!" + Arrays.toString(arr); } }
c)feign 客戶端
@FeignClient(value = "product", configuration = LoadBalancerClientConfiguration.class) public interface ProductClient { @GetMapping("/product/get_arr") String getArr(@RequestParam("arr") String[] arr); }
d)測試結(jié)果
1.1.4、集合類型的參數(shù)傳遞(了解)
spring mvc 不能直接接收集合類型參數(shù)(例如 List)!如果一定要接收,需要將集合類型參數(shù)放入對(duì)象中,然后使用對(duì)象的方式傳遞.
例如如下:
@Data public class User { private String username; private String password; private List<String> arr; }
這里就不演示了,因?yàn)?使用方式 以及 注意事項(xiàng) 和對(duì)象傳遞參數(shù)一樣.
1.2、feign 客戶端響應(yīng)處理
1.2.1、天坑!
這里我們只需要知道一點(diǎn)就可以,F(xiàn)eign 客戶端不能處理 Object 這種類型的返回格式!無論是對(duì)象中包含 Object 類型還是 Map 中存在 Object 類型....... 只要有他,就會(huì)出現(xiàn)各種格式問題.
例如,服務(wù)提供方傳入的是一個(gè) Long 類型,但是遠(yuǎn)程調(diào)用方接收到參數(shù)之后就變成了 Integer 類型(這里的處理,和 RabbitMQ 消息發(fā)送后的格式轉(zhuǎn)化一個(gè)尿性),強(qiáng)轉(zhuǎn)就會(huì)報(bào)以下錯(cuò)誤:
ChatGPT 給出了以下解釋:
這是因?yàn)?OpenFeign 在默認(rèn)情況下會(huì)自動(dòng)將對(duì)象和 Map 對(duì)象轉(zhuǎn)換成 JSON 格式。它使用了 Jackson 作為默認(rèn)的序列化/反序列化庫。當(dāng)你在使用 OpenFeign 進(jìn)行遠(yuǎn)程調(diào)用時(shí),返回的對(duì)象會(huì)被自動(dòng)轉(zhuǎn)換成 JSON 格式。
然而,需要注意的是,OpenFeign 只能處理簡單的 Java 對(duì)象和 Map 對(duì)象,對(duì)于復(fù)雜的 Java 對(duì)象或包含特殊類型的對(duì)象,可能無法自動(dòng)進(jìn)行正確的序列化和反序列化。在這種情況下,你可能需要自定義序列化/反序列化方式,或者使用其他序列化庫來替代默認(rèn)的 Jackson。
1.2.2、解決辦法
只要服務(wù)提供方的返回值類型涉及到 Object 、對(duì)象、Map 這些復(fù)雜類型,都可以在 Feign 客戶端使用 String 類型作為接口返回值類型(因?yàn)?openfeign 會(huì)自動(dòng)轉(zhuǎn)換為 json 格式),遠(yuǎn)程調(diào)用方接收到響應(yīng)之后,就可以使用 ObjectMapper.readValue() 反序列化成我們所需要的對(duì)象即可.
案例一
a)遠(yuǎn)程調(diào)用方
@RestController @RequestMapping("/user") public class UserController { @Autowired private ProductClient productClient; @Autowired private ObjectMapper objectMapper; @SneakyThrows @GetMapping("/test6") public String test6() { String data = productClient.getData(); Long finalData = objectMapper.readValue(data, Long.class); return "user ok!" + finalData; } }
b)服務(wù)提供方
@RestController @RequestMapping("/product") public class ProductController { @GetMapping("/get_data") public Object getData() { return 100L; } }
c)feign 客戶端
@FeignClient(value = "product", configuration = LoadBalancerClientConfiguration.class) public interface ProductClient { @GetMapping("/product/get_data") String getData(); }
測試結(jié)果:
案例二(復(fù)雜數(shù)據(jù)類型)
a)Feign 客戶端接口響應(yīng)類型
@Data public class User { private String username; private String password; private List<String> arr; }
b)遠(yuǎn)程調(diào)用方
@RestController @RequestMapping("/user") public class UserController { @Autowired private ProductClient productClient; @Autowired private ObjectMapper objectMapper; @GetMapping("/test5") public String test5() throws JsonProcessingException { User user = new User(); user.setUsername("cyk"); user.setPassword("1111"); List<String> arrayList = new ArrayList<>(); arrayList.add("aaa"); arrayList.add("bbb"); user.setArr(arrayList); String userList = productClient.getUserList(user); User user2 = objectMapper.readValue(userList, User.class); System.out.println(user2); return "user ok! \n" + userList; } }
c)服務(wù)提供方
@RestController @RequestMapping("/product") public class ProductController { @PostMapping("/get_user_list") public User getUserList(@RequestBody User user) { return user; } }
d)feign 客戶端
@FeignClient(value = "product", configuration = LoadBalancerClientConfiguration.class) public interface ProductClient { @PostMapping("/product/get_user_list") String getUserList(@RequestBody User user); }
測試結(jié)果:
到此這篇關(guān)于SpringCloud OpenFeign 參數(shù)傳遞和響應(yīng)處理的文章就介紹到這了,更多相關(guān)SpringCloud OpenFeign 參數(shù)傳遞內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringCloud基于Feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用的問題小結(jié)
- SpringCloud Alibaba微服務(wù)實(shí)戰(zhàn)之遠(yuǎn)程Feign請(qǐng)求頭丟失問題解決方案
- Spring?cloud?OpenFeign中動(dòng)態(tài)URl、動(dòng)態(tài)傳遞接口地址代碼示例
- SpringCloud中的Feign服務(wù)間的調(diào)用詳解
- 解決Spring調(diào)用Feign報(bào)錯(cuò):java.io.IOException:Incomplete output stream問題
相關(guān)文章
Java實(shí)現(xiàn)快速排序和堆排序的示例代碼
這篇文章主要為大家詳細(xì)介紹了快速排序和堆排序的多種語言的實(shí)現(xiàn)(JavaScript、Python、Go語言、Java、C++),感興趣的小伙伴可以了解一下2022-12-12SpringCloud入門實(shí)驗(yàn)環(huán)境搭建
這篇文章主要介紹了SpringCloud入門實(shí)驗(yàn)環(huán)境搭建的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用SpringCloud,感興趣的朋友可以了解下2021-04-04Java中ConcurrentHashMap是如何實(shí)現(xiàn)線程安全
ConcurrentHashMap是一個(gè)哈希表,支持檢索的全并發(fā)和更新的高預(yù)期并發(fā)。本文主要介紹了Java中ConcurrentHashMap是如何實(shí)現(xiàn)線程安全,感興趣的可以了解一下2021-11-11Mybatis如何按順序查詢出對(duì)應(yīng)的數(shù)據(jù)字段
這篇文章主要介紹了Mybatis如何按順序查詢出對(duì)應(yīng)的數(shù)據(jù)字段,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Javaweb項(xiàng)目session超時(shí)解決方案
這篇文章主要介紹了Javaweb項(xiàng)目session超時(shí)解決方案,關(guān)于解決方案分類比較明確,內(nèi)容詳細(xì),需要的朋友可以參考下。2017-09-09Spring?Boot+RabbitMQ?通過fanout模式實(shí)現(xiàn)消息接收功能(支持消費(fèi)者多實(shí)例部署)
這篇文章主要介紹了Spring?Boot+RabbitMQ?通過fanout模式實(shí)現(xiàn)消息接收(支持消費(fèi)者多實(shí)例部署),本文通過案例場景分析給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03Spring Boot 整合 TKMybatis 二次簡化持久層代碼的實(shí)現(xiàn)
這篇文章主要介紹了Spring Boot 整合 TKMybatis 二次簡化持久層代碼的實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01Spring cloud alibaba之Ribbon負(fù)載均衡實(shí)現(xiàn)方案
Spring cloud Ribbon是基于Netflix Ribbon實(shí)現(xiàn)的一套客戶端的負(fù)載均衡工具,Ribbon客戶端提供一系列完善的配置,如超時(shí)、重試等,Ribbon也可以實(shí)現(xiàn)自己的負(fù)載均衡算法,感興趣的朋友跟隨小編一起看看吧2021-07-07