[TOC]
*****
# 1. 使用Feign實現遠程HTTP調用
```
fegin的github地址: https://github.com/openfeign/feign
Feign是一個聲明式WebService客戶端.使用Feign能讓編寫WebService客戶端更加簡單,它的使用方法是定義一個接口,然后在上面添加注解,同時也支持JAX-RS標準的注解.
Feign也支持可拔插式的編碼器和解碼器.Spring Cloud對Feign進行了封裝,使其支持了Spring MVC標準注解和HttpMessageConverters.
Feign可以與nacos/Eureka和Ribbon組合使用以支持負載均衡.
解決的問題:
1. 代碼不可讀
2. 復雜的url難以維護
3. 難以相應需求的變化
4. 編程體驗不統一
```
# 2. fegin的使用
```
1. 加依賴
compile("org.springframework.cloud:spring-cloud-starter-openfeign")
2. 在啟動類或者配置類上加注解 @EnableFeignClients
3. 寫配置 使用默認配置
```
```
/**
* name: 請求服務的名稱
*/
@FeignClient(name = "ali-pay-service")
public interface UserCenterFeginClient {
/**
* http://ali-pay-service/users/{id}
* @param id
* @return
*/
@GetMapping("/users/{id}")
String findById(@PathVariable Integer id);
}
```
# 3. Feign的組成

# 4. 細粒度配置自定義
```
4-1. 細粒度配置自定義-Java代碼方式-指定日志級別
場景: 通過feign請求服務時,打印請求信息的日志
```
**4-1. Feign的日志級別:**

**4-2. 代碼方式配置日志級別:**
```
/**
* name: 請求服務的名稱
*/
@FeignClient(name = "ali-pay-service", configuration = UserCenterFeignConfiguration.class)
public interface UserCenterFeginClient {
/**
* http://ali-pay-service/users/{id}
* @param id
* @return
*/
@GetMapping("/users/{id}")
String findById(@PathVariable Integer id);
}
```
```
/**
* 自定義日志級別
* 若改類上面有@Configuration注解,就要把它放在啟動類之外的包內
* 原因:父子上下文的關系,會被@ComponentScan掃描到用在所有的feignClient上
* 出現一些奇怪的問題,所以建議不要加@Configuration注解
*/
public class UserCenterFeignConfiguration {
@Bean
public Logger.Level level() {
//讓feign打印所有請求的細節
return Logger.Level.FULL;
}
}
```
```
logging:
level:
# 自定義feign的日志級別是建立在debug基礎上的,若為其他如info,則不會打印任何日志
com.example.feginclient.UserCenterFeginClient: debug
```
**4-3. 配置屬性方式-指定日志級別:**
```
feign:
client:
config:
#想要調用的微服務名稱
ali-pay-service:
loggerLevel: full
```
**4-4. 全局配置-01-Java代碼方式-指定日志級別**
```
@EnableFeignClients(defaultConfiguration = UserCenterFeignConfiguration.class)
```
**4-5. 全局配置-02-配置屬性方式-指定日志級別**
```
feign:
client:
config:
#全局配置
default:
loggerLevel: full
```
**4-6. 支持的配置項**
```
1. 代碼方式支持的配置項
```

```
2. 屬性方式支持的配置項
```

**4-7. 日志級別配置最佳實踐總結**

# 5. 多參數請求構造
```
1. GET方法
/**
* name: 請求服務的名稱
*/
@FeignClient(name = "ali-pay-service", configuration = UserCenterFeignConfiguration.class)
public interface UserCenterFeginClient {
@GetMapping("/query")
public User get0(@SpringQueryMap User user);
}
此時會報405的錯誤,status 405 reading UserFeignClient#get0(User); content:
{"timestamp":1482676142940,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/get"}
由異常可知,盡管我們指定了GET方法,Feign依然會使用POST方法發送請求.于是導致了異常. 正確寫法如下:
方法一[推薦]
@FeignClient("ali-pay-service")
public interface UserFeignClient {
@GetMapping("/get")
public User get0(@SpringQueryMap User user);
}
方法二[推薦]
@FeignClient(name = "ali-pay-service")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get1(@RequestParam("id") Long id, @RequestParam("username") String username);
}
這是最為直觀的方式,URL有幾個參數,Feign接口中的方法就有幾個參數。使用@RequestParam注解指定請求的參數是什么.
方法三[不推薦]
多參數的URL也可使用Map來構建。當目標URL參數非常多的時候,可使用這種方式簡化Feign接口的編寫。
@FeignClient(name = "ali-pay-service")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get2(@RequestParam Map<String, Object> map);
}
在調用時,可使用類似以下的代碼。
public User get(String username, String password) {
HashMap<String, Object> map = Maps.newHashMap();
map.put("id", "1");
map.put("username", "張三");
return this.userFeignClient.get2(map);
}
注意:這種方式不建議使用。主要是因為可讀性不好,而且如果參數為空的時候會有一些問題,例如map.put("username", null);
會導致"ali-pay-service 服務接收到的username是 "" ,而不是null.
```
```
2. post方法
@FeignClient(name = "ali-pay-service")
public interface UserFeignClient {
@RequestMapping(value = "/post", method = RequestMethod.POST)
public User post(@RequestBody User user);
}
```
# 6. Feign脫離Ribbon使用
```
場景: 用feign調用的服務沒有注冊到nacos / eureka上,怎么實現?
```
```
/**
* name: 可以隨便寫,但必須有
*/
@FeignClient(name = "baidu", url = "http://www.baidu.com")
public interface TestBaiduFeignClient {
@GetMapping("")
String index();
}
```
# 7. RestTemplate 對比 Feign

# 8. Feign性能優化
```
1. 為feign配置連接池[提升15%左右] 以apache的httpClient為例(okhttp同理,需要自己指定版本)
第一步: 加依賴: compile ("io.github.openfeign:feign-httpclient")
第二步: 寫配置
feign:
httpclient:
#讓feign使用apache httpclient做請求,而不是默認的urlConnection
enabled: true
#feign的最大連接數
max-connections: 200
#feign單個路徑的最大連接數
max-connections-per-route: 50
```
```
2. 日志級別(默認不打印的, 建議生產環境設置成BASIC)
```
# 9. 常見問題總結
```
參考: https://www.imooc.com/article/289005
```