Spring Cloud——微服务网关Spring Cloud GateWay

Spring Cloud GateWay

Spring 自己开发的新一代API网关产品,基于NIO异步处理,摒弃了Zuul基于Servlet同步通信的设计。

Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

关键特征:

  • 1、基于JDK8+开发。
  • 2、Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
  • 3、支持动态路由,能够匹配任何请求属性上的路由。
  • 4、支持基于HTTP请求的路由匹配(Path、Method、Header、Host等)。
  • 5、过滤器可以修改HTTP请求和HTTP响应。

在性能方面,根据官方提供的基准测试, Spring Cloud Gateway 的 RPS(每秒请求数)是Zuul 的 1.6 倍。

Spring Cloud Gateway十分优秀,Spring Cloud Alibaba也默认选用该组件作为网关产品。

相关概念:

  • Route(路由):这是网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
  • Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
  • Filter(过滤器):这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,我们可以使用它修改请求和响应。

工作流程:

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

Spring Cloud Gateway 的特征:

  • 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  • 动态路由
  • Predicates 和 Filters 作用于特定路由
  • 集成 Hystrix 断路器
  • 集成 Spring Cloud DiscoveryClient
  • 易于编写的 Predicates 和 Filters
  • 限流
  • 路径重写

Spring Cloud GateWay 快速上手

Spring Cloud Gateway 网关路由有两种配置方式:

  • 在配置文件 yml 中配置
  • 通过@Bean自定义 RouteLocator,在启动主类 Application 中配置

这两种方式是等价的,建议使用 yml 方式进配置。

引入依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.12.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies> 

<dependencyManagement>
    <dependencies>
        <!--整合Spring Cloud-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR12</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--整合Spring Cloud Alibaba-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement> 

Spring Cloud Gateway 是使用 netty+webflux 实现因此不需要再引入 web 模块。

gateWay的主要功能之一是转发请求,转发规则的定义主要包含三个部分:

  • Route(路由):路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发。
  • Predicate(谓语、断言):路由转发的判断条件,目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式。
  • Filter(过滤器):过滤器是路由转发请求时所经过的过滤逻辑,可用于修改请求、响应内容。

注意:其中Route和Predicate必须同时申明

路由配置方式

基础URI路由配置方式

  • 如果请求的目标地址,是单个的URI资源路径,配置文件示例如下:
//通过配置文件配置
spring:
  cloud:
    gateway:
      routes:
        - id: gate_route
          uri: http://localhost:9023
          predicates:
          ## 当请求的路径为gate、rule开头的时,转发到http://localhost:9023服务器上
            - Path=/gate/**,/rule/**
        ### 请求路径前加上/app
          filters:
          - PrefixPath=/app     

基于代码的路由配置方式

转发功能同样可以通过代码来实现,我们可以在启动类 GateWayApplication 中添加方法 customRouteLocator() 来定制转发规则。

@SpringBootApplication
public class GatewayApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
 
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("/csdn")
                    .uri("https://blog.csdn.net"))
                .build();
    }
}

上面配置了一个 id 为 path_route 的路由,当访问地址http://localhost:8080/about时会自动转发到地址:https://blog.csdn.net/csdn和上面的转发效果一样,只是这里转发的是以项目地址/csdn格式的请求地址。

和注册中心相结合的路由配置方式

在uri的schema协议部分为自定义的lb:类型,表示从微服务注册中心(如Eureka)订阅服务,并且进行服务的路由。

server:
  port: 8084
spring:
  cloud:
    gateway:
      routes:
      -id: seckill-provider-route
        uri: lb://seckill-provider
        predicates:
        - Path=/seckill-provider/**

      -id: message-provider-route
        uri: lb://message-provider
        predicates:
        -Path=/message-provider/**

application:
  name: cloud-gateway

eureka:
  instance:
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://localhost:8888/eureka/

注册中心相结合的路由配置方式,与单个URI的路由配置,区别其实很小,仅仅在于URI的schema协议不同。单个URI的地址的schema协议,一般为http或者https协议。

路由匹配规则

Spring Cloud Gateway 的功能很强大,我们仅仅通过 Predicates 的设计就可以看出来,前面我们只是使用了 predicates 进行了简单的条件匹配,其实 Spring Cloud Gataway 帮我们内置了很多 Predicates 功能。

Spring Cloud Gateway 是通过 Spring WebFlux 的 HandlerMapping 做为底层支持来匹配到转发路由,Spring Cloud Gateway 内置了很多 Predicates 工厂,这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配,多个 Predicates 工厂可以组合使用。

Predicate 断言条件(转发规则)介绍

Predicate 来源于 Java 8,是 Java 8 中引入的一个函数,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。

说白了 Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用。

规则 实例 说明
Path - Path=/gate/,/rule/ 当请求的路径为gate、rule开头的时,转发到http://localhost:9023服务器上
Before - Before=2017-01-20T17:42:47.789-07:00[America/Denver] 在某个时间之前的请求才会被转发到 http://localhost:9023服务器上
After - After=2017-01-20T17:42:47.789-07:00[America/Denver] 在某个时间之后的请求才会被转发
Between - Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver] 在某个时间段之间的才会被转发
Cookie - Cookie=chocolate, ch.p 名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发
Header - Header=X-Request-Id, \d+ 携带参数X-Request-Id或者满足\d+的请求头才会匹配
Host - Host=www.hd123.com 当主机名为www.hd123.com的时候直接转发到http://localhost:9023服务器上
Method - Method=GET 只有GET方法才会匹配转发请求,还可以限定POST、PUT等请求方式

通过请求参数匹配

  • Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。
server:
  port: 8080
spring:
  application:
     name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Query=smile

只要请求中包含 smile 属性的参数即可匹配路由,不带 smile 参数则不会匹配。

curl localhost:8080?smile=x&id=2
  • 还可以将 Query 的值以键值对的方式进行配置,这样在请求过来时会对属性值和正则进行匹配,匹配上才会走路由。
server:
  port: 8080
spring:
  application:
     name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Query=keep, pu.

这样只要当请求中包含 keep 属性并且参数值是以 pu 开头的长度为三位的字符串才会进行匹配和路由。

curl localhost:8080?keep=pub

通过 Header 属性匹配

Header Route Predicate 和 Cookie Route Predicate 一样,也是接收 2 个参数,一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Header=X-Request-Id, \d+

使用 curl 测试,命令行输入:

curl http://localhost:8080 -H "X-Request-Id:88"

则返回页面代码证明匹配成功。将参数-H "X-Request-Id:88"改为-H "X-Request-Id:spring"再次执行时返回404证明没有匹配。

通过 Cookie 匹配

Cookie Route Predicate 可以接收两个参数,一个是 Cookie name ,一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Cookie=sessionId, test

使用 curl 测试,命令行输入:

curl http://localhost:8080 --cookie "sessionId=test"

则会返回页面代码,如果去掉--cookie "sessionId=test",后台汇报 404 错误。

通过 Host 匹配

Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Host=**.baidu.com

使用 curl 测试,命令行输入:

curl http://localhost:8080 -H "Host: www.baidu.com"

curl http://localhost:8080 -H "Host: md.baidu.com"

经测试以上两种 host 均可匹配到 host_route 路由,去掉 host 参数则会报 404 错误。

通过请求方式匹配

可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Method=GET

使用 curl 测试,命令行输入:

# curl 默认是以 GET 的方式去请求

curl http://localhost:8080

测试返回页面代码,证明匹配到路由,我们再以 POST 的方式请求测试。

# curl 默认是以 GET 的方式去请求

curl -X POST http://localhost:8080

返回 404 没有找到,证明没有匹配上路由。

通过请求路径匹配

Path Route Predicate 接收一个匹配路径的参数来判断是否走路由。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: http://ityouknow.com
          order: 0
          predicates:
            - Path=/foo/{segment}

如果请求路径符合要求,则此路由将匹配,例如:/foo/1 或者 /foo/bar。

使用 curl 测试,命令行输入:

curl http://localhost:8080/foo/1

curl http://localhost:8080/foo/xx

curl http://localhost:8080/boo/xx

经过测试第一和第二条命令可以正常获取到页面返回值,最后一个命令报404,证明路由是通过指定路由来匹配。

通过请求 ip 地址进行匹配

Predicate 也支持通过设置某个 ip 区间号段的请求才会路由,RemoteAddr Route Predicate 接受 cidr 符号(IPv4 或 IPv6 )字符串的列表(最小大小为1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - RemoteAddr=192.168.1.1/24

可以将此地址设置为本机的 ip 地址进行测试。

curl localhost:8080

如果请求的远程地址是 192.168.1.10,则此路由将匹配。

组合使用

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - Host=**.foo.org
            - Path=/headers
            - Method=GET
            - Header=X-Request-Id, \d+
            - Query=foo, ba.
            - Query=baz
            - Cookie=chocolate, ch.p

各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。

一个请求满足多个路由的断言条件时,请求只会被首个成功匹配的路由转发。

过滤器规则(Filter)

过滤规则 实例 说明
PrefixPath - PrefixPath=/app 在请求路径前加上app
RewritePath - RewritePath=/test, /app/test 访问localhost:9022/test,请求会转发到localhost:8001/app/test
SetPath SetPath=/app/{path} 通过模板设置路径,转发的规则时会在路径前增加app,{path}表示原请求路径
RedirectTo 重定向
RemoveRequestHeader 去掉某个请求头信息

注意:当配置多个filter时,优先定义的会被调用,剩余的filter将不会生效

PrefixPath

  • 对所有的请求路径添加前缀:
spring:
  cloud:
    gateway:
      routes:
        - id: prefixpath_route
          uri: https://example.org
          filters:
            - PrefixPath=/mypath

访问/hello的请求被发送到https://example.org/mypath/hello

RedirectTo

  • 重定向,配置包含重定向的返回码和地址:
spring:
  cloud:
    gateway:
      routes:
        - id: prefixpath_route
          uri: https://example.org
          filters:
            - RedirectTo=302, https://acme.org

RemoveRequestHeader

  • 去掉某个请求头信息:
spring:
  cloud:
    gateway:
      routes:
        - id: removerequestheader_route
          uri: https://example.org
          filters:
            - RemoveRequestHeader=X-Request-Foo

去掉请求头信息 X-Request-Foo

RemoveResponseHeader

  • 去掉某个回执头信息:
spring:
  cloud:
    gateway:
      routes:
        - id: removerequestheader_route
          uri: https://example.org
          filters:
            - RemoveResponseHeader=X-Request-Foo

RemoveRequestParameter

  • 去掉某个请求参数信息:
spring:
  cloud:
    gateway:
      routes:
        - id: removerequestparameter_route
          uri: https://example.org
          filters:
            - RemoveRequestParameter=red

RewritePath

  • 改写路径:
spring:
  cloud:
    gateway:
      routes:
        - id: rewrite_filter
          uri: http://localhost:8081
          predicates:
            - Path=/test/**
          filters:
            - RewritePath=/where(?<segment>/?.*), /test(?<segment>/?.*)

/where/... 改成 test/...

使用代码改下路径

RouteLocatorBuilder.Builder builder = routeLocatorBuilder.routes();
builder.route("path_rote_at_guigu", r -> r.path("/guonei")
                .uri("http://news.baidu.com/guonei"))
        .route("csdn_route", r -> r.path("/csdn")
                .uri("https://blog.csdn.net"))
        .route("blog3_rewrite_filter", r -> r.path("/blog3/**")
                .filters(f -> f.rewritePath("/blog3/(?<segment>.*)", "/$\\{segment}"))
                .uri("https://blog.csdn.net"))
        .route("rewritepath_route", r -> r.path("/baidu/**")
                .filters(f -> f.rewritePath("/baidu/(?<segment>.*)", "/$\\{segment}"))
                .uri("http://www.baidu.com"))
        .build();

SetPath

  • 设置请求路径,与RewritePath类似。
spring:
  cloud:
    gateway:
      routes:
        - id: setpath_route
          uri: https://example.org
          predicates:
            - Path=/red/{segment}
          filters:
            - SetPath=/{segment}

如/red/blue的请求被转发到/blue。

SetRequestHeader

  • 设置请求头信息。
spring:
  cloud:
    gateway:
      routes:
        - id: setrequestheader_route
          uri: https://example.org
          filters:
            - SetRequestHeader=X-Request-Red, Blue

SetStatus

  • 设置回执状态码。
spring:
  cloud:
    gateway:
      routes:
        - id: setstatusint_route
          uri: https://example.org
          filters:
            - SetStatus=401

StripPrefix

  • 跳过指定路径。
spring:
  cloud:
    gateway:
      routes:
        - id: nameRoot
          uri: https://nameservice
          predicates:
            - Path=/name/**
          filters:
            - StripPrefix=2

请求/name/blue/red会转发到/red。

RequestSize

  • 请求大小。
spring:
  cloud:
    gateway:
      routes:
        - id: request_size_route
          uri: http://localhost:8080/upload
          predicates:
            - Path=/upload
          filters:
            - name: RequestSize
              args:
                maxSize: 5000000

超过5M的请求会返回413错误。

Default-filters

  • 对所有请求添加过滤器。
spring:
  cloud:
    gateway:
      default-filters:
        - AddResponseHeader=X-Response-Default-Red, Default-Blue
        - PrefixPath=/httpbin

通过代码进行配置

  • 通过代码进行配置,将路由规则设置为一个Bean即可:
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("path_route", r -> r.path("/get")
            .uri("http://httpbin.org"))
        .route("host_route", r -> r.host("*.myhost.org")
            .uri("http://httpbin.org"))
        .route("rewrite_route", r -> r.host("*.rewrite.org")
            .filters(f -> f.rewritePath("/foo/(?<segment>.*)", "/${segment}"))
            .uri("http://httpbin.org"))
        .route("hystrix_route", r -> r.host("*.hystrix.org")
            .filters(f -> f.hystrix(c -> c.setName("slowcmd")))
            .uri("http://httpbin.org"))
        .route("hystrix_fallback_route", r -> r.host("*.hystrixfallback.org")
            .filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))
            .uri("http://httpbin.org"))
        .route("limit_route", r -> r
            .host("*.limited.org").and().path("/anything/**")
            .filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter())))
            .uri("http://httpbin.org"))
        .build();
}

统一配置跨域请求:

现在的请求通过经过gateWay网关时,需要在网关统一配置跨域请求,需求所有请求通过

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origins: "*"
            allowed-headers: "*"
            allow-credentials: true
            allowed-methods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION

Gatway 网关的过滤器开发

过滤器的执行次序

Spring-Cloud-Gateway 基于过滤器实现,同 zuul 类似,有pre和post两种方式的 filter,分别处理前置逻辑和后置逻辑。客户端的请求先经过pre类型的 filter,然后将请求转发到具体的业务服务,收到业务服务的响应之后,再经过post类型的 filter 处理,最后返回响应到客户端。

过滤器执行流程如下,order 越大,优先级越低


Spring Cloud Gateway根据作用范围划分为GatewayFilter和GlobalFilter,二者区别如下:

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

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

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


定义全局过滤器

实现 GlobalFilter 和 Ordered,重写相关方法,加入到spring容器管理即可,无需配置,全局过滤器对所有的路由都有效。

全局过滤器举例:代码如下:

@Configuration
public class FilterConfig {

    @Bean
    @Order(-1)
    public GlobalFilter a() {
        return new AFilter();
    }

    @Bean
    @Order(0)
    public GlobalFilter b() {
        return new BFilter();
    }

    @Bean
    @Order(1)
    public GlobalFilter c() {
        return new CFilter();
    }


    @Slf4j
    public class AFilter implements GlobalFilter, Ordered {

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            log.info("AFilter前置逻辑");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("AFilter后置逻辑");
            }));
        }

        //值越小,优先级越高
        //int HIGHEST_PRECEDENCE = -2147483648;
        //int LOWEST_PRECEDENCE = 2147483647;
        @Override
        public int getOrder() {
            return HIGHEST_PRECEDENCE + 100;
        }
    }

    @Slf4j
    public class BFilter implements GlobalFilter, Ordered {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            log.info("BFilter前置逻辑");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("BFilter后置逻辑");
            }));
        }

        //值越小,优先级越高
        //int HIGHEST_PRECEDENCE = -2147483648;
        //int LOWEST_PRECEDENCE = 2147483647;
        @Override
        public int getOrder() {
            return HIGHEST_PRECEDENCE + 200;
        }
    }

    @Slf4j
    public class CFilter implements GlobalFilter, Ordered {

        @Override 
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            log.info("CFilter前置逻辑");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("CFilter后置逻辑");
            }));
        }

        //值越小,优先级越高
        //int HIGHEST_PRECEDENCE = -2147483648;
        //int LOWEST_PRECEDENCE = 2147483647;
        @Override
        public int getOrder() {
            return HIGHEST_PRECEDENCE + 300;
        }
    }
}

定义局部过滤器

步骤:

  • 1、需要实现GatewayFilter, Ordered,实现相关的方法
  • 2、加入到过滤器工厂,并且注册到spring容器中。
  • 3、在配置文件中进行配置,如果不配置则不启用此过滤器规则。

局部过滤器举例, 对请求头部的 user-id 进行校验,代码如下:

  • 1、需要实现GatewayFilter, Ordered,实现相关的方法
@Slf4j
public class UserIdCheckGateWayFilter implements GatewayFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getPath().pathWithinApplication().value();
        log.info("请求URL:" + url);
        log.info("method:" + exchange.getRequest().getMethod());
        //获取param 请求参数
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        //获取header
        String userId = exchange.getRequest().getHeaders().getFirst("user-id");
        log.info("userId:" + userId);

        if (StringUtils.isEmpty(userId)) {
            log.info("*****头部验证不通过,请在头部输入  user-id");
            //终止请求,直接回应
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    // 值越小,优先级越高
    //int HIGHEST_PRECEDENCE = -2147483648;
    //int LOWEST_PRECEDENCE = 2147483647;
    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }
}
  • 2、加入到过滤器工厂,并且注册到spring容器中。
@Component
public class UserIdCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
    
    @Override
    public GatewayFilter apply(Object config) {
        return new UserIdCheckGateWayFilter();
    }
}
  • 3、在配置文件中进行配置,如果不配置则不启用此过滤器规则。
- id: service_provider_demo_route_filter
  uri: lb://service-provider-demo
  predicates:
    - Path=/filter/**
  filters:
    - RewritePath=/filter/(?<segment>.*), /provider/$\{segment}
    - UserIdCheck

参考:
http://www.ityouknow.com/springcloud/2018/12/12/spring-cloud-gateway-start.html

http://www.likecs.com/show-50293.html

https://zhuanlan.zhihu.com/p/299608850?utm_source=wechat_session

https://juejin.cn/post/6844903965352525838

https://blog.csdn.net/weixin_38361347/article/details/114108368

http://www.zyiz.net/tech/detail-98256.html

https://www.cnblogs.com/crazymakercircle/p/11704077.html

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容