使用Spring Cloud Feign作為HTTP客戶端調(diào)用遠(yuǎn)程HTTP服務(wù)的方法(推薦)
在Spring Cloud Netflix棧中,各個微服務(wù)都是以HTTP接口的形式暴露自身服務(wù)的,因此在調(diào)用遠(yuǎn)程服務(wù)時就必須使用HTTP客戶端。我們可以使用JDK原生的URLConnection、Apache的Http Client、Netty的異步HTTP Client, Spring的RestTemplate。但是,用起來最方便、最優(yōu)雅的還是要屬Feign了。
Feign簡介
Feign是一種聲明式、模板化的HTTP客戶端。在Spring Cloud中使用Feign, 我們可以做到使用HTTP請求遠(yuǎn)程服務(wù)時能與調(diào)用本地方法一樣的編碼體驗(yàn),開發(fā)者完全感知不到這是遠(yuǎn)程方法,更感知不到這是個HTTP請求。比如:
@Autowired private AdvertGropRemoteService service; // 遠(yuǎn)程服務(wù) public AdvertGroupVO foo(Integer groupId) { return service.findByGroupId(groupId); // 通過HTTP調(diào)用遠(yuǎn)程服務(wù) }
開發(fā)者通過service.findByGroupId()
就能完成發(fā)送HTTP請求和解碼HTTP返回結(jié)果并封裝成對象的過程。
Feign的定義
為了讓Feign知道在調(diào)用方法時應(yīng)該向哪個地址發(fā)請求以及請求需要帶哪些參數(shù),我們需要定義一個接口:
@FeignClient(name = "ea") // [A] public interface AdvertGroupRemoteService { @RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) // [B] AdvertGroupVO findByGroupId(@PathVariable("groupId") Integer adGroupId) // [C] @RequestMapping(value = "/group/{groupId}", method = RequestMethod.PUT) void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName)
A: @FeignClient用于通知Feign組件對該接口進(jìn)行代理(不需要編寫接口實(shí)現(xiàn)),使用者可直接通過@Autowired注入。
B: @RequestMapping表示在調(diào)用該方法時需要向/group/{groupId}
發(fā)送GET請求。
C: @PathVariable與SpringMVC中對應(yīng)注解含義相同。
Spring Cloud應(yīng)用在啟動時,F(xiàn)eign會掃描標(biāo)有@FeignClient注解的接口,生成代理,并注冊到Spring容器中。生成代理時Feign會為每個接口方法創(chuàng)建一個RequetTemplate對象,該對象封裝了HTTP請求需要的全部信息,請求參數(shù)名、請求方法等信息都是在這個過程中確定的,F(xiàn)eign的模板化就體現(xiàn)在這里。
在本例中,我們將Feign與Eureka和Ribbon組合使用,@FeignClient(name = "ea")
意為通知Feign在調(diào)用該接口方法時要向Eureka中查詢名為ea的服務(wù),從而得到服務(wù)URL。
Feign的Encoder、Decoder和ErrorDecoder
Feign將方法簽名中方法參數(shù)對象序列化為請求參數(shù)放到HTTP請求中的過程,是由編碼器(Encoder)完成的。同理,將HTTP響應(yīng)數(shù)據(jù)反序列化為java對象是由解碼器(Decoder)完成的。
默認(rèn)情況下,F(xiàn)eign會將標(biāo)有@RequestParam注解的參數(shù)轉(zhuǎn)換成字符串添加到URL中,將沒有注解的參數(shù)通過Jackson轉(zhuǎn)換成json放到請求體中。注意,如果在@RequetMapping中的method將請求方式指定為POST,那么所有未標(biāo)注解的參數(shù)將會被忽略,例如:
@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName, DataObject obj);
此時因?yàn)槁暶鞯氖荊ET請求沒有請求體,所以obj參數(shù)就會被忽略。
在Spring Cloud環(huán)境下,F(xiàn)eign的Encoder*只會用來編碼沒有添加注解的參數(shù)*。如果你自定義了Encoder, 那么只有在編碼obj參數(shù)時才會調(diào)用你的Encoder。對于Decoder, 默認(rèn)會委托給SpringMVC中的MappingJackson2HttpMessageConverter類進(jìn)行解碼。只有當(dāng)狀態(tài)碼不在200 ~ 300之間時ErrorDecoder才會被調(diào)用。ErrorDecoder的作用是可以根據(jù)HTTP響應(yīng)信息返回一個異常,該異??梢栽谡{(diào)用Feign接口的地方被捕獲到。我們目前就通過ErrorDecoder來使Feign接口拋出業(yè)務(wù)異常以供調(diào)用者處理。
Feign的HTTP Client
Feign在默認(rèn)情況下使用的是JDK原生的URLConnection發(fā)送HTTP請求,沒有連接池,但是對每個地址會保持一個長連接,即利用HTTP的persistence connection 。我們可以用Apache的HTTP Client替換Feign原始的http client, 從而獲取連接池、超時時間等與性能息息相關(guān)的控制能力。Spring Cloud從Brixtion.SR5版本開始支持這種替換,首先在項(xiàng)目中聲明Apache HTTP Client和feign-httpclient
依賴:
<!-- 使用Apache HttpClient替換Feign原生httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-httpclient</artifactId> <version>${feign-httpclient}</version> </dependency>
然后在application.properties中添加:
feign.httpclient.enabled=true
總結(jié)
通過Feign, 我們能把HTTP遠(yuǎn)程調(diào)用對開發(fā)者完全透明,得到與調(diào)用本地方法一致的編碼體驗(yàn)。這一點(diǎn)與阿里Dubbo中暴露遠(yuǎn)程服務(wù)的方式類似,區(qū)別在于Dubbo是基于私有二進(jìn)制協(xié)議,而Feign本質(zhì)上還是個HTTP客戶端。如果是在用Spring Cloud Netflix搭建微服務(wù),那么Feign無疑是最佳選擇。
以上所述是小編給大家介紹的使用Spring Cloud Feign作為HTTP客戶端調(diào)用遠(yuǎn)程HTTP服務(wù)的方法(推薦),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
IntelliJ IDEA2019 安裝lombok的實(shí)現(xiàn)
這篇文章主要介紹了IntelliJ IDEA2019 安裝lombok的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Mybatis Limit實(shí)現(xiàn)分頁功能
這篇文章主要介紹了Mybatis Limit實(shí)現(xiàn)分頁功能,使用Limit實(shí)現(xiàn)分頁可以減少數(shù)據(jù)的處理量,本文通過代碼講解的非常詳細(xì),需要的朋友可以參考下2021-04-04詳解Java從后臺重定向(redirect)到另一個項(xiàng)目的方法
這篇文章主要介紹了詳解Java從后臺重定向(redirect)到另一個項(xiàng)目的方法,非常具有實(shí)用價值,需要的朋友可以參考下2017-04-04spring?boot自動裝配之@ComponentScan注解用法詳解
@ComponentScan的作用就是根據(jù)定義的掃描路徑,把符合掃描規(guī)則的類裝配到spring容器中,下面這篇文章主要給大家介紹了關(guān)于spring?boot自動裝配之@ComponentScan注解用法的相關(guān)資料,需要的朋友可以參考下2023-04-04