Feign接口方法返回值設(shè)置方式
一、介紹
隨著微服務(wù)的廣泛應(yīng)用,越來越多的企業(yè)都會(huì)使用微服務(wù)進(jìn)行項(xiàng)目開發(fā),在各個(gè)服務(wù)之間需要通過feign來進(jìn)行通信,所以在feign調(diào)用接口中方法會(huì)接受其他服務(wù)接口不同類型返回值。
二、返回值設(shè)置
1、依據(jù)被調(diào)用服務(wù)接口設(shè)置相同返回類型
介紹:微服務(wù)A接口getUser 返回List<User>類型,微服務(wù)B通過feign調(diào)用方法也返回相同的結(jié)果類型。
特點(diǎn):返回類型一一對(duì)應(yīng),在調(diào)用時(shí)不需要進(jìn)行轉(zhuǎn)化直接拿來就可以用。
缺點(diǎn):擴(kuò)展性不好,維護(hù)性不加。
解釋:在目前springboot開發(fā)中,接口一般都會(huì)返回json類型數(shù)據(jù)(也就是使用@restController或者使用@ResponseBody注解修飾),就算是對(duì)象或者對(duì)象集合也是一樣的,或者其他自己封裝的返回對(duì)象。如果有許多不同的返回對(duì)象,當(dāng)這些返回對(duì)象在A服務(wù)做了修改相應(yīng)的在B服務(wù)的feign接口處也要做修改,相當(dāng)麻煩且不符合java面向接口編程思想。
2、全部設(shè)置為String
介紹:微服務(wù)A接口只要被@restController或者使用@ResponseBody注解修飾我統(tǒng)統(tǒng)在微服務(wù)Bfeign接口使用String來進(jìn)行接受。
特點(diǎn):通過String來接受返回參數(shù),格式一致。
缺點(diǎn):后面調(diào)用需要轉(zhuǎn)換。
代碼介紹:
// 微服務(wù)A controller 已經(jīng)使用@restController修飾
@PostMapping(value="/getAllQuestionBank",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public List<QuestionBankDto> getAllQuestionBank(){
return baseinfoQuestionMange.getAllQuestionBank();
}
// 微服務(wù)B feign接口 使用String進(jìn)行接受
@PostMapping(value="/baseinfo/getAllQuestionBank")
String getAllQuestionBank();
// 微服務(wù)B 當(dāng)需要調(diào)用feign信息時(shí)需要強(qiáng)轉(zhuǎn)成List<QuestionBankDto>格式
// 調(diào)用微服務(wù)獲取題庫章節(jié)信息,該處強(qiáng)制使用try catch進(jìn)行包裹
String questionBankInfo = baseInfoApi.getAllQuestionBank();
List<QuestionBankDto> mysqlQuestionBank = objectMapper.readValue(questionBankInfo,new TypeReference<ArrayList<QuestionBankDto>>(){});

只要你導(dǎo)入一下springboot依賴,它默認(rèn)就給你導(dǎo)入了Jackson jar包

注意事項(xiàng):使用該方式時(shí)需要將ObjectMapper配置到bean容器中。

3、總結(jié)
項(xiàng)目不同,需求不同,兩種方式?jīng)]有誰對(duì)誰錯(cuò)之分,依據(jù)自己項(xiàng)目需求進(jìn)行選擇。
Feign 使用這幾天遇到的一些問題
事情的起因要從我打算調(diào)用下paas模塊服務(wù)開始
Feign 現(xiàn)在教程很多,然后引入下pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
自己定義下接口
@FeignClient(name = "weixinTokenClient", url = "https://qyapi.weixin.qq.com/cgi-bin")
public interface IWeiXinTokenClient {
/**
* 獲取應(yīng)用的token
* @param corpid
* @param corpsecret
* @return
*/
@RequestMapping(value = "/gettoken", method = RequestMethod.GET)
WeiXinTokenResultModel getToken(@RequestParam String corpid, @RequestParam String corpsecret);
}
寫個(gè)test類測試下,完美返回,因?yàn)樽约簩戇^類似的項(xiàng)目,可以看下lemur-http,原理大體一致,想了想還是簡單的.但是后面的問題就出來
1. nacos 配置拿不到服務(wù)
原因是:nacos注冊(cè)服務(wù)只注冊(cè)了lemur-admin和lemur-paas這種服務(wù)級(jí)別的服務(wù),獲取服務(wù)地址需要用lemur-admin服務(wù),但是在admin調(diào)用paas接口的時(shí)候
@FeignClient(value = "paasUserFacade", contextId = "lemur-paas", path = "/im/user")
public interface IPaasUserFacade extends IBaseController<PaasUserRequestModel> {
}
@FeignClient注解不論是value,name,contextId ,serviceId全都是當(dāng)做了name,所以在獲取nacos地址的地方都是用paasUserFacade去匹配的,根本無法拿到,最終一直跟了N遍代碼,也沒有找打解決辦法,自己還是改了源碼FeignClientFactoryBean,在注冊(cè)bean的地方還是使用value ,并且不用contextId 注冊(cè)別名,意義不大,還重名,把contextId 當(dāng)做服務(wù)Id,feign是通過target來做地址解析的,所以只要把target的url地址改為lemur-paas/im/user就可以了
<T> T getTarget() {
FeignContext context = this.applicationContext.getBean(FeignContext.class);
Feign.Builder builder = feign(context);
if (!StringUtils.hasText(this.url)) {
if (StringUtils.hasText(this.contextId) && !this.name.startsWith("http")){
this.url = "http://" + this.contextId;
}else if (StringUtils.hasText(this.contextId)){
this.url = this.contextId;
} else if (!this.name.startsWith("http")) {
this.url = "http://" + this.name;
}
else {
this.url = this.name;
}
this.url += cleanPath();
return (T) loadBalance(builder, context,
new HardCodedTarget<>(this.type, this.name, this.url));
}
if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
this.url = "http://" + this.url;
}
String url = this.url + cleanPath();
Client client = getOptional(context, Client.class);
if (client != null) {
if (client instanceof LoadBalancerFeignClient) {
// not load balancing because we have a url,
// but ribbon is on the classpath, so unwrap
client = ((LoadBalancerFeignClient) client).getDelegate();
}
builder.client(client);
}
Targeter targeter = get(context, Targeter.class);
return (T) targeter.target(this, builder, context,
new HardCodedTarget<>(this.type, this.name, url));
}
改完源碼之后,算是可以互相調(diào)用了
2.fastjson 不支持abstract class ,關(guān)鍵是不報(bào)錯(cuò),直接返回null
因?yàn)轱L(fēng)鈴統(tǒng)一返回的都是Response對(duì)象,加泛型,結(jié)果怎么調(diào)用返回的都是null,看看被調(diào)用的服務(wù)是有收到請(qǐng)求并返回的,這個(gè)只能是客戶端的問題了,一開始以為是泛型解析的問題,跟蹤了整個(gè)調(diào)用解析鏈條
ReflectiveFeign.invoke-> SynchronousMethodHandler.invoke-> executeAndDecode->decode(解析對(duì)象)-> ResponseEntityDecoder.decode-> SpringDecoder.decode-> HttpMessageConverterExtractor.extractData(返回泛型)-> FastJsonHttpMessageConverter(真正的解析器).read(type,clazz,inputMessage)-> parseObject(is)
然后發(fā)現(xiàn)什么,fastjson無法實(shí)例化對(duì)象,我去你也報(bào)個(gè)錯(cuò)啊,把a(bǔ)bstract去掉,就正常返回了
3.spring gateway 不支持web
spring gateway 因?yàn)槭褂脀ebflux寫的,不是web容器所以不能引入web,在引入feign的時(shí)候要把web去掉,不然起不來
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-web</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
同時(shí)spring gateway 也不支持讀取配置文件,同理原因,像j2cache的文件配置方式就讀取不到
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java(基于Struts2) 分頁實(shí)現(xiàn)代碼
這篇文章介紹了Java(基于Struts2) 分頁實(shí)現(xiàn)代碼,有需要的朋友可以參考一下2013-10-10
java實(shí)現(xiàn)學(xué)生宿舍系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)學(xué)生宿舍系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Java對(duì)MySQL數(shù)據(jù)庫進(jìn)行連接、查詢和修改操作方法
這篇文章主要介紹了Java對(duì)MySQL數(shù)據(jù)庫進(jìn)行連接、查詢和修改操作方法,需要的朋友可以參考下2017-07-07
如何實(shí)現(xiàn)Java的ArrayList經(jīng)典實(shí)體類
ArrayList是Java集合框架中一個(gè)經(jīng)典的實(shí)現(xiàn)類。他比起常用的數(shù)組而言,明顯的優(yōu)點(diǎn)在于,可以隨意的添加和刪除元素而不需考慮數(shù)組的大小。下面跟著小編一起來看下吧2017-02-02
使用MyEclipse 開發(fā)struts2框架實(shí)現(xiàn)登錄功能(結(jié)構(gòu)教程)
這篇文章主要介紹了使用MyEclipse 開發(fā)struts2框架實(shí)現(xiàn)登錄功能(結(jié)構(gòu)教程)的相關(guān)資料,需要的朋友可以參考下2016-03-03
java 同步器SynchronousQueue詳解及實(shí)例
這篇文章主要介紹了java 同步器SynchronousQueue詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05
Java實(shí)現(xiàn)Excel表單控件的添加與刪除
本文通過Java代碼示例介紹如何在Excel表格中添加表單控件,包括文本框、單選按鈕、復(fù)選框、組合框、微調(diào)按鈕等,以及如何刪除Excel中的指定表單控件,需要的可以參考一下2022-05-05
定時(shí)任務(wù)@Scheduled用法及其參數(shù)使用
這篇文章主要介紹了定時(shí)任務(wù)@Scheduled用法及其參數(shù)使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08

