定制软件Spring Cloud GateWay-过滤器

定制软件说起过滤器可能有不少实现方式,比如spring定制软件自带的就可以实现

定制软件这篇文章说的是Spring Cloud GateWay-过滤器,定制软件因为由于的兴起,定制软件现在各个项目都会采用定制软件网关进行单独的资源隔离、token校验等,定制软件而不是放在下游的业务定制软件服务进行处理

Gateway 定制软件过滤器总结

filter的作用和

Zuul1.x 阻塞式IO 2.x 基于Netty,Spring Cloud GateWay定制软件天生就是异步非阻塞的,基于Reactor模型;

一个请求–>定制软件根据特定的条件匹配—>定制软件匹配成功之后可以将请定制软件求转发到指定的服务地址;定制软件在这个过程中,定制软件我们可以进行一些比较定制软件具体的控制(限流、日志、黑白名单)

路由(route): 定制软件网关最基础的部分,定制软件也是网关比较基础的工作单元。定制软件路由由多个ID、多个多标URL(定制软件最终路由到的地址)、定制软件一系列的断言(定制软件匹配条件判断)和Filter过滤器(定制软件精细化控制)组成。定制软件如果断言为true,则匹配该路由。

断言(predicates):参考了Java8中的断言java.util.function.Predicate,开发人员可以匹配Http请求中的所有内容(包括请求头、请求参数等)(类似于nginx中的location匹配),如果断言与请求相匹配则路由。

过滤器(filter):一个标准的Spring webFilter,使用过滤器,可以在请求之前或者之后执行业务逻辑

Predicates断言就是我们的匹配条件,Filter就可以理解为多个无所不能的拦截器,有了这两个元素,结合⽬标URL,就可以实现一个具体的路由转发。

作用

在微服务的上一层加一个全局的权限控制、限流、日志输出的Api Gatewat服务,然后再将请求转发到具体的业务服务层。这个Api Gateway服务就是起到一个服务边界的作用,外接的请求访问系统,必须先通过网关层。

生命周期

Spring Cloud Gateway同类似,有“pre”和“post”两种方式的filter

客户端向Spring Cloud GateWay发出请求,然后在GateWay Handler Mapping中找到与请求相匹配的路由,将其发送到GateWay Web Handler;Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或者之后(post)执行业务逻辑。

Filter在“pre”类型过滤器中可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改、日志的输出、流量监控等。

从过滤器生命周期(影响时机点)的⻆度来说,主要有两个pre和post:

  • pre:这种过滤器在请求被路由之前调用。我们可以利用这类过滤器实现身份验证、在集群中选择 请求的微服务、记录调试信息等。
  • post:这种过滤器在路由到微服务以后执行。这类过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端。

与zuul不同的是,filter除了分为“pre”和“post”两种方式的filter外,在Spring Cloud Gateway中,

从过滤器作用范围的角度来说,可分为另外两种,一种是针对于单个路由的gateway filter,它在配置文件中的写法同predict类似;另外一种是针对于所有路由的global gateway filer。现在从作用范围划分的维度来讲解这两种filter。

gateway filter

GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上。

gateway内置的filter

自定义filter

自定义过滤器工厂

在上面的自定义过滤器中,有没有办法自定义过滤器工厂类呢?这样就可以在配置文件中配置过滤器了。现在需要实现一个过滤器工厂,在打印时间的时候,可以设置参数来决定是否打印请参数。查看GatewayFilterFactory的源码,可以发现GatewayFilterfactory的层级如下:


过滤器工厂的顶级接口是GatewayFilterFactory,我们可以直接继承它的两个抽象类来简化开发AbstractGatewayFilterFactory和AbstractNameValueGatewayFilterFactory,这两个抽象类的区别就是前者接收一个参数(像StripPrefix和我们创建的这种),后者接收两个参数(像AddResponseHeader)。

过滤器工厂的顶级接口是GatewayFilterFactory,有2个两个较接近具体实现的抽象类,分别为AbstractGatewayFilterFactory和AbstractNameValueGatewayFilterFactory,这2个类前者接收一个参数,比如它的实现类RedirectToGatewayFilterFactory;后者接收2个参数,比如它的实现类AddRequestHeaderGatewayFilterFactory类。

可以参考gateway内置的Filter例如RedirectToGatewayFilterFactory的写法,

  • extends AbstractGatewayFilterFactory类,实现apply方法;
  • 需要在工程的启动文件Application类中,向Srping Ioc容器注册RequestTimeGatewayFilterFactory类的Bean;
  • 配置文件中配置,配置时只需要填写xxxGatewayFilterFactory前面的xxx;或者通过编码方式:例如:
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {        return builder.routes()                .route(r -> r.path("/serviceApi/**").filters(f -> f.filter(new MonitoringGatewayFilter()))                        .uri("lb://tag"))                .route(r -> r.path("/offline/**").filters(f -> f.filter(new MonitoringGatewayFilter()))                        .uri("lb://claimplat-offline"))                .route(r -> r.path("/test/**").filters(f -> f.filter(new MonitoringGatewayFilter()))                        .uri("lb://claimplat-offline"))                .route(r -> r.order(11000).path("/baidu")                        .filters(f -> f.addRequestHeader("x-request-uuid", UUID.randomUUID().toString())                                .filter(new MonitoringGatewayFilter()))                        .uri("https://www.baidu.com"))                .build();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

过滤器要求:

在过滤器(MyParamGatewayFilterFactory)中将http://localhost:10010/api/user/8?name=xxx中的参数name的值获取到并输出到控制台;并且参数名是可变的,也就是不一定每次都是name;需要可以通过配置过滤器的时候做到配置参数名。

1,自定义过滤器命名规则 :XXXXGatewayFilterFactory
2,创建一个静态内部类Config ,里面的属性为配置文件中配置的参数
​ - 过滤器名称=参数1,参数2…
3,extends AbstractGatewayFilterFactory<创建的静态内部类>
4,重写**shortcutFieldOrder()**方法
返回List参数列表为Config中属性集合
return Arrays.asList(“参数1”,参数2…);
5,无参构造方法中
super(Config.class);
6.编写过滤逻辑 public GatewayFilter apply(Config config)

@Overridepublic GatewayFilter apply(Config config) {    return ((exchange, chain) -> {       		//前置过滤器代码逻辑       return chain.filter(exchange);//执行请求		//后置过滤器代码逻辑   });}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意:不要重写其他方法 ,会导致异常Unable to find GatewayFilterFactory with name xxx
7.application.yml配置过滤器

filters: - MyParam=name
  • 1
  • 2

下图为 shortcutFieldOrder()方法返回的集合为Config的属性名称集合

完整代码:

@Componentpublic class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {    public MyParamGatewayFilterFactory() {        super(MyParamGatewayFilterFactory.Config.class);    }    @Override    public List<String> shortcutFieldOrder() {        return Arrays.asList("param");    }    @Override    public GatewayFilter apply(Config config) {    // 这里的config很重要指的是注册中心里面的配置,里面是key-value键值对        return ((exchange, chain) -> {            ServerHttpRequest request = exchange.getRequest();            if (request.getQueryParams().containsKey(config.param)) {                System.out.println("局部过滤器获取到的参数:" + config.param + "=" + request.getQueryParams().get(config.param).get(0));            }            return chain.filter(exchange);        });    }    public static class Config {        //对应在配置文件中配置过滤器的时候指定的参数名列表        private String param;        public String getParam() {            return param;        }        public void setParam(String param) {            this.param = param;        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

PS:这里的config很重要指的是注册中心里面的配置,里面是key-value键值对,key就是filter下面的args下面的ignorePath,value就是下面的值,所以返回是一个list集合,这个地方也就是解释了自定义网关过滤器的使用场景了,因为每个服务的制定的filter不同,那么就会有不同的过滤逻辑,如果不指定 那就使用全局过滤器,这里使用的是Hystrix

Global Filter

GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。

过滤器要求:

编写全局过滤器,在过滤器中检查请求中是否携带token请求头。如果token请求头存在则放行;如果token为空或者不存在则设置返回的状态码为:未授权也不再执行下去.

1,编写一个类 ,实现 两个接口: GlobalFilter, Ordered
GlobalFilter:全局过滤拦截器
Ordered:拦截器的顺序,数字越低,优先级越高
-----------------全局过滤器不用配置 --------------

@Componentpublic class MyGlobalFilter implements GlobalFilter,Ordered {    @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        boolean token = exchange.getRequest().getHeaders().containsKey("token");        System.out.println("----全局过滤器token----"+token);        if (!token){            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);            ServerHttpResponse response = exchange.getResponse();            return  response.setComplete();        }        return chain.filter(exchange);    }    @Override    public int getOrder() {        return 1;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

gateway内置的Global Filter

Spring Cloud Gateway框架内置的GlobalFilter如下:

自定义Global Filter

一般情况下GlobalFilter全局过滤器是程序员使用较多的过滤器;可以用来自定义一些黑名单校验、Token校验等。

步骤:

  • implements GlobalFilter, Ordered,实现filter方法;
  • 需要在工程的启动文件Application类中,向Srping Ioc容器注册GlobalFilter类的Bean;
网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发