# :-: 聲明式服務調用 Feign
## 前言
* 在以往的單工程項目,所有代碼都融合在一起,業務相互調用只需要引入共有的工具類或者對應模塊的service。
* 但是到了微服務時代,已然不能使用這種方式,我們需要尋找新的解決方案。
* 若每個模塊都把需要調用模塊的service拷貝一份,那會令代碼非常冗余,影響整個工程的健壯性。
* 稍大一些的系統,會分成多個庫,比如用戶庫、訂單庫分開,訂單服務想要取到用戶的相關信息,由于不能連接到用戶的庫,所以無法直接新建數據庫查詢以達到目的。
* 這個時候,遠程調用方案出現,訂單服務只需調用用戶服務的API,就可以獲取所需信息,非常方便。
* 我們下面來學習,如何使用SpringCloud的Feign來進行微服務遠程調用。
## Feign簡介
Feign是一種聲明式、模板化的HTTP客戶端。在Spring Cloud中使用Feign, 我們可以做到使用HTTP請求遠程服務時能與調用本地方法一樣的編碼體驗,開發者完全感知不到這是遠程方法,更感知不到這是個HTTP請求。
## 代碼示例
1. 我們以`applets-demo`中的服務為例,讓我們的`applets-desk`可以調用到`applets-demo`的API
2. 在`applets-demo-api`工程中創建一個新的`package`,`feign`

3. 在`package`,`feign`下創建一個接口類,命名為`BlogClient`
4. 增加如下代碼
~~~
package org.springblade.demo.feign;
import com.applets.common.constant.CommonConstant;
import com.applets.core.tool.api.R;
import com.applets.demo.entity.Blog;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(
//定義Feign指向的service-id
value = CommonConstant.APPLICATION_DEMO_NAME
)
public interface BlogClient{
/**
* 接口前綴
*/
String API_PREFIX = "/api/blog";
/**
* 獲取詳情
*
* @param id 主鍵
* @return
*/
@GetMapping(API_PREFIX + "/detail")
R<Blog> detail(@RequestParam("id") Integer id);
}
~~~
5. 返回`blade-demo`,增加feign的實現類`BlogClientImpl`

6. 增加代碼如下,因為Feign本質上是HTTP客戶端,所以我們創建的`BlogClientImpl`其實就是`SpringMVC`的`Controller`,所以需要加上`@RestController`注解。
~~~
package com.applets.demo.feign;
import lombok.AllArgsConstructor;
import com.applets.core.tool.api.R;
import com.applets.demo.entity.Blog;
import com.applets.demo.service.BlogService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@AllArgsConstructor
public class BlogClientImpl implements BlogClient {
private BlogService service;
@Override
@GetMapping(API_PREFIX + "/detail")
public R<Blog> detail(Integer id) {
return R.data(service.getById(id));
}
}
~~~
7. 在`applets-desk`模塊的`pom.xml`文件引入`applets-demo`的API包

8. 找到`DashboardController`,新增如下代碼
~~~
private BlogClient client;
@GetMapping("/blog-detail")
public R<Blog> blogDetail(Integer id) {
R<Blog> result = client.detail(id);
return result;
}
~~~
9. 啟動`applets-desk`并使用Postman調用查看API遠程調用成功
10. 我們再來看下控制臺日志,請求先到了`/dashboard/blog-detail`,由于調用了`Feign`,程序又根據`Feign`的配置去查找名為`applets-demo`的服務,并調用對應方法,最后返回了所需數據,整個流程非常清晰
## 后話
* Feign調用我們已經走通,但是真實環境問題會很多,經常會有服務調用失敗的情況。
* 應對這種場景,我們有沒有什么好的解決方案?
* 下面我們來學習下`Hystrix 熔斷機制`
- 序
- 快速開始
- 環境要求
- 環境準備
- 工程導入
- 工程運行
- 技術基礎
- Java8
- Lambda
- Lambda 受檢異常處理
- Stream 簡介
- Stream API 一覽
- Stream API(上)
- Stream API(下)
- Optional 干掉空指針
- 函數式接口
- 新的日期 API
- Lombok
- SpringMVC
- Swagger
- Mybaties
- Mybaties-plus
- 開發初探
- 新建微服務工程
- 第一個API
- API鑒權
- API響應結果
- Redis 緩存
- 第一個CRUD
- 建表
- 建Entity
- 建Service和Mapper
- 新增API
- 修改API
- 刪除API
- 查詢API
- 單條查詢
- 多條查詢
- 分頁
- 微服務遠程調用
- 聲明式服務調用Feign
- 熔斷機制 Hystrix
- 開發進階