Feign 簡介 Spring Cloud Feign 是一個 HTTP 請求調用的輕量級框架,可以以 Java 介面註解的方式調用 HTTP 請求,而不用通過封裝 HTTP 請求報文的方式直接調用 Feign 通過處理註解,將請求模板化,當實際調用的時候傳入參數,根據參數再應用到請求上,進而轉化成 ...
Feign 簡介
Spring Cloud Feign 是一個 HTTP 請求調用的輕量級框架,可以以 Java 介面註解的方式調用 HTTP 請求,而不用通過封裝 HTTP 請求報文的方式直接調用
Feign 通過處理註解,將請求模板化,當實際調用的時候傳入參數,根據參數再應用到請求上,進而轉化成真正的請求
第一個 Feign 程式
本小節介紹如何通過 Nacos+Feign 實現服務之間的調用,新建 server-01、server-02 項目,並分別註冊 Nacos
server-01 引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
新建 Server02FeignClient 介面,用於調用 server-02 提供的對外介面
// name:要調用的服務名
FeignClient(name = "server-02")
public interface Server02FeignClient {
@GetMapping("/test/getConfig")
void getConfig();
}
啟動類加上註解 @EnableFeignClients
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class Server01Application {
public static void main(String[] args) {
SpringApplication.run(Server01Application.class, args);
}
}
使用 Server02FeignClient 調用 server-02 的介面
@Slf4j
@RestController
public class TestCon {
@Autowired
private Server02FeignClient server02FeignClient;
@GetMapping("/test/getConfigByFeign")
public void getConfigByFeign() {
server02FeignClient.getConfig();
}
}
在 server-02 創建介面
@Slf4j
@RestController
public class TestCon {
@Value("${test.value}")
private String testValue;
@Value("${spring.application.name}")
private String applicationName;
@Value("${server.port}")
private String port;
@GetMapping("/test/getConfig")
public void getConfig() {
log.info("testValue: {} by {}-{}", testValue, applicationName, port);
}
}
調用 server-01 的 /test/getConfigByFeign
介面,就會通過 Feign 調用 server-02 的 /test/getConfig
介面
@FeignClient
註解可作用在類、介面、枚舉上,主要包含如下屬性:
-
name/value:name 是 vaue 的別名,value 也是 name 的別名,兩者的作用是一致的,用指定 FeignClient 的名稱,如果配合註冊中心使用,則作為微服務的名稱,用於服務發現
-
url:主要用於調試,可以手動指定
@FeignClient
調用的地址 -
path:path 用於定義當前 FeignClient 的統一首碼
-
contextld:如果要創建多個具有相同名稱或 URL 的 Feign 客戶端,以便它們指向同一臺伺服器,但是每個客戶端具有不同的自定義配置,則必須使用 contextId 屬性,以避免這些配置的名稱衝突
@FeignClient(contextId = "fooClient", name = "stores", configuration=FooConfiguration.class)
public interface FooClient {...}
@FeignClient(contextId = "barClient", name = "stores", configuration=BarConfiguration.class)
public interface BarClient {...}
-
fallback/fallbackFactory:
-
fallback:定義容錯的處理類,當調用遠程介面失敗或超時時,就會調用對應介面的容錯邏輯,falback 指定的類必須實現
@FeignClient
標記的介面 -
fallbackFactory:工廠類,用於生成 fallback 類,通過該屬性可以實現每個介面通用的容錯邏輯,減少重覆的代碼
-
decode404:當發生 404 錯誤時,如果該欄位為 true,就會調用 decoder 進行解碼,否則拋出異常
-
Configuration:Feign 配置類可以自定義 Feign 的 Encoder、Decoder、LogLevel、Contract 等,OpenFeign 預設為 Feign 提供以下對象(bean 類型 bean 名稱 : 類名稱):
-
Decoder feignDecoder : ResponseEntityDecoder
-
Encoder feignEncoder : SpringEncoder
-
Logger feignLogger : Slf4jLogger
-
Contract feignContract : SpringMvcContract
-
FeignBuilder feignBuilder : HystrixFeignBuilder
spring-cloud-starter-openfeign 支持 spring-cloud-starter-netflix-ribbon 和 spring-cloud-starter.loadbalancer,如果 Ribbon 在類路徑中且已啟用,則 Client feignClient 是 LoadBalancerFeignClient,如果 SpringCloud LoadBalancer 在類路徑中,則使用 FeignBlockingLoadBalancerClient
預設情況下,Spring Cloud OpenFeign 不會為 Feign 提供以下 bean 對象,但是仍然會從應用程式上下文中查找這些類型的 bean 以創建 Feign 客戶端:
- Logger.Level
- Retryer
- ErrorDecoder
- Request.Options
- Collection<RequestInterceptor>
- SetterFactory
- QueryMapEncoder
以上是通過註解 @FeignClient
的配置屬性進行配置的,我們也可以使用配置文件進行配置
feign:
client:
config:
feignName:
connectTimeout: 5000
readTimeout:5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example,SimpleRetryer
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example,BarRequestInterceptor
decode404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract
可以在 @EnableFeignClients
屬性 defaultConfiguration 中指定預設配置,不同之處在於此配置將適用於所有 Feign 客戶端
如果希望使用配置文件來配置所有 @FeignClient
,則可以使用預設 Feign 名稱創建配置屬性,例如:
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
如果同時創建 @Configuration
bean 和配置文件,則配置文件將覆蓋 @Configuration
值,如果要將優先順序更改為 @Configuration
,就可以將 feign.client.default-to-properties
更改為 false
Feign 傳參
以下服務端介面可通過 Get 或 Post 請求調用並接收參數
@RequestMapping("/test/testFeignWithParam")
public void testFeignWithParam(@RequestParam String name,
@RequestParam int age) {
log.info("testFeignWithParam: name-{}, age-{}", name, age);
}
通過在 Url 拼接請求傳參如下:
@FeignClient(name = "server-02", path = "server-02")
public interface Server02FeignClient {
@GetMapping("/test/testFeignWithParam?name=zhanghsan&age=66")
//@PostMapping("/test/testFeignWithParam?name=zhanghsan&age=66")
void testFeignWithParam();
}
使用 @RequestParam
傳參如下:
@FeignClient(name = "server-02", path = "server-02")
public interface Server02FeignClient {
//@GetMapping("/test/testFeignWithParam")
@PostMapping("/test/testFeignWithParam")
void testFeignWithParam(@RequestParam("name") String name,
@RequestParam("age") int age);
}
也可以使用 OpenFeign 的 @QueryMap
將請求實體作為參數的映射,不過由於 @QueryMap
註解與 Spring 不相容,所以 OpenFeign 提供了等效的 @SpringQueryMap
註解
@FeignClient(name = "server-02", path = "server-02")
public interface Server02FeignClient {
//@GetMapping("/test/testFeignWithQueryMap")
@PostMapping("/test/testFeignWithQueryMap")
void testFeignWithQueryMap(@SpringQueryMap FeignParam param);
}