Feign如何實現第三方的HTTP請求
最近,在使用spring cloud框架時,發現feign也能實現三方請求,而且實現很簡單,請求接口的結構很清晰,便果斷學習一波。
記錄一下。本次使用的依賴僅有openfeign。
Feign調用的簡單實現
maven依賴
<!-- openfeign依賴 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
Feign配置方式
feign有三種使用方式,前一種多是用於無需配置的微服務內部調用,後兩者是用於自定義配置的三方調用或者內部微服務調用。
1. 默認模式,不使用配置類,作用於服務內部調用而非三方請求接口
這種情況下,如果不需要給註冊中心的微服務添加額外的參數配置,那麼可以不使用配置類,直接在yml配置打開feign開關即可。
此時默認使用SpringMVC契約模式。如下代碼中,yml配置為用戶中心的配置文件。
如果一個業務中心想要根據用戶id查詢用戶信息,那麼便可以直接根據用戶中心的服務名定位,如UserService 類中的@FeignClient配置,註冊中心會自動根據服務名尋址到用戶中心的地址。
# 用戶中心的服務名 spring: application: name: user-service # 註冊中心 eureka: instance: prefer-ip-address: true hostname: localhost client: service-url: defaultZone: http://localhost:8080/eureka/ # feign feign: httpclient: enabled: true
@FeignClient(name = "user-service", fallback = UserServiceHystrix.class) public interface UserService { @GetMapping("/user/getUserById") Result getUserById(@RequestParam("id") String id); }
2.自定義配置類
自定義配置類時, 直接在feign的配置類上加@Configuration註解,該註解的方式是全局的,對於所有由@FeignClient註解的調用類都生效。
這樣的好處在於,調用項目註冊中心的其他服務時不用頻繁的手動去加載配置類。該配置類也會被加載到spring cloud feign的服務調用中。
不過,比較致命的是,調用外部API時有可能會和微服務調用之間產生沖突。
Feign契約不支持SpringMVC契約,在feign契約下使用springMVC註解時,spring註解的部分功能會失效,甚至導致創建bean失敗等。
(大部分java.lang.IllegalStateException: Method getAllUrl not annotated with HTTP method type (ex. GET, POST) 異常都是由於契約問題造成的。)
3.自定義配置類法2
自定義配置類時,另一種則是不使用註解對配置類加以標識,而是在@FeignClient的註解中添加配置參數,在需要調用外部API接口的feign調用類裡手動加載該配置,加載方式如後文中ApiService服務所示。
使用這種方式能將項目同註冊中心的服務與外部API區分開來。
但是需要每一個feign類去手動加載該配置。@FeignClient參數會在下文中講到。
4. @FeignClient參數說明
@FeignClient用來修飾類、接口類、註解類等。它的所有參數如下:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FeignClient { @AliasFor("name") String value() default ""; /** @deprecated */ @Deprecated String serviceId() default ""; String contextId() 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; }
value
:服務名,訪問第三方接口時可以隨便命名。支持從配置文件中獲取配置。name
:請求的服務名(用於微服務時,請求其他服務名的名稱)。url
:第三方請求地址,支持從配置文件中獲取配置。fallback
:失敗時請求的回調類,熔斷處理。configuration
:手動加載feign配置類。
5. 自定義配置的簡單實現
A. Feign配置類
// 增加該配置時,該配置類就變成全局配置類 // @Configuration public class FeignConfig implements RequestInterceptor { @Autowired private ObjectFactory<HttpMessageConverters> messageConverters; @Bean public Contract feignContract() { // feign 契約 @RequestLine return new Contract.Default(); // springMVC契約 @GetMapping @PostMapping 等 // return new SpringMvcContract(); } // 記錄請求和響應的頭文件,正文和元數據的日志,需要在配置文件指出需要打印日志的類 @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } // 連接超時時間說明:連接超時時間,單位分鐘,讀取超時時間,單位秒,重定向為是 @Bean public Options options() { return new Options(10, TimeUnit.MINUTES, 60, TimeUnit.SECONDS, true); } // 編碼方式 @Bean public Encoder feignFormEncoder() { return new SpringFormEncoder(new SpringEncoder(messageConverters)); } // (全局設置)設置請求頭等業務需要參數。 @Override public void apply(RequestTemplate template) { } }
B. 配置文件
使用yml文件配置。Feign默認使用URLConnection發送HTTP請求。可以通過配置文件修改他的http發送方式如:httpclient、okhttp等。可以根據自己的需求進行修改。
server: port: 8080 #設置feign請求方式 feign: httpclient: enabled: true # 打開debug請求日志 可以使用的參數有info warn error debug等 logging: level: com.example.feign.feign.ApiService: debug # 第三方請求地址 api: url: https://api.apiopen.top
C. 正式使用,feign無參數GET方式 請求三方接口
該部分的測試接口都是基於開源社區的測試接口。使用很久瞭,再次感謝一下開源社區大佬們的幸苦付出。現在有好多接口都用不瞭。希望大傢不要惡意刷接口。
請求方式:GET
請求地址:https://api.apiopen.top/getSingleJoke
方法上使用的註解是feign契約(Contract)RequestLine。要使用Spring契約 GetMapping 等註解時,需要在FeignConfig中配置即可。
ApiService類代碼如下:
@FeignClient(value = "api-service", url = "${api.url}" , fallback = ApiServiceHystrix.class, configuration = FeignConfig.class) public interface ApiService { /** * 平臺接口預覽 方法名可以隨便取 */ @RequestLine("GET /getAllUrl") List<String> getAllUrl(); }
ApiServiceHystrix類代碼:
public class ApiServiceHystrix implements ApiService { @Override public List<String> getAllUrl() { // 設置調用失敗時的降級處理 return null; } }
調用寫好的接口,查看參數:
調用成功!Feign的基礎調用很簡單,如果需要調用多個相同地址的第三方請求,隻需要新增方法即可,無需再增加額外的配置。
但僅僅用於單次調用時,feign比起其他HTTP請求方式又稍顯麻煩,不過勝在簡潔明瞭。
6. Feign 的其他請求方式
- Query參數
請求方式:POST
請求地址:https://api.apiopen.top/getImages
現在嘗試用feign來進行Query請求。請求成功後,用於接收數據的對象可以是一個Java 對象類,也可以是JSONObject對象。當返回內容結構穩定時(成功失敗所返回的數據格式相同時),Java對象才能準確接收到信息。
創建一個結果類:
@Data public class ApiResult implements Serializable { private static final long serialVersionUID = 1L; private Integer code; private String message; private List result; }
ApiService類中增加對應方法:
@RequestLine("POST /getImages?page={page}&count={count}") ApiResult getImages(@Param("page") String page, @Param("count") String count);
請求結果:
- POST表單
post表單請求發送時,請求參數要為Map類型的鍵值對。示例代碼:
@RequestLine("POST /deleteFeedback") ApiResult deleteFeedback(@RequestBody Map<String, ?> bodyMap);
- 設置Header請求頭
請求頭可以通過feign註解 @HeaderMap(import feign.HeaderMap;)示例代碼:
@RequestLine("POST /requestHeader") JSONObject getTcText(@HeaderMap Map<String, Object> headers, @RequestBody Map<String, Object> map);
其他請求可移步git:open-feign
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 使用FeignClient設置動態Url
- 基於spring cloud多個消費端重復定義feign client的問題
- 基於FeignClient調用超時的處理方案
- feign 打印日志不顯示的問題及解決
- 輕量級聲明式的Http庫——Feign的獨立使用