欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于注解FeignClient的使用規(guī)范

 更新時(shí)間:2022年03月07日 16:58:55   作者:你是豬,  
這篇文章主要介紹了關(guān)于注解FeignClient的使用規(guī)范,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

注解FeignClient使用規(guī)范

首先是對(duì)FeignClient里的常用屬性

  • contextId:當(dāng)有多個(gè)服務(wù)調(diào)用方法不想寫在一個(gè)接口里,就要使用到
  • name:指定FeignClient的名稱,如果項(xiàng)目使用了Ribbon,name屬性會(huì)作為微服務(wù)的名稱,用于服務(wù)發(fā)現(xiàn)
  • url:url一般用于調(diào)試,可以手動(dòng)指定@FeignClient調(diào)用的地址
  • fallback:定義容錯(cuò)的處理類,當(dāng)調(diào)用遠(yuǎn)程接口失敗或超時(shí)時(shí),會(huì)調(diào)用對(duì)應(yīng)接口的容錯(cuò)邏輯,fallback指定的類必須實(shí)現(xiàn)@FeignClient標(biāo)記的接口
  • fallbackFactory:工廠類,用于生成fallback類示例,通過這個(gè)屬性我們可以實(shí)現(xiàn)每個(gè)接口通用的容錯(cuò)邏輯,減少重復(fù)的代碼 
  • path:定義當(dāng)前FeignClient的統(tǒng)一前綴

使用FeignClient的原因

無非讓一個(gè)微服務(wù)的接口被另一個(gè)服務(wù)訪問,微服務(wù)的一個(gè)特點(diǎn)就是業(yè)務(wù)隔離,那就要盡量的做到數(shù)據(jù)庫(kù)隔離,雖 然不是真的隔離,但是要盡量在代碼上做隔離。

舉例,系統(tǒng)有一個(gè)file-server,是系統(tǒng)的公共服務(wù),附件的下載,上傳,獲取內(nèi)容等接口實(shí)現(xiàn)。對(duì)應(yīng)操作的表是系統(tǒng)附件表。

現(xiàn)在客戶的信息里有附,正常是在客戶與附件之間做連表查詢,將附件信息拿到,但是在微服務(wù)里這樣子做是不合規(guī)的?,F(xiàn)在如果進(jìn)行如下的引用

在controller類里定義的接口方法

//在controller類里定義的接口方法 ??
@RequestMapping(value = "/add" ,method = RequestMethod.GET)
public Integer add(@RequestParam Integer a, @RequestParam Integer b) {
?ServiceInstance instance = client.getLocalServiceInstance();
?Integer r = a + b;
?logger.info("/add, host:" + instance.getHost() + ", service_id:" + instance.getServiceId() + ", result:" + r);
?return r;
}

使用@FeignClient

@FeignClient("compute-service")
public interface ComputeClient {
? ? @RequestMapping(method = RequestMethod.GET, value = "/add")
? ? Integer add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b);
}

然后在另一個(gè)微服務(wù)里的controller層調(diào)用

@Autowired
ComputeClient computeClient;
@RequestMapping(value = "/add", method = RequestMethod.GET)
public Integer add() {
? ? return computeClient.add(10, 20);
}

只能說使用成功了,但是不規(guī)范,這是網(wǎng)上隨處可見的錯(cuò)誤規(guī)范,一開始我也是錯(cuò)誤的在controll層引用,但是被技術(shù)經(jīng)理叼了,反正就是不合規(guī)。

理由很簡(jiǎn)單,給前端的接口不要重復(fù)。如果你這邊controller調(diào)用原來的服務(wù),不管是哪個(gè)微服務(wù)的,前端是可以直接訪問的,那這樣子的意義何在。接口給你調(diào)用,是讓你用來獲取有用的信息來處理,然后返回給前端。

所以應(yīng)該在server層調(diào)用。

規(guī)范的使用@FignClient注解

以公共服務(wù)中的文件服務(wù)和客戶業(yè)務(wù)模塊進(jìn)行服務(wù)間的通信為例

在文件服務(wù)的api模塊里寫如下

FeignClient(contextId = "fileService", value = ServicellaneConstants.FTLE_SERNVTCE,fallbackFactory=RenoteFileFallbackFactory.class)
public interface RemoteFileservice {
/**
*上傳文件*
* aparam file 文件信息*areturn結(jié)果
*/
@PostMapping(value = "/upload",consumes = MediaType.WULTIPART_FORN_DATA_VALUE)
public RcLong uplocad(CRequestParan("module ) String nodole ,ORequestParan("sunceId ) String souneId, OlequestFart(value = "file ") liltigartFile file);

此時(shí)在客戶業(yè)務(wù)板塊,即客戶需要和附件進(jìn)行相關(guān)信息的1對(duì)多查詢,不能連表查詢,那就調(diào)用上面的RemoteFileservice ,一開始我在客戶模塊里寫了一個(gè)FileController,然后寫接口,接口里調(diào)用,直接NO。

應(yīng)該在業(yè)務(wù)層里調(diào)用就好了,用注解@Autowired,將你需要處理的數(shù)據(jù)獲取到并處理好。

接下來看看fallbackFactory,主要是為降級(jí)處理就是出錯(cuò)了應(yīng)該返回什么。

代碼僅供參考,可能還會(huì)有其它 的寫法

//注意FallbackFactory<你注解對(duì)應(yīng)的接口類名>
@component
public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileService>
private static final Logger log = LoggerFactory.getLogger(RemoteFileFallbackFactory.class);
0verride
public RemoteFileservice create(Throwable throwable){
//打印出錯(cuò)日志
log.error("文件朋務(wù)調(diào)用失敗:{}", throwable.getHessage());return new RemoteFileserviceo
{
Override
public R<Long> upload(String module,String sourceId,MultipartFile file){
return R.fail("上傳失敗:" + throwable.getMessage(o);
}
0verride
public byte[ ] getFileBytes(Long fileId) { return new byte[0];}
@0verride
public R getURL(Long[] ids) { return R.fail("獲取文件URL失敗:" + throwable.getHessage());}
@0verride
public R<List<SysFileApivo>> getURL(List<Long> ids) {
return R.fail("獲取文件URL失敗:" + throwable.getMessage());
}
};

想要怎么用,就動(dòng)手實(shí)踐吧

@FeignClient注解使用的常見問題

Feign 是一個(gè)聲明式的 Web 服務(wù),通過定義一個(gè)添加相應(yīng)注解的接口,即可完成一個(gè) Web 服務(wù)的接口。SpringCloud 對(duì) Feign 進(jìn)行了封裝以后,其開始能夠支持 Spring MVC 標(biāo)準(zhǔn)注解,同時(shí)在 SpringCloud 架構(gòu)上結(jié)合 Eureka 和 Ribbon,還能夠支持負(fù)載均衡。

既然是一個(gè) Web 服務(wù),必然服務(wù)端模塊與客戶端模塊都加入 Feign 依賴以及對(duì)接的 api 接口,這是 Feign 服務(wù)的基本前提。因此雙方引入的 Feign 接口都要保持一致,包括服務(wù)地址、入?yún)⒍x、返回值等。

基本配置

要啟用 @FeignClient 接口,首先需要引入 Feign 依賴:

<dependency>
? ? <groupId>org.springframework.cloud</groupId>
? ? <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在父 pom.xml 里還需要引入 SpringCloud 依賴,這樣使用 FeignClient 才有意義。

在啟動(dòng)類上添加啟動(dòng)注解 @EnableFeignClients:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
?
@SpringBootApplication
@EnableFeignClients
public class FeignDemoApp {
? ? public static void main(String[] args) {
? ? ? ? SpringApplication.run(FeignDemoApp.class, args);
? ? }
}

然后定義 Feign 客戶端提供的服務(wù)接口,示例代碼如下:

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
?
import com.demo.feign.model.request.FeignDemoDetailRequest;
import com.demo.feign.model.response.FeignDemoDetailResponse;
import com.demo.feign.model.response.FeignDemoListResponse;
@FeignClient("spring-boot-feign-demo")
public interface FeignDemoClient {
?
? ? @RequestMapping(value="/demo/list", method=RequestMethod.GET)
? ? public FeignDemoListResponse queryListByCode(@PathVariable("code") String code);
? ? ?
? ? @RequestMapping(value="/demo/detail", method=RequestMethod.POST)
? ? public FeignDemoDetailResponse queryDetail(@RequestBody FeignDemoDetailRequest request);
}

這里定義的 FeignDemoDetailRequest,F(xiàn)eignDemoDetailResponse 和 FeignDemoListResponse 是定義的實(shí)體類,具體就不展示了。

常見問題

Feign 的 maven 依賴報(bào)紅,或者主啟動(dòng)類上@EnableFeignClients不識(shí)別,一直報(bào)紅,或者 feign 接口注入到控制器報(bào)紅。

可能的原因及處理方案:

  • maven 包沒有成功導(dǎo)入,或者 maven 包下載不完整,可以從倉(cāng)庫(kù)刪掉依賴包后重新下載導(dǎo)入;
  • 版本沖突,或者無法獲取適當(dāng)版本,此時(shí)可以在 maven 包導(dǎo)入時(shí)指定版本號(hào),嘗試其他可用的版本。

項(xiàng)目 Application 啟動(dòng)時(shí),使用 @Autowired 自動(dòng)注入的 FeignClient 接口被告知對(duì)應(yīng)的 Bean 無法尋獲

***************************
APPLICATION FAILED TO START
***************************
 
Description:
Field feignDemoClient in com.xxx.xxx.service.impl.DemoServiceImpl required a bean of type 'com.xxx.xxx.feign.FeignDemoClient' that could not be found.
The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)
 
Action:
Consider defining a bean of type 'com.xxx.xxx.feign.FeignDemoClient' in your configuration.
Disconnected from the target VM, address: '127.0.0.1:51645', transport: 'socket'
Process finished with exit code 1

可能的原因及處理方案:

  • 服務(wù)所在模塊沒有在 pom.xml 引入 spring-cloud-starter-openfeign 這個(gè) maven 依賴,補(bǔ)上這個(gè)依賴重新構(gòu)建項(xiàng)目即可。
  • 項(xiàng)目啟動(dòng)沒有掃描 FeignClient 接口所在的包。項(xiàng)目通過啟動(dòng)類啟動(dòng)時(shí)默認(rèn)會(huì)掃描同目錄及同目錄下級(jí)目錄的類文件。所以,Spring注入第三方包或者其他模塊的包,需要掃描需要注入的包。這種情況,只需要在啟動(dòng)類的注解中指定需要掃描的包路徑即可,如:
// 開啟Feign客戶端,指定掃描 FeignClient 接口類所在的包
@EnableFeignClients("com.xxx.xxx.feign")
@SpringBootApplication

正確添加 Feign 依賴,啟動(dòng)類掃描 api 接口所有包路徑,但注入接口仍然報(bào)紅

這種情況現(xiàn)在比較少見,但是在一段時(shí)間以前出現(xiàn)比較頻繁,主要是在 SpringBoot 2.0 版本后優(yōu)化了相關(guān)邏輯。在 SpringBoot 2.0 之前,如果你的 Feign 接口使用 GetMapping 注解,那么注入該接口都會(huì)報(bào)紅,無法注入。相應(yīng)的,修改成 RequestMapping 或者 PostMapping 就能注入了。

處理方案:

1、采用合適的注解形式定義 Feign 接口。目前可行的定義方式基本有以下幾種:

@FeignClient("spring-boot-feign-demo")
public interface FeignDemoClient {
? ??
? ? // 使用RequestMapping指定Get方法,入?yún)蝹€(gè)傳入
? ? @RequestMapping(value="/demo/list", method=RequestMethod.GET)
? ? public FeignDemoListResponse queryListByCode(@PathVariable("code") String code);
? ? ?
? ? // 使用RequestMapping指定Post方法,傳入實(shí)體使用注解@RequestBody
? ? @RequestMapping(value="/demo/detail", method=RequestMethod.POST)
? ? public FeignDemoDetailResponse queryDetail(@RequestBody FeignDemoDetailRequest request);
? ??
? ? // 使用PostMapping,傳入實(shí)體使用注解@RequestBody
? ? @PostMapping("/demo/seq")
? ? public FeignDemoSeqResponse querySeq(@RequestBody FeignDemoSeqRequest request);
}

通過 FeignClient 發(fā)起 Get 請(qǐng)求報(bào) 405 錯(cuò)誤

通過在服務(wù)端斷點(diǎn)捕獲異??梢园l(fā)現(xiàn),報(bào) 405 錯(cuò)誤的直接原因,其實(shí)是因?yàn)槎x為 Get 的 Feign 接口,接收到 Post 方法的調(diào)用。但是在調(diào)用方調(diào)用時(shí)大多數(shù)也是采用 Get 方法,那么到底是什么原因呢?

暫且預(yù)設(shè) Feign 接口的定義如下:

@FeignClient("spring-boot-feign-demo")
public interface FeignDemoClient {
? ? // 服務(wù)方接收到的請(qǐng)求是Post方法,而不是Get方法
? ? @GetMapping(value="/demo/list")
? ? public Response queryList(Request request);

實(shí)際上,通過斷點(diǎn)跟蹤接口調(diào)用時(shí)的調(diào)用路徑,就會(huì)發(fā)現(xiàn) FeignClient 最后是通過 HttpURLConnection 發(fā)起的網(wǎng)絡(luò)連接,在發(fā)起的過程中,Connection 會(huì)判斷自身請(qǐng)求的 body 是否為空。如果 body 不為空,則將 Get 方法轉(zhuǎn)換成 Post 方法。因?yàn)?body 形式的數(shù)據(jù)只能方法 RequestBody 內(nèi)以流的形式進(jìn)行傳輸,而根據(jù) Http 協(xié)議 param 形式的數(shù)據(jù)可以直接放在 URL 上進(jìn)行傳輸和獲取。

之所以 FeignClient 在網(wǎng)絡(luò)請(qǐng)求時(shí)會(huì)出現(xiàn)這種轉(zhuǎn)換,這跟它的初始化規(guī)則有關(guān)。在項(xiàng)目啟動(dòng)過程中,@FeignClient 直接的類會(huì)被初始化一個(gè)動(dòng)態(tài)代理的類,并通過一個(gè) RequestTemplate.Factory 的工廠類生成請(qǐng)求模板,具體規(guī)則如下:

  • 如果基本類型參數(shù)有 @RequestParam 注解,則會(huì)將參數(shù)作為 key 放入 RequestTemplate.Factory 中,通過 urlIndex 記錄數(shù)組索引。在進(jìn)行解析時(shí),通過 key 從數(shù)組中獲取具體的參數(shù)值,拼接在 url 后面。
  • 如果參數(shù)沒有任何注解,或者有 @RequestBody 注解,那么初始化時(shí)會(huì)使用 bodyIndex 維護(hù)參數(shù)索引,并通過 bodyType 記錄參數(shù)的具體類型。

需要注意的是,@RequestParam 只能用于對(duì)單個(gè)基本類型參數(shù)的注解,不能用來注解一個(gè)實(shí)體類。使用實(shí)體類作為入?yún)⒊鰠r(shí),建議還是使用 Post 方法進(jìn)行請(qǐng)求。

如果在開發(fā)中覺得維護(hù)以上的對(duì)應(yīng)關(guān)系不方便的話,還有另外一種修改方法可供使用,基本原理就是使用 Apache 的 HTTP Client 替換 Feign 原生的 Http Client,替換后 Get 方法也可以用一個(gè)實(shí)體類作為請(qǐng)求參數(shù)而不用擔(dān)心請(qǐng)求被轉(zhuǎn)換成 Post 方法了。具體修改方式如下:

引入 http client 依賴

<dependency>
? ? <groupId>org.apache.httpcomponents</groupId>
? ? <artifactId>httpclient</artifactId><br> ? ?
? ? <version>4.5.2</version>
</dependency>
<dependency>
? ? <groupId>com.netflix.feign</groupId>
? ? <artifactId>feign-httpclient</artifactId>
? ? <version>8.18.0</version>
</dependency>

開啟 Feign 對(duì) httpClient 的設(shè)置

feign.httpclient.enabled=true

完成配置修改后,內(nèi)部就可以使用 Apache 的 http client。Feign 接口的定義是相同的,但是由于 Get 方法支持了自定義實(shí)體類,與 Post 有類似的處理方式,因此參數(shù)的傳輸需要我們額外指定其類型,以確保 JSON 序列化與反序列化的正常進(jìn)行。

這里給出一個(gè)示例接口定義:

@FeignClient("spring-boot-feign-demo")
public interface FeignDemoClient {
? ? @PostMapping(value="/demo/detail", consumes = MediaType.APPLICATION_JSON_VALUE)
? ? public Response<List<ResultDTO>> query(@RequestBody FeignQueryRequest request,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@PathVariable("page") Integer page,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@PathVariable("page_size") Integer pageSize);
}

JSON 反序列化失敗

Error while extracting response for type [com.xxx.xxx.feign] and content type [application/json].Can not deserialize instance of java.util.ArrayList out of START_OBJECT token

翻譯過來的意思大致就是,F(xiàn)eign 接口的返回值無法通過 application/json 的格式解析出來,也就是調(diào)用方返回值的定義就服務(wù)方不一致(結(jié)構(gòu)不同)。

處理方案:

確保雙方引入的接口 api 完全一致,可通過將接口所在模塊打包成 jar 包,雙方引用同一個(gè) jar 等方式以保證接口定義一致。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 修改idea的這些啟動(dòng)參數(shù),令你的idea健步如飛

    修改idea的這些啟動(dòng)參數(shù),令你的idea健步如飛

    這篇文章主要介紹了修改idea的這些啟動(dòng)參數(shù),令你的idea健步如飛~具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • idea maven pom不自動(dòng)更新的解決方法

    idea maven pom不自動(dòng)更新的解決方法

    這篇文章主要介紹了idea maven pom不自動(dòng)更新的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java mockito單元測(cè)試實(shí)現(xiàn)過程解析

    Java mockito單元測(cè)試實(shí)現(xiàn)過程解析

    這篇文章主要介紹了Java mockito單元測(cè)試實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java原生操作JDBC連接以及原理詳解

    Java原生操作JDBC連接以及原理詳解

    這篇文章主要給大家介紹了關(guān)于Java原生操作JDBC連接以及原理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • java中的自增問題介紹

    java中的自增問題介紹

    下面小編就為大家?guī)硪黄猨ava中的自增問題介紹。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家。給大家一個(gè)參考。
    2016-03-03
  • Java的NIO之并發(fā)環(huán)境下非阻塞IO技術(shù)詳解

    Java的NIO之并發(fā)環(huán)境下非阻塞IO技術(shù)詳解

    這篇文章主要介紹了Java的NIO之并發(fā)環(huán)境下非阻塞IO技術(shù)詳解,Java NIO(New IO)是Java平臺(tái)提供的一種用于高效處理I/O操作的API,它引入了一組新的類和概念,以提供更好的性能和可擴(kuò)展性,需要的朋友可以參考下
    2023-09-09
  • Java實(shí)現(xiàn)租車管理系統(tǒng)

    Java實(shí)現(xiàn)租車管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)租車管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • Spring MVC接受表單自動(dòng)封裝特性實(shí)例解析

    Spring MVC接受表單自動(dòng)封裝特性實(shí)例解析

    這篇文章主要介紹了Spring MVC接受表單自動(dòng)封裝特性實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • SpringBoot通過tractId操作日志鏈路跟蹤

    SpringBoot通過tractId操作日志鏈路跟蹤

    這篇文章給大家介紹SpringBoot通過tractId操作日志鏈路跟蹤,通過tractId,即可完成對(duì)從一個(gè)請(qǐng)求進(jìn)入系統(tǒng)到請(qǐng)求結(jié)束的日志追蹤,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-10-10
  • java中spi使用詳解

    java中spi使用詳解

    java中spi(service provider interface)是jdk內(nèi)置的一種服務(wù)發(fā)現(xiàn)機(jī)制,可以基于配置,在運(yùn)行時(shí)加載指定服務(wù)。這篇文章主要介紹了java中spi使用,需要的朋友可以參考下
    2020-09-09

最新評(píng)論