Feign如何實(shí)現(xiàn)第三方的HTTP請求
最近,在使用spring cloud框架時(shí),發(fā)現(xiàn)feign也能實(shí)現(xiàn)三方請求,而且實(shí)現(xiàn)很簡單,請求接口的結(jié)構(gòu)很清晰,便果斷學(xué)習(xí)一波。
記錄一下。本次使用的依賴僅有openfeign。
Feign調(diào)用的簡單實(shí)現(xiàn)
maven依賴
<!-- openfeign依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>Feign配置方式
feign有三種使用方式,前一種多是用于無需配置的微服務(wù)內(nèi)部調(diào)用,后兩者是用于自定義配置的三方調(diào)用或者內(nèi)部微服務(wù)調(diào)用。
1. 默認(rèn)模式,不使用配置類,作用于服務(wù)內(nèi)部調(diào)用而非三方請求接口
這種情況下,如果不需要給注冊中心的微服務(wù)添加額外的參數(shù)配置,那么可以不使用配置類,直接在yml配置打開feign開關(guān)即可。
此時(shí)默認(rèn)使用SpringMVC契約模式。如下代碼中,yml配置為用戶中心的配置文件。
如果一個業(yè)務(wù)中心想要根據(jù)用戶id查詢用戶信息,那么便可以直接根據(jù)用戶中心的服務(wù)名定位,如UserService 類中的@FeignClient配置,注冊中心會自動根據(jù)服務(wù)名尋址到用戶中心的地址。
# 用戶中心的服務(wù)名
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.自定義配置類
自定義配置類時(shí), 直接在feign的配置類上加@Configuration注解,該注解的方式是全局的,對于所有由@FeignClient注解的調(diào)用類都生效。
這樣的好處在于,調(diào)用項(xiàng)目注冊中心的其他服務(wù)時(shí)不用頻繁的手動去加載配置類。該配置類也會被加載到spring cloud feign的服務(wù)調(diào)用中。
不過,比較致命的是,調(diào)用外部API時(shí)有可能會和微服務(wù)調(diào)用之間產(chǎn)生沖突。
Feign契約不支持SpringMVC契約,在feign契約下使用springMVC注解時(shí),spring注解的部分功能會失效,甚至導(dǎo)致創(chuàng)建bean失敗等。
(大部分java.lang.IllegalStateException: Method getAllUrl not annotated with HTTP method type (ex. GET, POST) 異常都是由于契約問題造成的。)
3.自定義配置類法2
自定義配置類時(shí),另一種則是不使用注解對配置類加以標(biāo)識,而是在@FeignClient的注解中添加配置參數(shù),在需要調(diào)用外部API接口的feign調(diào)用類里手動加載該配置,加載方式如后文中ApiService服務(wù)所示。
使用這種方式能將項(xiàng)目同注冊中心的服務(wù)與外部API區(qū)分開來。
但是需要每一個feign類去手動加載該配置。@FeignClient參數(shù)會在下文中講到。
4. @FeignClient參數(shù)說明
@FeignClient用來修飾類、接口類、注解類等。它的所有參數(shù)如下:
@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:服務(wù)名,訪問第三方接口時(shí)可以隨便命名。支持從配置文件中獲取配置。name:請求的服務(wù)名(用于微服務(wù)時(shí),請求其他服務(wù)名的名稱)。url:第三方請求地址,支持從配置文件中獲取配置。fallback:失敗時(shí)請求的回調(diào)類,熔斷處理。configuration:手動加載feign配置類。
5. 自定義配置的簡單實(shí)現(xiàn)
A. Feign配置類
// 增加該配置時(shí),該配置類就變成全局配置類
// @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();
}
// 記錄請求和響應(yīng)的頭文件,正文和元數(shù)據(jù)的日志,需要在配置文件指出需要打印日志的類
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
// 連接超時(shí)時(shí)間說明:連接超時(shí)時(shí)間,單位分鐘,讀取超時(shí)時(shí)間,單位秒,重定向?yàn)槭?
@Bean
public Options options() {
return new Options(10, TimeUnit.MINUTES, 60, TimeUnit.SECONDS, true);
}
// 編碼方式
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
// (全局設(shè)置)設(shè)置請求頭等業(yè)務(wù)需要參數(shù)。
@Override
public void apply(RequestTemplate template) {
}
}B. 配置文件
使用yml文件配置。Feign默認(rèn)使用URLConnection發(fā)送HTTP請求。可以通過配置文件修改他的http發(fā)送方式如:httpclient、okhttp等??梢愿鶕?jù)自己的需求進(jìn)行修改。
server:
port: 8080
#設(shè)置feign請求方式
feign:
httpclient:
enabled: true
# 打開debug請求日志 可以使用的參數(shù)有info warn error debug等
logging:
level:
com.example.feign.feign.ApiService: debug
# 第三方請求地址
api:
url: https://api.apiopen.topC. 正式使用,feign無參數(shù)GET方式 請求三方接口
該部分的測試接口都是基于開源社區(qū)的測試接口。使用很久了,再次感謝一下開源社區(qū)大佬們的幸苦付出?,F(xiàn)在有好多接口都用不了。希望大家不要惡意刷接口。
請求方式:GET
請求地址:https://api.apiopen.top/getSingleJoke
方法上使用的注解是feign契約(Contract)RequestLine。要使用Spring契約 GetMapping 等注解時(shí),需要在FeignConfig中配置即可。
ApiService類代碼如下:
@FeignClient(value = "api-service", url = "${api.url}"
, fallback = ApiServiceHystrix.class, configuration = FeignConfig.class)
public interface ApiService {
/**
* 平臺接口預(yù)覽 方法名可以隨便取
*/
@RequestLine("GET /getAllUrl")
List<String> getAllUrl();
}ApiServiceHystrix類代碼:
public class ApiServiceHystrix implements ApiService {
@Override
public List<String> getAllUrl() {
// 設(shè)置調(diào)用失敗時(shí)的降級處理
return null;
}
}調(diào)用寫好的接口,查看參數(shù):

調(diào)用成功!Feign的基礎(chǔ)調(diào)用很簡單,如果需要調(diào)用多個相同地址的第三方請求,只需要新增方法即可,無需再增加額外的配置。
但僅僅用于單次調(diào)用時(shí),feign比起其他HTTP請求方式又稍顯麻煩,不過勝在簡潔明了。
6. Feign 的其他請求方式
- Query參數(shù)
請求方式:POST
請求地址:https://api.apiopen.top/getImages
現(xiàn)在嘗試用feign來進(jìn)行Query請求。請求成功后,用于接收數(shù)據(jù)的對象可以是一個Java 對象類,也可以是JSONObject對象。當(dāng)返回內(nèi)容結(jié)構(gòu)穩(wěn)定時(shí)(成功失敗所返回的數(shù)據(jù)格式相同時(shí)),Java對象才能準(zhǔn)確接收到信息。
創(chuàng)建一個結(jié)果類:
@Data
public class ApiResult implements Serializable {
private static final long serialVersionUID = 1L;
private Integer code;
private String message;
private List result;
}ApiService類中增加對應(yīng)方法:
@RequestLine("POST /getImages?page={page}&count={count}")
ApiResult getImages(@Param("page") String page, @Param("count") String count);請求結(jié)果:

- POST表單
post表單請求發(fā)送時(shí),請求參數(shù)要為Map類型的鍵值對。示例代碼:
@RequestLine("POST /deleteFeedback")
ApiResult deleteFeedback(@RequestBody Map<String, ?> bodyMap);- 設(shè)置Header請求頭
請求頭可以通過feign注解 @HeaderMap(import feign.HeaderMap;)示例代碼:
@RequestLine("POST /requestHeader")
JSONObject getTcText(@HeaderMap Map<String, Object> headers, @RequestBody Map<String, Object> map);其他請求可移步git:open-feign
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot集成Mybatis的實(shí)現(xiàn)步驟
這篇文章主要介紹了SpringBoot集成Mybatis的實(shí)現(xiàn)步驟,本文通過SpringBoot +MyBatis 實(shí)現(xiàn)對數(shù)據(jù)庫學(xué)生表的查詢操作,需要的朋友可以參考下2020-12-12
淺析Spring容器原始Bean是如何創(chuàng)建的
這篇文章主要是想和小伙伴們一起聊聊?Spring?容器創(chuàng)建?Bean?最最核心的?createBeanInstance?方法,文中的示例代碼講解詳細(xì),需要的可以參考一下2023-08-08
在CentOS系統(tǒng)上安裝Java的openjdk的方法
這篇文章主要介紹了在CentOS系統(tǒng)上安裝Java的openjdk的方法,同樣適用于Fedora等其他RedHat系的Linux系統(tǒng),需要的朋友可以參考下2015-06-06

