Spring Cloud 學習(6) ---Feign(一) 遠程調(diào)用、RestTemplate、Feign

在使用 SpringCloud 時短蜕,遠程服務都是以 HTTP 接口形式對外提供服務氢架,因此服務消費者在調(diào)用服務時,需要使用 HTTP Client 方式訪問朋魔。在通常進行遠程 HTTP 調(diào)用時岖研,可以使用 RestTemplate、HttpClient警检、URLConnection孙援、OkHttp 等,也可以使用 SpringCloud Feign 進行遠程調(diào)用

RestTemplate

源碼:https://gitee.com/laiyy0728/spring-cloud/tree/master/spring-cloud-feign/spring-cloud-feign-simple

脫離 Eureka 的使用

在脫離 Eureka 使用 RestTemplate 調(diào)用遠程接口時扇雕,只需要引入 web 依賴即可拓售。

在使用 RestTemplate 時,需要先將 RestTemplate 交給 Spring 管理

@Configuration
public class RestTemplateConfiguration {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

編寫一個 Controller镶奉,注入 RestTemplate础淤,調(diào)用遠程接口

@RestController
public class RestTemplateController {

    private final RestTemplate restTemplate;

    @Autowired
    public RestTemplateController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @GetMapping(value = "rest-get", produces = "text/html;charset=utf-8")
    public String restTemplateGet(){
        return restTemplate.getForObject("https://gitee.com", String.class);
    }

}

訪問 http://localhost:8080/rest-get

RestTemplate Simple

關聯(lián) Eureka 使用

將服務注冊到 Eureka Server,并使用 RestTemplate 調(diào)用遠程 Eureka Client 服務

此時哨苛,只需要按照一個標準的 Eureka Client 編寫步驟鸽凶,將項目改造成一個 Eureka Client,并編寫另外一個 Client建峭。將要使用 RestTemplate 的 Client 當做服務消費者玻侥,另外一個當做服務提供者。在進行遠程調(diào)用時迹缀,只需要將 getForObject 的 url使碾,改為 http://service-id 即可,具體傳入?yún)?shù)使用 ?祝懂、&= 拼接即可拘鞋。

在注冊到 Eureka Server 后砚蓬,進行 RestTemplate 遠程調(diào)用時,service-id 會被 Eureka Client 解析為 Server 中注冊的 ip盆色、端口灰蛙,以此進行遠程調(diào)用。

Rest Template

RestTemplate 提供了 11 個獨立的方法隔躲,這 11 個方法對應了各種遠程調(diào)用請求

方法名 http 動作 說明
getForEntity() GET 發(fā)送 GET 請求摩梧,返回的 ResponseEntity 包含了響應體所映射成的對象
getForObject() GET 發(fā)送 GET 請求,返回的請求體將映射為一個對象
postForEntity() POST 發(fā)送 POST 請求宣旱,返回包含一個對象的 ResponseEntity仅父,這個對象是從響應體中映射得到的
postForObject() POST 發(fā)送 POST 請求,返回根據(jù)響應體匹配形成的對象
postForLocation() POST 發(fā)送 POST 請求,返回新創(chuàng)建資源的 URL
put() PUT PUT 資源到指定 URL
delete() DELETE 發(fā)送 DELETE 請求笙纤,執(zhí)行刪除操作
headForHeaders() HEAD 發(fā)送 HEAD 請求耗溜,返回包含指定資源 URL 的 HTTP 頭
optionsFOrAllow() OPTIONS 發(fā)送 OPTIONS 請求,返回指定 URL 的 Allow 頭信息
execute() 執(zhí)行非響應 ResponseEntity 的請求
exchange() 執(zhí)行響應 ResponseEntity 的請求

Feign

使用 RestTemplate 進行遠程調(diào)用省容,非常方便抖拴,但是也有一個致命的問題:硬編碼。 在 RestTemplate 調(diào)用中腥椒,我們每個調(diào)用遠程接口的方法阿宅,都將遠程接口對應的 ip、端口笼蛛,或 service-id 硬編碼到了 URL 中家夺,如果遠程接口的 ip、端口伐弹、service-id 有修改的話拉馋,需要將所有的調(diào)用都修改一遍,這樣難免會出現(xiàn)漏改惨好、錯改等問題煌茴,且代碼不便于維護。為了解決這個問題日川,Netflix 推出了 Feign 來統(tǒng)一管理遠程調(diào)用蔓腐。

什么是 Feign

Feign 是一個聲明式的 Web Service 客戶端,只需要創(chuàng)建一個接口龄句,并加上對應的 Feign Client 注解回论,即可進行遠程調(diào)用。Feign 也支持編碼器分歇、解碼器傀蓉,Spring Cloud Open Feign 也對 Feign 進行了增強,支持了 SpringMVC 注解职抡,可以像 SpringMVC 一樣進行遠程調(diào)用葬燎。

Feign 是一種聲明式、模版化的 HTTP 客戶端缚甩,在 Spring Cloud 中使用 Feign谱净,可以做到使用 HTTP 請求訪問遠程方法就像調(diào)用本地方法一樣簡單,開發(fā)者完全感知不到是在進行遠程調(diào)用擅威。

Feign 的特性:

  • 可插拔的注解支持
  • 可插拔的 HTTP 編碼器壕探、解碼器
  • 支持 Hystrix 斷路器、Fallback
  • 支持 Ribbon 負載均衡
  • 支持 HTTP 請求郊丛、響應壓縮

簡單示例

源碼:https://gitee.com/laiyy0728/spring-cloud/tree/master/spring-cloud-feign/spring-cloud-feign-simple

使用 Feign 進行 github 接口調(diào)用

pom 依賴

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

配置文件

只是進行一個簡單的遠程調(diào)用李请,不需要注冊 Eureka瞧筛、不需要配置文件。

啟動類

@SpringBootApplication
@EnableFeignClients
public class SpringCloudFeignSimpleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudFeignSimpleApplication.class, args);
    }

}

Feign Client 配置

@Configuration
public class GiteeFeignConfiguration {
    
     /**
     * 配置 Feign 日志級別
     * <p>
     * NONE:沒有日志
     * BASIC:基本日志
     * HEADERS:header
     * FULL:全部
     * <p>
     * 配置為打印全部日志捻艳,可以更方便的查看 Feign 的調(diào)用信息
     *
     * @return Feign 日志級別
     */
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
    
}

FeignClient

@FeignClient(name = "gitee-client", url = "https://www.gitee.com/", configuration = GiteeFeignConfiguration.class)
public interface GiteeFeignClient {

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    String searchRepo(@RequestParam("q") String query);

}

@FeignClient:聲明為一個 Feign 遠程調(diào)用
name:給遠程調(diào)用起個名字
url:指定要調(diào)用哪個 url
configuration:指定配置信息

@RequestMapping:如同 SpringMVC 一樣調(diào)用驾窟。

Feign Controller

@RestController
public class FeignController {

    private final GiteeFeignClient giteeFeignClient;

    @Autowired
    public FeignController(GiteeFeignClient giteeFeignClient) {
        this.giteeFeignClient = giteeFeignClient;
    }

    @GetMapping(value = "feign-gitee")
    public String feign(String query){
        return giteeFeignClient.searchRepo(query);
    }

}

驗證調(diào)用結果

在瀏覽器中訪問: http://localhost:8080/feign-gitee?query=spring-cloud-openfeign

Feign To Gitee

@FeignClient、@RequestMapping

在 Feign 中使用 MVC 注解的注意事項

在 FeignClient 中使用 @RequestMapping 注解調(diào)用遠程接口认轨,需要注意:

  • 注解必須為 @RequestMapping绅络,不能為組合注解 @GetMapping 等,否則解析不到
  • 必須指定 method嘁字,否則會出問題
  • value 必須指定被調(diào)用方的 url恩急,不能包含域名、ip 等

使用 @FeignClient 的注意事項

  • 在啟動類上必須加上 @FeignClients 注解纪蜒,開啟掃描
  • 在 FeignClient 接口上必須指定 @FeignClient 注解衷恭,聲明是一個 Feign 遠程調(diào)用

@FeignClient

源碼

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient {
    @AliasFor("name")
    String value() default "";

    /** @deprecated */
    @Deprecated
    String serviceId() default "";

    @AliasFor("value")
    String name() default "";

    String qualifier() default "";

    String url() default "";

    boolean decode404() default false;

    Class<?>[] configuration() default {};

    Class<?> fallback() default void.class;

    Class<?> fallbackFactory() default void.class;

    String path() default "";

    boolean primary() default true;
}
字段名 含義
name 指定 FeignClient 的名稱,如果使用到了 Eureka纯续,且使用了 Ribbon 負載均衡随珠,則 name 為被調(diào)用者的微服務名稱,用于服務發(fā)現(xiàn)
url 一般用于調(diào)試猬错,可以手動指定 feign 調(diào)用的地址
decode404 當 404 時窗看,如果該字段為 true,會調(diào)用 decoder 進行解碼倦炒,否則會拋出 FeignException
configuration Feign 配置類显沈,可以自定義 Feign 的 Encoder、Decoder逢唤、LogLevel拉讯、Contract 等
fallback 容錯處理類,當遠程調(diào)用失敗鳖藕、超時時魔慷,會調(diào)用對應接口的容錯邏輯。Fallback 指定的類吊奢,必須實現(xiàn) @FeignClient 標記的接口
fallbackFactory 工廠類盖彭,用于生成 fallback 類的示例,可以實現(xiàn)每個接口通用的容錯邏輯页滚,減少重復代碼
path 定義當前 FeignClient 的統(tǒng)一前綴

Feign 的運行原理

  • 在啟動類上加上 @EnableFeignClients 注解,開啟對 Feign Client 掃描加載
  • 在啟用時铺呵,會進行包掃描裹驰,掃描所有的 @FeignClient 的注解的類,并將這些信息注入 Spring IOC 容器片挂,當定義的 Feign 接口中的方法被調(diào)用時幻林,通過 JDK 的代理方式贞盯,來生成具體的 RestTemplate。當生成代理時沪饺,F(xiàn)eign 會為每個接口方法創(chuàng)建一個 RestTemplate 對象躏敢,該對象封裝了 HTTP 請求需要的全部信息,如:參數(shù)名整葡、請求方法件余、header等
  • 然后由 RestTemplate 生成 Request,然后把 Request 交給 Client 處理遭居,這里指的 Client 可以是 JDK 原生的 URLConnection啼器、Apache 的 HTTP ClientOkHttp俱萍。最后 Client 被封裝到 LoadBalanceClient 類端壳,結合 Ribbon 負載均衡發(fā)起服務間的調(diào)用。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枪蘑,一起剝皮案震驚了整個濱河市损谦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌岳颇,老刑警劉巖照捡,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赦役,居然都是意外死亡麻敌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門掂摔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來术羔,“玉大人,你說我怎么就攤上這事乙漓〖独” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵叭披,是天一觀的道長寥殖。 經(jīng)常有香客問我,道長涩蜘,這世上最難降的妖魔是什么嚼贡? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮同诫,結果婚禮上粤策,老公的妹妹穿的比我還像新娘。我一直安慰自己误窖,他們只是感情好叮盘,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布秩贰。 她就那樣靜靜地躺著,像睡著了一般柔吼。 火紅的嫁衣襯著肌膚如雪毒费。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天愈魏,我揣著相機與錄音觅玻,去河邊找鬼。 笑死蝌戒,一個胖子當著我的面吹牛串塑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播北苟,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼桩匪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了友鼻?” 一聲冷哼從身側響起傻昙,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎彩扔,沒想到半個月后妆档,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡虫碉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年贾惦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敦捧。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡须板,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兢卵,到底是詐尸還是另有隱情习瑰,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布秽荤,位于F島的核電站甜奄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏窃款。R本人自食惡果不足惜课兄,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晨继。 院中可真熱鬧第喳,春花似錦、人聲如沸踱稍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽珠月。三九已至扩淀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間啤挎,已是汗流浹背驻谆。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留庆聘,地道東北人胜臊。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像伙判,于是被迫代替她去往敵國和親象对。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359