【Hoxton.SR1版本】Spring Cloud Gateway之Filter详解

目录

一、简介

二、常用的Gateway Filter详解

三、自定义过滤器

四、自定义过滤器工厂

五、总结


一、简介

上一篇文章我们对Gateway Predicate进行了详细的介绍,我们再来看下官网对Predicate的描述:Predict断言决定了请求由哪一个路由处理,在路由处理之前,需要经过“pre”类型的前置过滤器处理,处理返回响应之后,可以由“post”类型的后置过滤器处理。

由上图可以看到,在Predicate断言之后,会经过过滤器链,我们可以在过滤器中对请求或者响应进行修改,如添加请求头、响应头等等。

  • Filter作用

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

举例:

假设有订单服务、支付服务、商品服务三个微服务,我们有一个需求就是记录所有请求的执行时间,可想而知,每个微服务都需要做相同的事情,这显然不太好,那么由于在微服务中所有的请求都必须经过网关进行路由转发,其实我们可以将记录请求时间统一放在网关服务进行处理,这样就很大程度上减少了每个微服务中重复的代码,也利于维护。

  • Filter声明周期 

如果了解过Spring Cloud Zuul旧版本网关的小伙伴应该知道,ZuulFilter中有下面四个方法:

  • boolean shouldFilter():过滤器是否放行
  • Object run():过滤器业务执行主体方法
  • String filterType():过滤器的类型,支持pre和post
  • filterOrder():过滤器执行的顺序

在Spring Cloud Gateway新网关中,Filter同样支持 "pre" 和 "post" 两种方式的filter。客户端的请求先经过 "pre"类型的filter,然后将请求转发到具体的业务服务,收到业务服务的响应之后,再经过 "post" 类型的filter处理,最后返回响应到客户端。

二、常用的Gateway Filter详解

Spring Cloud Gateway Filter官网地址:https://docs.spring.io/spring-cloud-gateway/docs/2.2.4.RELEASE/reference/html/#gatewayfilter-factories

可以看到,Spring Cloud官网提供了多达30种过滤器工厂之多:

下面我们挑选一些比较常用的过滤器工厂进行详解的讲解,在这之前,由于applicaiton.yml上一篇文章对Predicate断言的配置过多,这里我们新建一个module【springcloud-apigateway-gateway9528】专门用来针对Filter进行讲解,除了端口,其他具体的配置跟【springcloud-apigateway-gateway9527】一模一样,这里不再过多阐述。

(一)、The AddRequestHeader GatewayFilter Factory:添加请求头过滤器工厂

【a】payment服务提供者增加如下方法

/**
     * 测试gateway网关转发指定地址并添加请求头信息
     */
    @GetMapping("/gatewayAddRequestHeader")
    public String gatewayAddRequestHeader(HttpServletRequest request) {
        String value = request.getHeader("X-Request-red");
        return "hello, [gatewayAddRequestHeader] the header[X-Request-red] is :" + value;
    }

【b】application.yml配置

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue


      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【c】测试

浏览器访问:http://localhost:9528/gatewayAddRequestHeader

可见,下游服务payment成功获取到网关gateway增加的请求头信息[X-Request-red]的值。

 

(二)、The AddRequestParameter GatewayFilter Factory:添加请求参数过滤器工厂

【a】payment服务提供者增加如下方法

/**
     * 测试gateway网关转发指定地址并添加请求参数
     */
    @GetMapping("/gatewayAddRequestParameter")
    public String gatewayAddRequestParameter(HttpServletRequest request) {
        String name = request.getParameter("name");
        return "hello, [gatewayAddRequestParameter] the name is :" + name;
    }

【b】application.yml配置

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

      ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai



      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【c】测试

浏览器访问:http://localhost:9528/gatewayAddRequestParameter

可见,下游服务payment成功获取到网关gateway添加的请求参数信息,注意是Get请求。

 

(三)、The AddResponseHeader GatewayFilter Factory:添加响应头过滤器工厂

【a】payment服务提供者增加如下方法

    /**
     * 测试gateway网关转发指定地址并添加响应头
     */
    @GetMapping("/gatewayAddResponseHeader")
    public String gatewayAddResponseHeader() {
        return "hello, [gatewayAddResponseHeader] ";
    }

【b】application.yml配置

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

        ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai

        ########################################【AddResponseHeader GatewayFilter添加响应头】######################################################
        - id: payment_service8001_gatewayAddResponseHeader #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddResponseHeader
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddResponseHeader=X-Response-Red, Blue



      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【c】测试

浏览器访问:http://localhost:9528/gatewayAddResponseHeader

可见,gateway网关成功添加响应头到下游服务中。

 

(四)、The Hystrix GatewayFilter Factory 断路器过滤器工厂

Hystrix是来自Netflix的一个实现断路器模式的库。Hystrix GatewayFilter允许您为网关路由引入断路器,保护您的服务免受级联故障的影响,并允许您在发生下游故障时提供回退响应。

如果要在项目中启用Hystrix GatewayFilters,请在Spring Cloud Netflix上添加对spring-cloud-starter-netflix-hystrix的依赖关系。

Hystrix GatewayFilter Factory需要单个名称参数,该参数是HystrixCommand的名称。Hystrix过滤器还可以接受可选的fallbackUri参数。 目前,仅支持forward:schemed URIs。 如果调用了回退,请求将被转发到与URI匹配的控制器。

【a】网关服务添加Hystrix依赖

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

【b】主启动类开启断路器功能

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class GateWayServiceApplication9528 {
    public static void main(String[] args) {
        SpringApplication.run(GateWayServiceApplication9528.class, args);
    }
}

【c】payment服务提供者增加如下方法

 /**
     * 测试gateway网关断路器过滤器
     */
    @GetMapping("/gatewayHystrixGatewayFilter")
    public String gatewayHystrixGatewayFilter() {
        return "hello, [gatewayHystrixGatewayFilter] ";
    }

【d】添加网关fallback controller

package com.wsh.springcloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description: 过滤器失败回调Controller
 * @author: weishihuai
 * @Date: 2020/8/21 10:50
 */
@RestController
public class GatewayFallbackController {

    @GetMapping("/fallback")
    public String gatewayFallback() {
        return "sorry, gateway service is busy,please try again later!";
    }

}

【e】application.yml配置

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

        ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai

        ########################################【AddResponseHeader GatewayFilter添加响应头】######################################################
        - id: payment_service8001_gatewayAddResponseHeader #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddResponseHeader
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddResponseHeader=X-Response-Red, Blue

        ########################################【Hystrix GatewayFilter断路器】######################################################
        - id: payment_service8001_gatewayHystrixGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback



      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【f】测试

启动项目,浏览器访问:http://localhost:9528/gatewayHystrixGatewayFilter

可见,路由成功转发。下面我们停掉payment8001服务提供者,再次访问http://localhost:9528/gatewayHystrixGatewayFilter

可见,网关走了失败回调的方法localhost:9528/fallback的逻辑。上述示例是将fallbackUri用于网关应用程序内的内部控制器或处理程序。 但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示: 

【a】payment8001增加如下方法

 /**
     * 外部网关失败回调
     */
    @GetMapping("/gatewayFallback")
    public String gatewayFallback() {
        return "sorry,this is outer gateway fallback ";
    }

    /**
     * 外部网关失败回调
     */
    @GetMapping("/gatewayOuterFallbackHystrixGatewayFilter")
    public String gatewayOuterFallbackHystrixGatewayFilter() {
        return "hello,[gatewayOuterFallbackHystrixGatewayFilter]";
    }

【a】application.yml调整

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

        ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai

        ########################################【AddResponseHeader GatewayFilter添加响应头】######################################################
        - id: payment_service8001_gatewayAddResponseHeader #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddResponseHeader
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddResponseHeader=X-Response-Red, Blue

        ########################################【Hystrix GatewayFilter断路器】######################################################
        - id: payment_service8001_gatewayHystrixGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

        - id: payment_service8001_outerFallback-gatewayHystrix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayOuterFallbackHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/gatewayFallback  #此处需要与下面- Path=/gatewayFallback对应
        - id: outer-gateway-fallback
          uri: http://localhost:8001
          predicates:
            #fallback时调用的方法 http://localhost:8001/gatewayFallback
            - Path=/gatewayFallback


      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【c】测试 

正常启动项目,浏览器访问:http://localhost:9528/gatewayOuterFallbackHystrixGatewayFilter

可见,网关成功进行路由转发。下面我们手动触发网关熔断,稍微修改一下,加入休眠10秒钟。

 /**
     * 外部网关失败回调
     */
    @GetMapping("/gatewayOuterFallbackHystrixGatewayFilter")
    public String gatewayOuterFallbackHystrixGatewayFilter() throws InterruptedException {
        //手动触发网关超时熔断
        TimeUnit.SECONDS.sleep(10);
        return "hello,[gatewayOuterFallbackHystrixGatewayFilter]";
    }

重启项目,再次访问:http://localhost:9528/gatewayOuterFallbackHystrixGatewayFilter

可见,已经将网关的失败回调重新路由到外部应用程序中【此处是localhost:8001/gatewayFallback】的控制器或处理程序。

在此示例中,网关应用程序中没有/gatewayFallback回调端点或处理程序,但是,在http://localhost:8001应用程序中有一个gatewayFallback失败回调。

如果请求被转发到回调地址时,Hystrix网关过滤器还会提供导致它的Throwable。 它作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR属性添加到ServerWebExchange中,可以在处理网关应用程序中的回退时使用该属性。

对于外部控制器/处理程序方案,可以添加包含异常详细信息的标头。 您可以在FallbackHeaders GatewayFilter Factory部分中找到有关它的更多信息。

 

(五)、The PrefixPath GatewayFilter Factory路由前缀过滤器工厂

PrefixPath网关过滤器工厂接受一个前缀参数。下面的例子配置了一个前缀路径网关过滤器:

【a】payment服务提供者增加如下方法

/**
     * 测试路径前缀网关过滤器工厂
     */
    @GetMapping("/api/prefixPathGatewayFilter")
    public String prefixPathGatewayFilter() {
        return "hello,[prefixPathGatewayFilter]";
    }

【b】application.yml配置

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

        ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai

        ########################################【AddResponseHeader GatewayFilter添加响应头】######################################################
        - id: payment_service8001_gatewayAddResponseHeader #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddResponseHeader
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddResponseHeader=X-Response-Red, Blue

        ########################################【Hystrix GatewayFilter断路器】######################################################
        - id: payment_service8001_gatewayHystrixGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

        - id: payment_service8001_outerFallback-gatewayHystrix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayOuterFallbackHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/gatewayFallback  #此处需要与下面- Path=/gatewayFallback对应
        - id: outer-gateway-fallback
          uri: http://localhost:8001
          predicates:
            #fallback时调用的方法 http://localhost:8001/gatewayFallback
            - Path=/gatewayFallback

        ########################################【PrefixPath  GatewayFilter路径前缀过滤器工厂】######################################################
        - id: payment_service8001_prefixPathGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/prefixPathGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            #将把/api作为所有匹配请求的路径的前缀。因此,对/prefixPathGatewayFilter的请求将被发送到/api/prefixPathGatewayFilter
            - PrefixPath=/api

      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【c】测试

浏览器访问:http://localhost:9528/prefixPathGatewayFilter

可见,虽然访问的地址是http://localhost:9528/prefixPathGatewayFilter,但是网关转发的时候,加了一个路径前缀/api,真正请求的接口应该是http://localhost:8001/api/prefixPathGatewayFilter

 

(六)、 The StripPrefix GatewayFilter Factory 路由截取过滤器工厂

StripPrefix网关过滤器工厂接受一个参数,parts。parts参数指示在将请求发送到下游之前,路径中要从请求中URL截取的位数。下面的示例配置了一个StripPrefix网关过滤器:

【a】payment服务提供者增加如下方法

/**
     * 测试gateway网关截取请求
     */
    @GetMapping("/gatewayStripPrefix/{name}")
    public String gatewayStripPrefix(@PathVariable("name") String name) {
        return "hello, [gatewayStripPrefix] the name is :" + name + ", the server port is " + serverPort;
    }

【b】application.yml配置

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

        ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai

        ########################################【AddResponseHeader GatewayFilter添加响应头】######################################################
        - id: payment_service8001_gatewayAddResponseHeader #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddResponseHeader
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddResponseHeader=X-Response-Red, Blue

        ########################################【Hystrix GatewayFilter断路器】######################################################
        - id: payment_service8001_gatewayHystrixGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

        - id: payment_service8001_outerFallback-gatewayHystrix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayOuterFallbackHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/gatewayFallback  #此处需要与下面- Path=/gatewayFallback对应
        - id: outer-gateway-fallback
          uri: http://localhost:8001
          predicates:
            #fallback时调用的方法 http://localhost:8001/gatewayFallback
            - Path=/gatewayFallback

        ########################################【PrefixPath  GatewayFilter路径前缀过滤器工厂】######################################################
        - id: payment_service8001_prefixPathGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/prefixPathGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            #将把/api作为所有匹配请求的路径的前缀。因此,对/prefixPathGatewayFilter的请求将被发送到/api/prefixPathGatewayFilter
            - PrefixPath=/api

        ########################################【StripPrefix GatewayFilter Factory路径截取过滤器工厂】######################################################
        #如下配置表示,在访问localhost:9528/api/gatewayStripPrefix/**请求的,gateway网关将/api截取掉,请求分发到http://localhost:8001中去.
        - id: payment_service8001_gatewayStripPrefix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            # 转发地址格式为 uri/gatewayStripPrefix, /api 部分会被下面的过滤器给截取掉.
            - Path=/api/gatewayStripPrefix/**
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 截取路径位数  即截取/api
            - StripPrefix=1

      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【c】测试

浏览器访问:http://localhost:9528/api/gatewayStripPrefix/weishihuai

可见,网关转发请求的时候,截取了/api,真正访问到下游服务中的地址为:http://localhost:8001/gatewayStripPrefix/weishihuai

 

(七)、The RewritePath GatewayFilter Factory路由重写过滤器工厂

RewritePath GatewayFilter工厂接受一个路径regexp参数和一个替换参数。它使用Java正则表达式以一种灵活的方式重写请求路径。下面的清单配置了一个RewritePath网关过滤器:

【a】payment服务提供者增加如下方法

 /**
     * 测试路径重写网关过滤器工厂
     */
    @GetMapping("/api/rewritePathGatewayFilter")
    public String rewritePathGatewayFilter() {
        return "hello, [rewritePathGatewayFilter]";
    }

【b】application.yml配置

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

        ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai

        ########################################【AddResponseHeader GatewayFilter添加响应头】######################################################
        - id: payment_service8001_gatewayAddResponseHeader #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddResponseHeader
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddResponseHeader=X-Response-Red, Blue

        ########################################【Hystrix GatewayFilter断路器】######################################################
        - id: payment_service8001_gatewayHystrixGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

        - id: payment_service8001_outerFallback-gatewayHystrix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayOuterFallbackHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/gatewayFallback  #此处需要与下面- Path=/gatewayFallback对应
        - id: outer-gateway-fallback
          uri: http://localhost:8001
          predicates:
            #fallback时调用的方法 http://localhost:8001/gatewayFallback
            - Path=/gatewayFallback

        ########################################【PrefixPath  GatewayFilter路径前缀过滤器工厂】######################################################
        - id: payment_service8001_prefixPathGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/prefixPathGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            #将把/api作为所有匹配请求的路径的前缀。因此,对/prefixPathGatewayFilter的请求将被发送到/api/prefixPathGatewayFilter
            - PrefixPath=/api

        ########################################【StripPrefix GatewayFilter Factory路径截取过滤器工厂】######################################################
        #如下配置表示,在访问localhost:9528/api/gatewayStripPrefix/**请求的,gateway网关将/api截取掉,请求分发到http://localhost:8001中去.
        - id: payment_service8001_gatewayStripPrefix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            # 转发地址格式为 uri/gatewayStripPrefix, /api 部分会被下面的过滤器给截取掉.
            - Path=/api/gatewayStripPrefix/**
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 截取路径位数  即截取/api
            - StripPrefix=1

        ########################################【RewritePath GatewayFilter Factory路径截取过滤器工厂】######################################################
        #如下配置表示,在访问localhost:9528/api/rewritePathGatewayFilter/**请求的,gateway网关将路径重写为localhost:9528/rewritePathGatewayFilter,然后请求分发到http://localhost:8001中去.
        - id: payment_service8001_rewritePathGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/api/rewritePathGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - RewritePath=/api(?<segment>/?.*), $\{segment}

      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


对于/api/rewritePathGatewayFilter的请求路径,这将在发出下游请求之前将路径设置为/rewritePathGatewayFilter。注意,由于YAML规范,$应该被替换为$\。

【c】测试

浏览器访问:http://localhost:9528/api/rewritePathGatewayFilter

可见,网关在转发路由到下游服务的时候,成功重写了路径。

前面介绍了七种常用的Filter Factory,官网还有很多种,由于时间关系,这里不再一一列举,有兴趣的小伙伴可以前往官网按照示例一点一点尝试。 

三、自定义过滤器

Spring Cloud Gateway内置了19种强大的过滤器工厂,能够满足很多场景的需求,那么能不能自定义自己的过滤器呢,当然是可以的。在spring Cloud Gateway中,过滤器需要实现GatewayFilter和Ordered 2个接口。

下面通过两个示例说明如何在Gateway网关中自定义过滤器。

(一)、简单的token验证过滤器

【a】payment8001增加如下方法

/**
     * 测试自定义权限网关过滤器
     */
    @GetMapping("/customAuthFilter/{name}")
    public String customAuthFilter(@PathVariable("name") String name) {
        return "hello, [customAuthFilter] the name is :" + name + ", the server port is " + serverPort;
    }

【b】自定义权限校验过滤器

package com.wsh.springcloud.filter;

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

/**
 * @version V1.0
 * @ClassName: com.wsh.springcloud.filter.CustomAuthFilter.java
 * @Description: 自定义权限校验过滤器
 * @author: weishihuai
 * @date: 2020/8/21 15:55
 * 说明: 判断请求头中是否存在token信息,如果
 */
public class CustomAuthFilter implements GatewayFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求头中的token
        String token = exchange.getRequest().getHeaders().getFirst("token");
        if (StringUtils.isNotBlank(token)) {
            //执行下一个过滤器
            return chain.filter(exchange);
        } else {
            //token为空,结束
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
    }

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

【c】将自定义过滤器添加到Gateway Filter Factories工厂中。

注意: CustomAuthGatewayFilterFactory符合xxxGatewayFilterFactory中的 "CustomAuth" 即为配置文件application.yml的名称。

package com.wsh.springcloud.filter.factory;

import com.wsh.springcloud.filter.CustomAuthFilter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;

/**
 * @Description 过滤器工厂
 * @Date 2020/8/21 20:40
 * @Author weishihuai
 * 说明:
 */
@Component
public class CustomAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
    @Override
    public GatewayFilter apply(Object config) {
        return new CustomAuthFilter();
    }
}

【d】application.yml中配置过滤器工厂

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

        ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai

        ########################################【AddResponseHeader GatewayFilter添加响应头】######################################################
        - id: payment_service8001_gatewayAddResponseHeader #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddResponseHeader
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddResponseHeader=X-Response-Red, Blue

        ########################################【Hystrix GatewayFilter断路器】######################################################
        - id: payment_service8001_gatewayHystrixGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

        - id: payment_service8001_outerFallback-gatewayHystrix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayOuterFallbackHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/gatewayFallback  #此处需要与下面- Path=/gatewayFallback对应
        - id: outer-gateway-fallback
          uri: http://localhost:8001
          predicates:
            #fallback时调用的方法 http://localhost:8001/gatewayFallback
            - Path=/gatewayFallback

        ########################################【PrefixPath  GatewayFilter路径前缀过滤器工厂】######################################################
        - id: payment_service8001_prefixPathGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/prefixPathGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            #将把/api作为所有匹配请求的路径的前缀。因此,对/prefixPathGatewayFilter的请求将被发送到/api/prefixPathGatewayFilter
            - PrefixPath=/api

        ########################################【StripPrefix GatewayFilter Factory路径截取过滤器工厂】######################################################
        #如下配置表示,在访问localhost:9528/api/gatewayStripPrefix/**请求的,gateway网关将/api截取掉,请求分发到http://localhost:8001中去.
        - id: payment_service8001_gatewayStripPrefix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            # 转发地址格式为 uri/gatewayStripPrefix, /api 部分会被下面的过滤器给截取掉.
            - Path=/api/gatewayStripPrefix/**
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 截取路径位数  即截取/api
            - StripPrefix=1

        ########################################【RewritePath GatewayFilter Factory路径截取过滤器工厂】######################################################
        #如下配置表示,在访问localhost:9528/api/rewritePathGatewayFilter/**请求的,gateway网关将路径重写为localhost:9528/rewritePathGatewayFilter,然后请求分发到http://localhost:8001中去.
        - id: payment_service8001_rewritePathGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/api/rewritePathGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - RewritePath=/api(?<segment>/?.*), $\{segment}

        ##########################################【测试自定义权限过滤器】#################################################
        - id: payment_service8001_customAuthFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/customAuthFilter/**
          filters:  #过滤器(filters:过滤器,过滤规则)
            - CustomAuth

      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【e】测试

启动项目,这里使用postman进行测试:

由上可见,只有请求头中携带了token参数,权限过滤器才会放行,否则返回错误代码。

 

(二)、记录请求时间的过滤器

【a】payment8001增加如下方法

/**
     * 测试记录请求时间过滤器
     */
    @GetMapping("/customRequestTimeFilter")
    public String customRequestTimeFilter(HttpServletRequest request) {
        String name = request.getParameter("name");
        return "hello, [customRequestTimeFilter], 接收到的请求参数name:" + name;
    }

【b】自定义请求时间积累过滤器

package com.wsh.springcloud.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;

/**
 * @Description: 自定义请求时间记录过滤器
 * @author: weishihuai
 * @Date: 2020/8/21 15:27
 */
public class CustomRequestTimeFilter implements GatewayFilter, Ordered {

    private static final Logger logger = LoggerFactory.getLogger(CustomRequestTimeFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String rawPath = exchange.getRequest().getURI().getRawPath();
        logger.info(rawPath + "-----------pre前置处理----------");
        long startTime = System.currentTimeMillis();

        return chain.filter(exchange).then().then(
                Mono.fromRunnable(() -> {
                    long endTime = System.currentTimeMillis();
                    logger.info(rawPath + "-----------post后置处理----------");
                    logger.info(exchange.getRequest().getURI().getRawPath() + "----> 耗时: " + (endTime - startTime) + "ms");
                })
        );
    }

    /**
     * 定义过滤器执行的顺序
     */
    @Override
    public int getOrder() {
        return 0;
    }

}

【c】自定义RouteLocator 路由定位器配置:将自定义请求过滤器配置到某个请求上。

package com.wsh.springcloud.config;

import com.wsh.springcloud.filter.CustomRequestTimeFilter;
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;

/**
 * @version V1.0
 * @ClassName: com.wsh.springcloud.config.CustomRouteLocatorConfig.java
 * @Description: 自定义路由定位器配置
 * @author: weishihuai
 * @date: 2020/8/21 15:41
 */
@Configuration
public class CustomRouteLocatorConfig {

    @Bean
    public RouteLocator routes(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("payment8001_customRequestTimeFilter",     //路由ID
                r -> r.path("/customRequestTimeFilter/**")  //路由路径正则表达式
                        .filters(f -> f.filter(new CustomRequestTimeFilter())  //自定义请求时间记录过滤器
                                .addRequestParameter("name", "weishihuai"))   //添加请求参数
                        .uri("http://localhost:8001")   //跳转目标服务地址
                        .order(0)
        ).build();
        return routes.build();
    }

}

【d】测试

启动项目,浏览器访问:http://localhost:9528/customRequestTimeFilter

查看后台日志:

2020-08-21 21:09:41.471  INFO 10136 --- [ctor-http-nio-1] c.w.s.filter.CustomRequestTimeFilter     : /customRequestTimeFilter-----------pre前置处理----------
2020-08-21 21:09:41.486  INFO 10136 --- [ctor-http-nio-1] c.w.s.filter.CustomRequestTimeFilter     : /customRequestTimeFilter-----------post后置处理----------
2020-08-21 21:09:41.486  INFO 10136 --- [ctor-http-nio-1] c.w.s.filter.CustomRequestTimeFilter     : /customRequestTimeFilter----> 耗时: 15ms

可见,成功实现了记录某个接口的请求时间功能,建议在项目中将此过滤器配置为全局过滤器,毕竟所有请求都可以进行记录。 

四、自定义过滤器工厂

其实,在Gateway中除了能自定义过滤器之外,还支持自定义过滤器工厂类,这样的话我们就可以在配置文件中配置过滤器了。

过滤器工厂的顶级接口是GatewayFilterFactory,有2个两个较接近具体实现的抽象类:

  • AbstractGatewayFilterFactory
  • AbstractNameValueGatewayFilterFactory

这2个类前者接收一个参数,比如它的实现类RedirectToGatewayFilterFactory;后者接收2个参数,比如它的实现类AddRequestHeaderGatewayFilterFactory类。

下面我们实现一个过滤器工厂,在记录请求时间的时候,可以设置参数来决定是否打印请求参数。

【a】自定义过滤器工厂

package com.wsh.springcloud.filter.factory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.List;

/**
 * @Description 自定义请求时间过滤器工厂
 * @Date 2020/8/21 21:27
 * @Author weishihuai
 * 说明:
 */
public class CustomRequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomRequestTimeGatewayFilterFactory.Config> {

    private static final Logger logger = LoggerFactory.getLogger(CustomRequestTimeGatewayFilterFactory.class);

    public static final String SHOULD_PARAMS = "shouldParams";

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

    public List<String> shortcutFieldOrder() {
        return Collections.singletonList(SHOULD_PARAMS);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String rawPath = exchange.getRequest().getURI().getRawPath();
            logger.info(rawPath + "-----------pre前置处理----------");
            long startTime = System.currentTimeMillis();
            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {
                        long endTime = System.currentTimeMillis();
                        logger.info(rawPath + "-----------post后置处理----------");
                        StringBuilder sb = new StringBuilder(rawPath)
                                .append("--------> 耗时: ")
                                .append(endTime - startTime)
                                .append("ms");
                        if (config.isShouldParams()) {
                            sb.append(",请求参数:").append(exchange.getRequest().getQueryParams());
                        }
                        logger.info(sb.toString());
                    })
            );
        };
    }

    public static class Config {
        /**
         * 是否输出参数
         */
        boolean shouldParams;

        public Config() {
        }

        public boolean isShouldParams() {
            return shouldParams;
        }

        public void setShouldParams(boolean shouldParams) {
            this.shouldParams = shouldParams;
        }
    }

}

在上面的代码中 apply(Config config)方法内创建了一个GatewayFilter的匿名类,具体的实现逻辑跟之前一样,只不过加了是否打印请求参数的逻辑,而这个逻辑的开关是config.isShouldParams()。静态内部类类Config就是为了接收那个boolean类型的参数服务的,变量名可以随意写,但是要重写List shortcutFieldOrder()这个方法。需要注意的是,在类的构造器中一定要调用下父类的构造器把Config类型传过去,否则会报ClassCastException。

【b】将过滤器工厂注入IOC容器中

package com.wsh.springcloud.config;

import com.wsh.springcloud.filter.factory.CustomRequestTimeGatewayFilterFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description 注册自定义过滤器工厂
 * @Date 2020/8/21 21:37
 * @Author weishihuai
 * 说明:
 */
@Configuration
public class CustomRequestTimeGatewayFilterFactoryConfig {
    @Bean
    public CustomRequestTimeGatewayFilterFactory customRequestTimeGatewayFilterFactory() {
        return new CustomRequestTimeGatewayFilterFactory();
    }
}

【c】payment8001增加如下方法

 /**
     * 测试自定义过滤器工厂
     */
    @GetMapping("/customGatewayFilterFactory/{name}")
    public String customGatewayFilterFactory(@PathVariable("name") String name) {
        return "hello, [customGatewayFilterFactory] the name is :" + name + ", the server port is " + serverPort;
    }

【d】application.yml中加入如下配置

server:
  port: 9528
spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      routes:
        ########################################【AddRequestHeader GatewayFilter添加请求头】######################################################
        - id: payment_service8001_gatewayAddRequestHeader  #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestHeader/**
          filters:
            #将X-Request-red:blue头添加到所有匹配请求的下游请求头中
            - AddRequestHeader=X-Request-red, blue

        ########################################【AddRequestParameter GatewayFilter添加请求参数】######################################################
        - id: payment_service8001_gatewayAddRequestParameter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddRequestParameter
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddRequestParameter=name, weishihuai

        ########################################【AddResponseHeader GatewayFilter添加响应头】######################################################
        - id: payment_service8001_gatewayAddResponseHeader #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayAddResponseHeader
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 添加指定参数
            - AddResponseHeader=X-Response-Red, Blue

        ########################################【Hystrix GatewayFilter断路器】######################################################
        - id: payment_service8001_gatewayHystrixGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback

        - id: payment_service8001_outerFallback-gatewayHystrix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/gatewayOuterFallbackHystrixGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/gatewayFallback  #此处需要与下面- Path=/gatewayFallback对应
        - id: outer-gateway-fallback
          uri: http://localhost:8001
          predicates:
            #fallback时调用的方法 http://localhost:8001/gatewayFallback
            - Path=/gatewayFallback

        ########################################【PrefixPath  GatewayFilter路径前缀过滤器工厂】######################################################
        - id: payment_service8001_prefixPathGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/prefixPathGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            #将把/api作为所有匹配请求的路径的前缀。因此,对/prefixPathGatewayFilter的请求将被发送到/api/prefixPathGatewayFilter
            - PrefixPath=/api

        ########################################【StripPrefix GatewayFilter Factory路径截取过滤器工厂】######################################################
        #如下配置表示,在访问localhost:9528/api/gatewayStripPrefix/**请求的,gateway网关将/api截取掉,请求分发到http://localhost:8001中去.
        - id: payment_service8001_gatewayStripPrefix #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            # 转发地址格式为 uri/gatewayStripPrefix, /api 部分会被下面的过滤器给截取掉.
            - Path=/api/gatewayStripPrefix/**
          filters:  #过滤器(filters:过滤器,过滤规则)
            # 截取路径位数  即截取/api
            - StripPrefix=1

        ########################################【RewritePath GatewayFilter Factory路径截取过滤器工厂】######################################################
        #如下配置表示,在访问localhost:9528/api/rewritePathGatewayFilter/**请求的,gateway网关将路径重写为localhost:9528/rewritePathGatewayFilter,然后请求分发到http://localhost:8001中去.
        - id: payment_service8001_rewritePathGatewayFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/api/rewritePathGatewayFilter
          filters:  #过滤器(filters:过滤器,过滤规则)
            - RewritePath=/api(?<segment>/?.*), $\{segment}

        ##########################################【测试自定义权限过滤器】#################################################
        - id: payment_service8001_customAuthFilter #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/customAuthFilter/**
          filters:  #过滤器(filters:过滤器,过滤规则)
            - CustomAuth

        ##########################################【自定义过滤器工厂】#################################################
        - id: payment_service8001_customGatewayFilterFactory #路由ID
          uri: http://localhost:8001  #指定payment8001的访问地址,即匹配后提供服务的路由地址
          predicates:
            - Path=/customGatewayFilterFactory/**
          filters:  #过滤器(filters:过滤器,过滤规则)
            - CustomRequestTime=true

      discovery:
        locator:
          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由
eureka:
  instance:
    hostname: springcloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://springcloud-eureka7001.com:7001/eureka/,http://springcloud-eureka7002.com:7002/eureka/   #集群版Eureka注册中心


【e】测试

启动项目,浏览器访问:http://localhost:9528/customGatewayFilterFactory/weishihuai?a=1&b=2

查看后台日志:

2020-08-21 21:44:17.705  INFO 8488 --- [ctor-http-nio-3] .f.CustomRequestTimeGatewayFilterFactory : /customGatewayFilterFactory/weishihuai-----------pre前置处理----------
2020-08-21 21:44:17.728  INFO 8488 --- [ctor-http-nio-4] .f.CustomRequestTimeGatewayFilterFactory : /customGatewayFilterFactory/weishihuai-----------post后置处理----------
2020-08-21 21:44:17.729  INFO 8488 --- [ctor-http-nio-4] .f.CustomRequestTimeGatewayFilterFactory : /customGatewayFilterFactory/weishihuai--------> 耗时: 23ms,请求参数:{a=[1], b=[2]}

可见,成功实现了在记录请求时间的同时记录请求参数的信息,以上就是关于自定义过滤器工厂的实现方法,具体实现的时候我们可以参考源码中自带的过滤器工厂进行实现,如RedirectToGatewayFilterFactory、AddRequestHeaderGatewayFilterFactory等等。

五、总结

以上除了总结了一些常见的过滤器使用方法,并且通过示例讲解了如何自定义过滤器以及自定义过滤器工厂,下篇文章我们将对gateway中全局过滤器global filter做一个总结。以上相关项目的代码我已经放在Gitee上,有需要的小伙伴可以去拉取进行学习:https://gitee.com/weixiaohuai/springcloud_Hoxton,由于笔者水平有限,如有不对之处,还请小伙伴们指正,相互学习,一起进步。

参考资料:

https://blog.csdn.net/forezp/article/details/85057268

https://www.cnblogs.com/ye-feng-yu/p/11111803.html

已标记关键词 清除标记
本课程总计13大章节,115课时,是一门全面的SpringCloud微服务体系化课程。课程共包括十三个大章节,涵盖注册中心、网关、熔断、降级、监控、安全、限流等全部体系。包含阿里巴巴Nacos,Consul,Spring Cloud Gateway,OAuth2.0 JWT 等主流技术。     [为什么要学习Spring Cloud微服务] SpringCloud作为主流微服务框架,已成为各互联网公司的首选框架,国内外企业占有率持续攀升,是Java工程师的必备技能。就连大名鼎鼎的阿里巴巴dubbo也正式更名为Spring Cloud Alibaba,成为了Spring Cloud 微服务中的一个子模块。Spring Cloud是企业架构转型、个人能力提升、架构师进阶的不二选择。     【推荐你学习这门课的理由:知识体系完整+丰富学习资料】   1、本课程总计13大章节,115课时,是一门全面的SpringCloud微服务体系化课程。 2、课程0基础入门,逐层递进深入,理论和代码相结合。 3、十三个大章节,涵盖注册中心、网关、熔断、降级、监控、安全、限流等全部体系。 4、包含阿里巴巴Nacos,Consul,Spring Cloud Gateway,OAuth2.0 JWT 主流技术。 5、课程附带230页高清PDF正版课件、Hoxton版本配套项目源码37个、Edgware版本配套项目26个,所有代码均有详细注释。     【主讲讲师】 尹洪亮Kevin: 现任职某互联网公司首席架构师,负责系统架构、项目群管理、产品研发工作。 10余年软件行业经验,具有数百个线上项目实战经验。 擅长JAVA技术栈、高并发高可用伸缩式微服务架构、DevOps。 主导研发的蜂巢微服务架构已经成功支撑数百个微服务稳定运行     【学完后我将达到什么水平?】 1、 对Spring Cloud的各个组件能够熟练配置、开发、部署。 2、 吊打一切关于Spring Cloud微服务的笔试面试题 3、 能够上手搭建十分完整的微服务分布式系统,涵盖服务注册与发现、负载、网关、配置中心、监控、安全、熔断等。 4、 对整个微服务体系架构有十分清晰准确的掌握。   【面向人群】 1、 不了解微服务是什么,感觉微服务很难、不敢学,网上资料松散,没有好的学习资料 2、 这么多年还一直在写SSH、SSM项目,没有更新过自己的知识体系。 3、 Spring Cloud组件太多,不知道应该重点关注和学习哪些。 4、 不会搭建微服务项目、依赖项目太多、完全搞不清楚。   【课程知识体系图】
课程简介: 历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值