<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] # 1. gateway基本概念 * Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技術開發的網關,Spring Cloud Gateway旨在為微服務架構提供一種簡單而有效的統一的API路由管理方式。 * Spring Cloud Gateway作為Spring Cloud生態系中的網關,目標是替代ZUUL,其不僅提供統一的**路由方式,并且基于Filter鏈的方式提供了網關基本的功能,例如:安全,監控/埋點,和限流等。** * 內置了 10 種 Router,使得我們可以直接配置一下就可以隨心所欲的根據 Header、或者 Path、或者 Host、或者 Query 來做路由。 * **過濾器分為Filter(內置20種) 和全局 Filter兩種(內置9種)** ![](https://img.kancloud.cn/a9/48/a94860bf14437fb5331a84e5742b63a2_1502x494.png) ![](https://img.kancloud.cn/ac/e4/ace44633c2e8d75e73b403dffe2200ff_1794x1006.png) ![](https://img.kancloud.cn/66/85/6685de69532dfd4477b3b1dabeaccb8c_1862x716.png) # 2. gateway 請求路由 就是使用Predicate實現一組匹配規則,方便讓請求過來找到對應的 Route 進行處理,接下來我們接下 Spring Cloud GateWay 內置幾種 Predicate 的使用。 ## 2.1 通過時間匹配 Predicate 支持設置一個時間,在請求進行轉發的時候,可以通過判斷在這個時間之前或者之后進行轉發。比如我們現在設置只有在 2019 年 1 月 1 日才會轉發到我的網站,在這之前不進行轉發,我就可以這樣配置: ~~~ spring: cloud: gateway: routes: - id: time_route uri: http://ityouknow.com predicates: - After=2018-01-20T06:06:06+08:00[Asia/Shanghai] ~~~ Spring 是通過 ZonedDateTime 來對時間進行的對比,ZonedDateTime 是 Java 8 中日期時間功能里,用于表示帶時區的日期與時間信息的類,ZonedDateTime 支持通過時區來設置時間,中國的時區是:`Asia/Shanghai`。 After Route Predicate 是指在這個時間之后的請求都轉發到目標地址。上面的示例是指,請求時間在 2018 年 1 月 20 日 6 點 6 分 6 秒之后的所有請求都轉發到地址`http://ityouknow.com`。`+08:00`是指時間和 UTC 時間相差八個小時,時間地區為`Asia/Shanghai`。 添加完路由規則之后,訪問地址`http://localhost:8080`會自動轉發到`http://ityouknow.com`。 Before Route Predicate 剛好相反,在某個時間之前的請求的請求都進行轉發。我們把上面路由規則中的 After 改為 Before,如下: ~~~ spring: cloud: gateway: routes: - id: after_route uri: http://ityouknow.com predicates: - Before=2018-01-20T06:06:06+08:00[Asia/Shanghai] ~~~ 就表示在這個時間之前可以進行路由,在這時間之后停止路由,修改完之后重啟項目再次訪問地址`http://localhost:8080`,頁面會報 404 沒有找到地址。 除過在時間之前或者之后外,Gateway 還支持限制路由請求在某一個時間段范圍內,可以使用 Between Route Predicate 來實現。 ~~~ spring: cloud: gateway: routes: - id: after_route uri: http://ityouknow.com predicates: - Between=2018-01-20T06:06:06+08:00[Asia/Shanghai], 2019-01-20T06:06:06+08:00[Asia/Shanghai] ~~~ 這樣設置就意味著在這個時間段內可以匹配到此路由,超過這個時間段范圍則不會進行匹配。通過時間匹配路由的功能很酷,可以用在限時搶購的一些場景中。 ## 2.2 通過 Cookie 匹配 Cookie Route Predicate 可以接收兩個參數,一個是 Cookie name , 一個是正則表達式,路由規則會通過獲取對應的 Cookie name 值和正則表達式去匹配,如果匹配上就會執行路由,如果沒有匹配上則不執行。 ~~~ spring: cloud: gateway: routes: - id: cookie_route uri: http://ityouknow.com predicates: - Cookie=ityouknow, kee.e ~~~ 使用 curl 測試,命令行輸入: ~~~ curl http://localhost:8080 --cookie "ityouknow=kee.e" ~~~ 則會返回頁面代碼,如果去掉`--cookie "ityouknow=kee.e"`,后臺匯報 404 錯誤。 ## 2.3 Header Route Predicate 和 Cookie Route Predicate 一樣,也是接收 2 個參數,一個 header 中屬性名稱和一個正則表達式,這個屬性值和正則表達式匹配則執行。 ~~~ spring: cloud: gateway: routes: - id: header_route uri: http://ityouknow.com predicates: - Header=X-Request-Id, \d+ ~~~ 使用 curl 測試,命令行輸入: ~~~ curl http://localhost:8080 -H "X-Request-Id:666666" ~~~ 則返回頁面代碼證明匹配成功。將參數`-H "X-Request-Id:666666"`改為`-H "X-Request-Id:neo"`再次執行時返回 404 證明沒有匹配。 ## 2.4 通過 Host 匹配 Host Route Predicate 接收一組參數,一組匹配的域名列表,這個模板是一個 ant 分隔的模板,用`.`號作為分隔符。它通過參數中的主機地址作為匹配規則。 ~~~ spring: cloud: gateway: routes: - id: host_route uri: http://ityouknow.com predicates: - Host=**.ityouknow.com ~~~ 使用 curl 測試,命令行輸入: ~~~ curl http://localhost:8080 -H "Host: www.ityouknow.com" curl http://localhost:8080 -H "Host: md.ityouknow.com" ~~~ 經測試以上兩種 host 均可匹配到 host\_route 路由,去掉 host 參數則會報 404 錯誤。 ## 2.5 通過請求方式匹配 可以通過是 POST、GET、PUT、DELETE 等不同的請求方式來進行路由。 ~~~ spring: cloud: gateway: routes: - id: method_route uri: http://ityouknow.com predicates: - Method=GET ~~~ 使用 curl 測試,命令行輸入: ~~~ # curl 默認是以 GET 的方式去請求 curl http://localhost:8080 ~~~ 測試返回頁面代碼,證明匹配到路由,我們再以 POST 的方式請求測試。 ~~~ # curl 默認是以 GET 的方式去請求 curl -X POST http://localhost:8080 ~~~ 返回 404 沒有找到,證明沒有匹配上路由 ## 2.6 通過請求路徑匹配 Path Route Predicate 接收一個匹配路徑的參數來判斷是否走路由。 ~~~ spring: cloud: gateway: routes: - id: host_route uri: http://ityouknow.com predicates: - Path=/foo/{segment} ~~~ 如果請求路徑符合要求,則此路由將匹配,例如:/foo/1 或者 /foo/bar。 `- Path=/foo/** ` 配置所有/foot開頭的請求 使用 curl 測試,命令行輸入: ~~~ curl http://localhost:8080/foo/1 curl http://localhost:8080/foo/xx curl http://localhost:8080/boo/xx ~~~ 經過測試第一和第二條命令可以正常獲取到頁面返回值,最后一個命令報 404,證明路由是通過指定路由來匹配。 ## 2.7 通過請求參數匹配 Query Route Predicate 支持傳入兩個參數,一個是屬性名一個為屬性值,屬性值可以是正則表達式。 ~~~ spring: cloud: gateway: routes: - id: query_route uri: http://ityouknow.com predicates: - Query=smile ~~~ 這樣配置,只要請求中包含 smile 屬性的參數即可匹配路由。 使用 curl 測試,命令行輸入: ~~~ curl localhost:8080?smile=x&id=2 ~~~ 經過測試發現只要請求匯總帶有 smile 參數即會匹配路由,不帶 smile 參數則不會匹配。 還可以將 Query 的值以鍵值對的方式進行配置,這樣在請求過來時會對屬性值和正則進行匹配,匹配上才會走路由。 ~~~ spring: cloud: gateway: routes: - id: query_route uri: http://ityouknow.com predicates: - Query=keep, pu. ~~~ 這樣只要當請求中包含 keep 屬性并且參數值是以 pu 開頭的長度為三位的字符串才會進行匹配和路由。 使用 curl 測試,命令行輸入: ~~~ curl localhost:8080?keep=pub ~~~ 測試可以返回頁面代碼,將 keep 的屬性值改為 pubx 再次訪問就會報 404, 證明路由需要匹配正則表達式才會進行路由。 ## 2.8 通過請求 ip 地址進行匹配 Predicate 也支持通過設置某個 ip 區間號段的請求才會路由,RemoteAddr Route Predicate 接受 cidr 符號 (IPv4 或 IPv6) 字符串的列表(最小大小為 1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子網掩碼)。 ~~~ spring: cloud: gateway: routes: - id: remoteaddr_route uri: http://ityouknow.com predicates: - RemoteAddr=192.168.1.1/24 ~~~ 可以將此地址設置為本機的 ip 地址進行測試。 果請求的遠程地址是 192.168.1.10,則此路由將匹配。 ## 2.9 組合使用 上面為了演示各個 Predicate 的使用,我們是單個單個進行配置測試,其實可以將各種 Predicate 組合起來一起使用。 例如: ~~~ spring: cloud: gateway: routes: - id: host_foo_path_headers_to_httpbin uri: http://ityouknow.com predicates: - Host=**.foo.org - Path=/headers - Method=GET - Header=X-Request-Id, \d+ - Query=foo, ba. - Query=baz - Cookie=chocolate, ch.p - After=2018-01-20T06:06:06+08:00[Asia/Shanghai] ~~~ ## 方式二:編碼 以上是基于配置文件方式,還可以編碼的方式添加路由 配置訪問路由端口`/guonei`鏈接到`http://news.baidu.com/guonei`的示例代碼 ~~~ import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class GatewayConfigration { @Bean public RouteLocator myRouteLocator(RouteLocatorBuilder builder){ RouteLocatorBuilder.Builder routes=builder.routes(); routes.route("my_path_routh",r->r.path("/guonei").uri("http://news.baidu.com/guonei")); return routes.build(); } } ~~~ # 3. gateway請求過濾 filter * predicate斷言是對請求路由處理,找到對應的后臺服務,而在路由處理之前,需要經過`pre`類型的filter,處理放回響應后由`post`類型的請求處理,和mvc的過濾器類似。 * 在`pre`類型的過濾器可以做參數校驗、權限校驗、流量監控、日志輸出、協議轉換等 * 在`post`類型的過濾器中可以做響應內容、響應頭的修改,日志的輸出,流量監控等。 ## 3.1 生命周期 Spring Cloud Gateway同zuul類似,有“pre”和“post”兩種方式的filter。客戶端的請求先經過“pre”類型的filter,然后將請求轉發到具體的業務服務,比如上圖中的user-service,收到業務服務的響應之后,再經過“post”類型的filter處理,最后返回響應到客戶端。 ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20190601011115924.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9mb3JlenAuYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70) 與zuul不同的是,filter除了分為“pre”和“post”兩種方式的filter外,在Spring Cloud Gateway中,filter從作用范圍可分為另外兩種,一種是針對于單個路由的gateway filter,它在配置文件中的寫法同predict類似;另外一種是針對于所有路由的global gateway filer。現在從作用范圍劃分的維度來講解這兩種filter。 ## 3.2 AddRequestHeader GatewayFilter Factory **增加請求頭過濾器** 創建工程,引入相關的依賴,包括spring boot 版本2.0.5,spring Cloud版本Finchley,gateway依賴如下: ~~~ <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> ~~~ 在工程的配置文件中,加入以下的配置: ~~~text server: port: 8081 spring: profiles: active: add_request_header_route --- spring: cloud: gateway: routes: - id: add_request_header_route uri: http://httpbin.org:80/get filters: - AddRequestHeader=X-Request-Foo, Bar predicates: - After=2017-01-20T17:42:47.789-07:00[America/Denver] profiles: add_request_header_route ~~~ 在上述的配置中,工程的啟動端口為8081,配置文件為add\_request\_header\_route,在add\_request\_header\_route配置中,配置了roter的id為add\_request\_header\_route,路由地址為http://httpbin.org:80/get,該router有AfterPredictFactory,有一個filter為AddRequestHeaderGatewayFilterFactory(約定寫成AddRequestHeader),AddRequestHeader過濾器工廠會在請求頭加上一對請求頭,名稱為X-Request-Foo,值為Bar。為了驗證AddRequestHeaderGatewayFilterFactory是怎么樣工作的,查看它的源碼,AddRequestHeaderGatewayFilterFactory的源碼如下: ~~~ public class AddRequestHeaderGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory { @Override public GatewayFilter apply(NameValueConfig config) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest().mutate() .header(config.getName(), config.getValue()) .build(); return chain.filter(exchange.mutate().request(request).build()); }; } } ~~~ 由上面的代碼可知,根據舊的ServerHttpRequest創建新的 ServerHttpRequest ,在新的ServerHttpRequest加了一個請求頭,然后創建新的 ServerWebExchange ,提交過濾器鏈繼續過濾。 啟動工程,通過curl命令來模擬請求: ~~~ curl localhost:8081 ~~~ 最終顯示了從 http://httpbin.org:80/get得到了請求,響應如下: ~~~ { "args": {}, "headers": { "Accept": "*/*", "Connection": "close", "Forwarded": "proto=http;host=\"localhost:8081\";for=\"0:0:0:0:0:0:0:1:56248\"", "Host": "httpbin.org", "User-Agent": "curl/7.58.0", "X-Forwarded-Host": "localhost:8081", "X-Request-Foo": "Bar" }, "origin": "0:0:0:0:0:0:0:1, 210.22.21.66", "url": "http://localhost:8081/get" } ~~~ 可以上面的響應可知,確實在請求頭中加入了X-Request-Foo這樣的一個請求頭,在配置文件中配置的AddRequestHeader過濾器工廠生效。 跟AddRequestHeader過濾器工廠類似的還有AddResponseHeader過濾器工廠,在此就不再重復。 ## 3.3 RewritePath GatewayFilter Factory **路徑重寫** 在Nginx服務啟中有一個非常強大的功能就是重寫路徑,Spring Cloud Gateway默認也提供了這樣的功能,這個功能是Zuul沒有的。在配置文件中加上以下的配置: ~~~ spring: profiles: active: rewritepath_route --- spring: cloud: gateway: routes: - id: rewritepath_route uri: https://blog.csdn.net predicates: - Path=/foo/** filters: - RewritePath=/foo/(?<segment>.*), /$\{segment} profiles: rewritepath_route ~~~ 上面的配置中,所有的/foo/\*\*開始的路徑都會命中配置的router,并執行過濾器的邏輯,在本案例中配置了RewritePath過濾器工廠,此工廠將/foo/(?.\*)重寫為{segment},然后轉發到https://blog.csdn.net。比如在網頁上請求localhost:8081/foo/forezp,此時會將請求轉發到https://blog.csdn.net/forezp的頁面,比如在網頁上請求localhost:8081/foo/forezp/1,頁面顯示404,就是因為不存在https://blog.csdn.net/forezp/1這個頁面。 ## 3.4 自定義過濾器 Spring Cloud Gateway內置了19種強大的過濾器工廠,能夠滿足很多場景的需求,那么能不能自定義自己的過濾器呢,當然是可以的。在spring Cloud Gateway中,過濾器需要實現GatewayFilter和Ordered2個接口。寫一個RequestTimeFilter,代碼如下: 統計請求耗時: ### 3.4.1 定義filter ~~~ public class RequestTimeFilter implements GatewayFilter, Ordered { private static final Log log = LogFactory.getLog(GatewayFilter.class); private static final String REQUEST_TIME_BEGIN = "requestTimeBegin"; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis()); return chain.filter(exchange).then( Mono.fromRunnable(() -> { Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN); if (startTime != null) { log.info(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms"); } }) ); } @Override public int getOrder() { return 0; } } ~~~ 在上面的代碼中,Ordered中的int getOrder()方法是來給過濾器設定優先級別的,值越大則優先級越低。還有有一個filterI(exchange,chain)方法,在該方法中,先記錄了請求的開始時間,并保存在ServerWebExchange中,此處是一個“pre”類型的過濾器,然后再chain.filter的內部類中的run()方法中相當于"post"過濾器,在此處打印了請求所消耗的時間。 ### 3.4.2 注冊filter 然后將該過濾器注冊到router中,代碼如下: ~~~ @Bean public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/customer/**") .filters(f -> f.filter(new RequestTimeFilter()) .addResponseHeader("X-Response-Default-Foo", "Default-Bar")) .uri("http://httpbin.org:80/get") .order(0) .id("customer_filter_router") ) .build(); } ~~~ 重啟程序,通過curl命令模擬請求: ~~~ curl localhost:8081/customer/123 ~~~ 在程序的控制臺輸出一下的請求信息的日志: ~~~ 2018-11-16 15:02:20.177 INFO 20488 --- [ctor-http-nio-3] o.s.cloud.gateway.filter.GatewayFilter : /customer/123: 152ms ~~~ ## 3.5 自定義過濾器工廠 在上面的自定義過濾器中,有沒有辦法自定義過濾器工廠類呢?這樣就可以在配置文件中配置過濾器了。現在需要實現一個過濾器工廠,在打印時間的時候,可以設置參數來決定是否打印請參數。查看GatewayFilterFactory的源碼,可以發現GatewayFilterfactory的層級如下: ![微信截圖_20181204175448.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly93d3cuZmFuZ3poaXBlbmcuY29tL2ltZy9qaWFuc2h1LzIyNzk1OTQtZjk3ZTEwNDVjZWJjOTU0Yy5wbmc?x-oss-process=image/format,png) 過濾器工廠的頂級接口是GatewayFilterFactory,我們可以直接繼承它的兩個抽象類來簡化開發AbstractGatewayFilterFactory和AbstractNameValueGatewayFilterFactory,這兩個抽象類的區別就是前者接收一個參數(像StripPrefix和我們創建的這種),后者接收兩個參數(像AddResponseHeader)。 過濾器工廠的頂級接口是GatewayFilterFactory,有2個兩個較接近具體實現的抽象類,分別為AbstractGatewayFilterFactory和AbstractNameValueGatewayFilterFactory,這2個類前者接收一個參數,比如它的實現類RedirectToGatewayFilterFactory;后者接收2個參數,比如它的實現類AddRequestHeaderGatewayFilterFactory類。現在需要將請求的日志打印出來,需要使用一個參數,這時可以參照RedirectToGatewayFilterFactory的寫法。 ~~~ public class RequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<RequestTimeGatewayFilterFactory.Config> { private static final Log log = LogFactory.getLog(GatewayFilter.class); private static final String REQUEST_TIME_BEGIN = "requestTimeBegin"; private static final String KEY = "withParams"; @Override public List<String> shortcutFieldOrder() { return Arrays.asList(KEY); } public RequestTimeGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis()); return chain.filter(exchange).then( Mono.fromRunnable(() -> { Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN); if (startTime != null) { StringBuilder sb = new StringBuilder(exchange.getRequest().getURI().getRawPath()) .append(": ") .append(System.currentTimeMillis() - startTime) .append("ms"); if (config.isWithParams()) { sb.append(" params:").append(exchange.getRequest().getQueryParams()); } log.info(sb.toString()); } }) ); }; } public static class Config { private boolean withParams; public boolean isWithParams() { return withParams; } public void setWithParams(boolean withParams) { this.withParams = withParams; } } } ~~~ 在上面的代碼中 apply(Config config)方法內創建了一個GatewayFilter的匿名類,具體的實現邏輯跟之前一樣,只不過加了是否打印請求參數的邏輯,而這個邏輯的開關是config.isWithParams()。靜態內部類類Config就是為了接收那個boolean類型的參數服務的,里邊的變量名可以隨意寫,但是要重寫List shortcutFieldOrder()這個方法。 。 需要注意的是,在類的構造器中一定要調用下父類的構造器把Config類型傳過去,否則會報ClassCastException 最后,需要在工程的啟動文件Application類中,向Srping Ioc容器注冊RequestTimeGatewayFilterFactory類的Bean。 ~~~ @Bean public RequestTimeGatewayFilterFactory elapsedGatewayFilterFactory() { return new RequestTimeGatewayFilterFactory(); } ~~~ 然后可以在配置文件中配置如下: ~~~ spring: profiles: active: elapse_route --- spring: cloud: gateway: routes: - id: elapse_route uri: http://httpbin.org:80/get filters: - RequestTime=false predicates: - After=2017-01-20T17:42:47.789-07:00[America/Denver] profiles: elapse_route ~~~ 啟動工程,在瀏覽器上訪問localhost:8081?name=forezp,可以在控制臺上看到,日志輸出了請求消耗的時間和請求參數。 ## 3.6 global filter Spring Cloud Gateway根據作用范圍劃分為GatewayFilter和GlobalFilter,二者區別如下: * GatewayFilter : 需要通過spring.cloud.routes.filters 配置在具體路由下,只作用在當前路由上或通過spring.cloud.default-filters配置在全局,作用在所有路由上 * GlobalFilter : **全局過濾器,不需要在配置文件中配置,作用在所有的路由上**,最終通過GatewayFilterAdapter包裝成GatewayFilterChain可識別的過濾器,它為請求業務以及路由的URI轉換為真實業務服務的請求地址的核心過濾器,不需要配置,系統初始化時加載,并作用在每個路由上。 Spring Cloud Gateway框架內置的GlobalFilter如下: ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20190601011412503.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9mb3JlenAuYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70) 上圖中每一個GlobalFilter都作用在每一個router上,能夠滿足大多數的需求。但是如果遇到業務上的定制,可能需要編寫滿足自己需求的GlobalFilter。在下面的案例中將講述如何編寫自己GlobalFilter,該GlobalFilter會校驗請求中是否包含了請求參數“token”,如何不包含請求參數“token”則不轉發路由,否則執行正常的邏輯。代碼如下: ~~~ public class TokenFilter implements GlobalFilter, Ordered { Logger logger=LoggerFactory.getLogger( TokenFilter.class ); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getQueryParams().getFirst("token"); if (token == null || token.isEmpty()) { logger.info( "token is empty..." ); exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return -100; } } ~~~ 在上面的TokenFilter需要實現GlobalFilter和Ordered接口,這和實現GatewayFilter很類似。然后根據ServerWebExchange獲取ServerHttpRequest,然后根據ServerHttpRequest中是否含有參數token,如果沒有則完成請求,終止轉發,否則執行正常的邏輯。 然后需要將TokenFilter在工程的啟動類中注入到Spring Ioc容器中,代碼如下: ~~~java @Bean public TokenFilter tokenFilter(){ return new TokenFilter(); } ~~~ 啟動工程,使用curl命令請求: ~~~ curl localhost:8081/customer/123 ~~~ 可以看到請沒有被轉發,請求被終止,并在控制臺打印了如下日志: ~~~ 2018-11-16 15:30:13.543 INFO 19372 --- [ctor-http-nio-2] gateway.TokenFilter : token is empty... ~~~ 上面的日志顯示了請求進入了沒有傳“token”的邏輯。 ## 總結 本篇文章講述了Spring Cloud Gateway中的過濾器,包括GatewayFilter和GlobalFilter。從官方文檔的內置過濾器講起,然后講解自定義GatewayFilter、GatewayFilterFactory以及自定義的GlobalFilter。有很多內置的過濾器并沒有講述到,比如限流過濾器,這個我覺得是比較重要和大家關注的過濾器,將在之后的文章講述。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看