中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何實現spring cloud 2.x版本Gateway自定義過濾器

發布時間:2021-09-29 15:50:58 來源:億速云 閱讀:132 作者:iii 欄目:大數據

本篇內容主要講解“如何實現spring cloud 2.x版本Gateway自定義過濾器”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何實現spring cloud 2.x版本Gateway自定義過濾器”吧!

前言

本文采用Spring cloud本文為2.1.8RELEASE,version=Greenwich.SR3

[toc]

本文基于前兩篇文章eureka-server、eureka-client、eureka-ribbon、eureka-feign和spring-gataway的實現。 參考

  • eureka-server

  • eureka-client

  • eureka-ribbon

  • eureka-feign

  • spring-gateway

概術

Spring Cloud Gateway內部已經提供非常多的過濾器filter,Hystrix Gateway Filter、Prefix PathGateway Filter等。感興趣的小伙伴可以直接閱讀Spring Cloud Gateway官網相關文檔或直接閱讀源碼。但是很多情況下自帶的過濾器并不能滿足我們的需求,所以自定義過濾器就顯得的非常重要。本文主要介紹全局過濾器(Global Filter)和局部過濾器(Gateway Filter)。

Gateway Filter

自定義過濾器需要實現GatewayFilter和Ordered。其中GatewayFilter主要是用來實現自定義的具體邏輯,Ordered中的getOrder()方法是來給過濾器設定優先級別的,值越大優先級別越低。

1.1 創建Filter

package spring.cloud.demo.spring.gateway.filter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

public class MyGatewayFilter implements GatewayFilter, Ordered {

    private static final Log log = LogFactory.getLog(MyGatewayFilter.class);

    private static final String TIME = "Time";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(TIME, System.currentTimeMillis());
        return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    Long start = exchange.getAttribute(TIME);
                    if (start != null) {
                        log.info("exchange request uri:" + exchange.getRequest().getURI() + ", Time:" + (System.currentTimeMillis() - start) + "ms");
                    }
                })
        );
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

我們在請求過來到達的時候,往ServerWebExchange中放了一個屬性TIME,屬性的值為當前時間的毫秒數,然后請求結束后,又會將請求的時間數取出來來和當前時間數做差,得到耗時時間數。

如何區分“pre”和“post”?

  • pre就是chain.filter(exchange)部分.

  • post就是then()部分.

1.2 將Filter添加到Chain

package spring.cloud.demo.spring.gateway.config;

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;
import spring.cloud.demo.spring.gateway.filter.MyGatewayFilter;

/**
 * @auther: fujie.feng
 * @DateT: 2019-10-12
 */
@Configuration
public class RoutesConfig {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
        return routeLocatorBuilder.routes().route(r -> r.path("/ribbon/**")
                .filters(f -> f.stripPrefix(1)
                        .filter(new MyGatewayFilter()) //增加自定義filter
                        .addRequestHeader("X-Response-Default-Foo", "Default-Bar"))
                .uri("lb://EUREKA-RIBBON")
                .order(0)
                .id("ribbon-route")
        ).build();
    }
}

1.2 啟動相關服務

啟動eureka-server、eureka-client、eureka-ribbon、spring-gateway相關服務,訪問http://localhost:8100/ribbon/sayHello地址,頁面顯示結果如下:

如何實現spring cloud 2.x版本Gateway自定義過濾器 這時我打開控制臺可以看到日志輸出為:

如何實現spring cloud 2.x版本Gateway自定義過濾器

2.1 創建GlobalFilter

package spring.cloud.demo.spring.gateway.filter;

import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


/**
 * 全局過濾器
 * 校驗token
 */
public class MyGlobalFilter implements GlobalFilter, Ordered {

    private static final String TOKEN = "token";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String parm = exchange.getRequest().getQueryParams().getFirst(TOKEN);
        if (StringUtils.isBlank(parm)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

2.2 添加Bean

將MyGlobalFilter添加到Bean中

package spring.cloud.demo.spring.gateway.filter;

import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


/**
 * 全局過濾器
 * 校驗token
 */
public class MyGlobalFilter implements GlobalFilter, Ordered {

    private static final String TOKEN = "token";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String parm = exchange.getRequest().getQueryParams().getFirst(TOKEN);
        if (StringUtils.isBlank(parm)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

這里只是簡單模擬,如果感興趣的小伙伴可以自己嘗試將所有參數取出來并解析(可以利用反射來實現)。

2.3 啟動服務

重啟動服務,訪問http://localhost:8100/ribbon/sayHello,顯示如下: 如何實現spring cloud 2.x版本Gateway自定義過濾器 我可以看到顯示訪問是不生效的,我們在請求中加如token=xxx,顯示如下: 如何實現spring cloud 2.x版本Gateway自定義過濾器 這是看到正常返回。日志輸出入下:

2019-10-21 16:20:00.478  INFO 15322 --- [ctor-http-nio-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-10-21 16:20:00.480  INFO 15322 --- [ctor-http-nio-2] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client EUREKA-RIBBON initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=EUREKA-RIBBON,current list of Servers=[eureka1.server.com:8901],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:1;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:eureka1.server.com:8901;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 CST 1970;	First connection made: Thu Jan 01 08:00:00 CST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@40585976
2019-10-21 16:20:01.293  INFO 15322 --- [ctor-http-nio-8] s.c.d.s.gateway.filter.MyGatewayFilter   : exchange request uri:http://localhost:8100/sayHello?token=xxx, Time:23ms
2019-10-21 16:20:01.467  INFO 15322 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

引用官網原文:The GlobalFilter interface has the same signature as GatewayFilter. These are special filters that are conditionally applied to all routes. (This interface and usage are subject to change in future milestones). 說明GlobalFilter在未來的版本中會又一些變化。

總結

至此,自定義filter的兩種方式就簡單的實現完成了。同樣的方式可以在feign做測試。

彩蛋

在前一片文章中,配置文件中有這樣一段配置:

filters:
  - StripPrefix=1
  - AddResponseHeader=X-Response-Default-Foo, Default-Bar

StripPrefix和AddResponseHeader這兩個配置實際上是兩個Filter的過濾器工廠(GatewayFilterFactory),接下來將介紹過濾器工廠的使用,相對來說這種方式更加靈活。

1.1 創建自定義過濾工廠

package spring.cloud.demo.spring.gateway.factory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

/**
 * 自定義過濾器工廠
 */
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {

    private static final Log log = LogFactory.getLog(MyGatewayFilterFactory.class);

    private static final String PARAMS = "myParams";

    private static final String START_TIME = "startTime";

    public MyGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(PARAMS);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return ((exchange, chain) -> {
            exchange.getAttributes().put(START_TIME, System.currentTimeMillis());
            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {
                        Long startTime = exchange.getAttribute(START_TIME);
                        if (startTime == null) {
                            return;
                        }
                        StringBuilder sb = new StringBuilder();
                        sb.append("exchange request uri:" + exchange.getRequest().getURI() + ",");
                        sb.append("Time:" + (System.currentTimeMillis() - startTime) + "ms.");
                        if (config.isMyParams()) {
                            sb.append("params:" + exchange.getRequest().getQueryParams());
                        }
                        log.info(sb.toString());
                    })
            );
        });
    }

    /**
     * 配置參數類
     */
    public static class Config {

        private boolean myParams;

        public boolean isMyParams() {
            return myParams;
        }

        public void setMyParams(boolean myParams) {
            this.myParams = myParams;
        }
    }
}

注意:當我們繼承AbstractGatewayFilterFactory的時候,要把自定義的Config類傳給父類,否者會報錯。

1.2 添加自定義工廠Bean

package spring.cloud.demo.spring.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import spring.cloud.demo.spring.gateway.factory.MyGatewayFilterFactory;

@Configuration
public class FilterFactory {

    @Bean
    public MyGatewayFilterFactory myGatewayFilterFactory() {
        return new MyGatewayFilterFactory();
    }
}

1.3 修改application.yml

server:
  port: 8100
spring:
  application:
    name: spring-gateway
  cloud:
      gateway:
        discovery:
          locator:
            enabled: true # 開啟通過服務中心的自動根據 serviceId 創建路由的功能
        default-filters:
          - My=true
        routes:
          - id: ribbon-route
            uri: lb://EUREKA-RIBBON
            order: 0
            predicates:
              - Path=/ribbon/**
            filters:
              - StripPrefix=1 #去掉前綴,具體實現參考StripPrefixGatewayFilterFactory
              - AddResponseHeader=X-Response-Default-Foo, Default-Bar
          - id: feign-route
            uri: lb://EUREKA-FEIGN
            order: 0
            predicates:
              - Path=/feign/**
            filters:
              - StripPrefix=1
              - AddResponseHeader=X-Response-Default-Foo, Default-Bar


eureka:
  instance:
    hostname: eureka1.server.com
    lease-renewal-interval-in-seconds: 5
    lease-expiration-duration-in-seconds: 10
  client:
    service-url:
      defaultZone: http://eureka1.server.com:8701/eureka/,http://eureka2.server.com:8702/eureka/,http://eureka3.server.com:8703/eureka/

default-filters:- My=true 主要增加了這個配置。

1.4 啟動服務

訪問http://localhost:8100/ribbon/sayHello?token=xxx,顯示如果下: 如何實現spring cloud 2.x版本Gateway自定義過濾器 日志輸出結果:

2019-10-21 17:40:20.191  INFO 18059 --- [ctor-http-nio-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-10-21 17:40:20.192  INFO 18059 --- [ctor-http-nio-2] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client EUREKA-RIBBON initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=EUREKA-RIBBON,current list of Servers=[eureka1.server.com:8901],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:1;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:eureka1.server.com:8901;	Zone:defaultZone;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 CST 1970;	First connection made: Thu Jan 01 08:00:00 CST 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@46c172ce
2019-10-21 17:40:20.583  INFO 18059 --- [ctor-http-nio-7] s.c.d.s.g.f.MyGatewayFilterFactory       : exchange request uri:http://localhost:8100/ribbon/sayHello?token=xxx,Time:582ms.params:{token=[xxx]}
2019-10-21 17:40:21.181  INFO 18059 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

總結

過濾器工廠的頂級的接口是GatewayFilterFactory,我們可以直接繼承它們的兩個抽象類AbstractGatewayFilterFactory 和 AbstractNameValueGatewayFilterFactory來簡化開發。區別在于AbstractGatewayFilterFactory是接受一個參數,AbstractNameValueGatewayFilterFactory是接收兩個參數,例如:- AddResponseHeader=X-Response-Default-Foo, Default-Bar

到此,相信大家對“如何實現spring cloud 2.x版本Gateway自定義過濾器”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

神木县| 察隅县| 紫阳县| 宝清县| 延庆县| 思南县| 精河县| 阿坝县| 象山县| 于田县| 成都市| 秀山| 日照市| 大宁县| 寿光市| 嵊泗县| 镇康县| 乌拉特中旗| 遂平县| 新和县| 周宁县| 上思县| 桑日县| 唐海县| 宁武县| 青田县| 五大连池市| 陆丰市| 宜城市| 乐亭县| 辛集市| 资源县| 突泉县| 波密县| 谷城县| 时尚| 黄冈市| 呼和浩特市| 泽普县| 盘锦市| 石河子市|