日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Feign深入学习(一)

發布時間:2024/4/13 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Feign深入学习(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

Feign版本https://github.com/Netflix/feign不再維護,修改為https://github.com/OpenFeign/feign?。

Maven

<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-core</artifactId> </dependency> 或者 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>

原理?

注解

@RequestLine

為請求定義HttpMethodUriTemplate(標注在方法上的就是一個HttpMethod,且寫好了URI(可是絕對路徑,也可是相對的,一般寫后部分即可))。表達式、用大括號括起來的值{expression}最終會用對應的@Param注解填進去(根據key匹配)

@java.lang.annotation.Target(METHOD) @Retention(RUNTIME) public @interface RequestLine {// 請求方法 + URI 。首個單詞必須是HTTP方法,且必須頂格寫(前面不允許有空格)String value(); // 是否編碼/符號,默認是會編碼的,也就是轉義的意思boolean decodeSlash() default true;// 默認支持URL傳多值,是通過key來傳輸的。形如:key=value1&key=value2&key=value3// CollectionFormat不同的取值對應不同的分隔符,一般不建議改CollectionFormat collectionFormat() default CollectionFormat.EXPLODED;}

示例:

? ? @RequestLine("GET /feign/demo1?name={name}")
? ? @Body("{age}")
? ? String testRequestLine8(@Param("name") String name, @Param("age") Integer age);
?

@Param

只能標注在方法參數Parameter上。?通過名稱定義模板變量,其值將用于填入模版:@Headers/@RequestLine/@Body均可使用模版表達式。

@Retention(RUNTIME) @java.lang.annotation.Target(PARAMETER) public @interface Param {// 名稱(key),和模版會進行匹配然后填充 必填項String value();// 如何把值填充上去,默認是調用其toString方法直接填上去Class<? extends Expander> expander() default ToStringExpander.class;// 是否轉義,默認不轉義,直接放上去boolean encoded() default false;interface Expander {String expand(Object value);}final class ToStringExpander implements Expander {@Overridepublic String expand(Object value) {return value.toString();}} }

?@Headers

@Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Headers {String[] value(); }

@Headers({"Accept:*/*", "Accept-Language:zh-cn"})

@QueryMap

@Retention(RUNTIME) @java.lang.annotation.Target(PARAMETER) public @interface QueryMap {boolean encoded() default false; }

只能標注在方法參數上。用于傳遞多個查詢值,拼接在URL后面。
僅需注意一點:只能標注在Map類型的參數前面,否則報錯。

@HeaderMap

@Retention(RUNTIME) @java.lang.annotation.Target(PARAMETER) public @interface HeaderMap { }

只能標注在Map類型的參數前面

@Body

@Target(METHOD) @Retention(RUNTIME) public @interface Body {String value(); }

@Body("{body}"),這樣就可以通過方法參數的@Param("body") String body傳值。這個值最終是以http body體的形式發送的(并非URL參數哦),body體的內容并不要求必須是json,一般請配合請求頭使用。

可以看到body里是可以是任意格式的數據的,包括POJO(默認是調用它的toString方法)。Feign默認情況下只能支持文本消息,但后來feign提供了feign-form這個擴展模塊,所以也就能夠支持二進制、文件上傳

Template

它用于表示:按照 RFC 6570 標準書寫的表達式模版,有了此模版后續就可以用變量進行替換形成最終值。

public class Template {Template( ... ) { ... }// 一個{}就是一個Expression對象,根據name(key)進行匹配public String expand(Map<String, ?> variables) { ... }protected String resolveExpression(Expression expression, Map<String, ?> variables) { ... }// Uri Encode URI編碼// encodeSlash true的話連/也會給轉義,默認不轉義它private String encode(String value) { ... }// 拿到當前template下所有的變量的**名稱**public List<String> getVariables() { ... } }

UriTemplate

用于處理URI的模版,用于處理@RequestLine的模版。若對應key不存在或值為null,那么此部分表達式將被忽略。

QueryTemplate

查詢參數(Query String parameter)的模版。用于處理@QueryMap的模版。該模版用于構造一個查詢參數,一次性構建一個,若有多個key需要構建多次。

public final class QueryTemplate extends Template {// 這里name沒有用字符串而是使用了模版類型,是因為name也可以是個模版{}// 大部分情況下它可以是字符串即可private final Template name;// 因為一個key可以對應多值,所以用Listprivate List<String> values; // 當一key多值時候用什么分隔符,支持:, \t | 等等// 默認它是CollectionFormat.EXPLODED,也就是會以foo=bar&foo=baz這種形式拼接起來private final CollectionFormat collectionFormat;// 請注意:默認這里使用的是CollectionFormat.EXPLODEDpublic static QueryTemplate create(String name, Iterable<String> values, Charset charset) {return create(name, values, charset, CollectionFormat.EXPLODED);}// 可以看到它expand實際上是對name進行expand@Overridepublic String expand(Map<String, ?> variables) {String name = this.name.expand(variables);return this.queryString(name, super.expand(variables));} }

示例:

public void fun2() {QueryTemplate template = QueryTemplate.create("hobby-{arg}", Arrays.asList("basket", "foot"), StandardCharsets.UTF_8);Map<String, Object> params = new HashMap<>();//params擴展的是hobby-{arg},如果沒有值,則會轉義{arg}String result = template.expand(params);System.out.println(result);//out:hobby-%7Barg%7D=basket&hobby-%7Barg%7D=foot }

HeaderTemplate

BodyTemplate

用于表示標注有@Body注解的模版。

Target

用于把請求模版RequestTemplate 轉換為實際請求實例 feign.Request,此Request后續交給Client發送Http請求。

public interface Target<T> {// 此target作用的接口的類型Class<T> type();String name();// 發送請求的Base URL。如:https://example/api/v1String url();// 用于把請求模版組裝、加上Base Url、轉換為一個真正的Request// 此input模版里包含有很多的:QueryTemplate/HeaderTemplate/UriTemplateRequest apply(RequestTemplate input); }

HardCodedTarget

硬編碼目標類。它的三大參數都不能為null

Client

用來發送feign.Request這個Http請求的

public interface Client {// Options是一些選項參數,比如:// connectTimeoutMillis鏈接超時時間,默認是:10s// readTimeoutMillis鏈接超時時間,默認是:60sResponse execute(Request request, Options options) throws IOException; }

Retryer

重試器。它能對每次執行Http請求Client#execute()的狀態克隆保持,從而根據配置決定是否應該重試。

默認情況下,Feign是有重試機制的,并且是100ms重試一次,默認重試5次。生產環境下建議務必關閉Feign的重試機制。

InvocationHandlerFactory

控制反射方法調度。它是一個工廠,用于為目標target創建一個java.lang.reflect.InvocationHandler反射調用對象。

public interface InvocationHandlerFactory {// Dispatcher:每個方法對應的MethodHandler -> SynchronousMethodHandler實例// 創建出來的是一個FeignInvocationHandler實例,實現了InvocationHandler接口InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch); }

Default

它有且僅有一個實現類:feign.InvocationHandlerFactory.Default。

static final class Default implements InvocationHandlerFactory {// 很簡單:調用FeignInvocationHandler構造器完成實例的創建@Overridepublic InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {return new ReflectiveFeign.FeignInvocationHandler(target, dispatch);}}

FeignInvocationHandler

static class FeignInvocationHandler implements InvocationHandler {private final Target target;//存儲方法的handler。private final Map<Method, MethodHandler> dispatch;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("equals".equals(method.getName())) {try {Object otherHandler =args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;return equals(otherHandler);} catch (IllegalArgumentException e) {return false;}} else if ("hashCode".equals(method.getName())) { //target方法return hashCode();} else if ("toString".equals(method.getName())) { //target方法return toString();}return dispatch.get(method).invoke(args);} }

Contract

它決定了哪些注解可以標注在接口/接口方法上是有效的,并且提取出有效的信息,組裝成為MethodMetadata元信息

public interface Contract {// 此方法來解析類中鏈接到HTTP請求的方法:提取有效信息到元信息存儲List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType); }

?

總結

以上是生活随笔為你收集整理的Feign深入学习(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。