zoukankan      html  css  js  c++  java
  • Gateway网关入门指南

    Spring Cloud Gateway

    粗话网关

    网关,是整个微服务平台所有请求的统一入口,所有客户端和服务端之间的联系都通过网关来接入,相当于就是一个不赚差价的中间商,Spring Cloud Gateway做为替换上一代网关产品Zuul的新组件出现在Spring Cloud 2.0以及之后的版本中,网关作为一个服务的唯一入口,其中可以集成我们项目中除了业务之外的很多功能,比如认证授权,路由、负载均衡、日志、过滤等等一些列功能,

    想了解Gateway就得我们就先了解它的三大功能名词

    • 断言

      • 匹配http中请求头或者请求参数,如果请求与断言想匹配则进行路由

    • 路由

      • 根据断言规则,将某些请求转发到指定的服务器上

    • 过滤器

      • 过滤可以发生在路由前后,使用过滤器的思想,对请求进行修改或者监视

    10分钟写个Demo

    演示Demo大致如下,创建一个订单模块,一个支付模块(端口不同的两个应用),一个网关模块

    演示功能如下:

    • Gateway + Nacos + Openfein,简单跑通一下,主要关注点在于Gateway的基本使用和学习上

    父工程pom

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion><groupId>org.example</groupId>
        <artifactId>springcloud_alibaba</artifactId>
        <packaging>pom</packaging>
        <version>1.0-SNAPSHOT</version>
       
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </dependency>
                <!--spring boot 2.2.2-->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.2.2.RELEASE</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.1.0.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency><!--spring cloud Hoxton.SR1-->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Hoxton.SR1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement><build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement><plugins>
                <!--热部署配置-->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <fork>true</fork>
                        <addResources>true</addResources>
                    </configuration>
                </plugin><plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.2</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

    支付工程子模块(两个)

    创建完后,复制一个出来,就该一下端口,使端口不同即可

    该模块用于后面演示:

    • 订单模块负载均衡调用支付模块

    • 网关模块负载均衡调用支付模块

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloud_alibaba</artifactId>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion><artifactId>payment_8801</artifactId><dependencies>
            <!-- nacos -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到-->
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-datasource-nacos</artifactId>
            </dependency>
            <!-- SpringCloud ailibaba sentinel-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
            <!--web-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--监控-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <!--监控 以json格式输出信息-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-hateoas</artifactId>
            </dependency>
        </dependencies>
    </project>
    • application.yml

    server:
      port: 8801
    spring:
      application:
        name: payment-server
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            #配置地址
            dashboard: localhost:8080
            #默认8719端口,本地启动 HTTP API Server 的端口号
            port: 8719#监控
    management:
      endpoints:
        web:
          exposure:
            include: '*'
    • Controller

    @RestController
    @RequestMapping("/payment")
    public class PaymentController {
    ​
        @Value("${server.port}")
        private String port;
    ​
        @GetMapping("/test1/{id}")
        public String test1(@PathVariable("id") Integer id){
            return "This is Payment server,Port is " + port + "	 id为" + id;
         }
    }
    • 启动类

    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    @EnableDiscoveryClient
    public class PaymentApplication8801 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentApplication8801.class);
        }
    }

    订单工程子模块

    该模块的作用:

    • Gatwway学习中调用该模块进行演示

    • 该模块负载均衡调用支付模块,跑个流程

    • pom

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloud_alibaba</artifactId>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion><artifactId>order_8803</artifactId><dependencies>
            <!-- nacos -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到-->
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-datasource-nacos</artifactId>
            </dependency>
            <!-- SpringCloud ailibaba sentinel-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
            <!--远程调用 OpenFeign-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>
            <!--web-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--监控-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <!--监控 以json格式输出信息-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-hateoas</artifactId>
            </dependency>
        </dependencies>
    </project>

    application.yml

    server:
      port: 8803
    spring:
      application:
        name: order-server
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            #配置地址
            dashboard: localhost:8080
            #默认8719端口,本地启动 HTTP API Server 的端口号
            port: 8719
          #持久化规则到Nacos中,Nacos又通过配置持久化到数据mysql中
          datasource:
            ds1:
              nacos:
                server-addr: localhost:8848 #nacos地址
                dataId: order-server-sentinel  #微服务名称
                groupId: DEFAULT_GROUP  #默认分组
                data-type: json #数据格式
                rule-type: flow #流控规则
    #feign集成hystrix需要配置开启,实现降级
    feign:
      sentinel:
        enabled: true
    #监控
    management:
      endpoints:
        web:
          exposure:
            include: '*'
    • 远程调用Client

    @FeignClient(value = "payment-server",fallback = PaymentClientDuty.class)
    public interface PaymentClient {
    ​
        @GetMapping("/payment/test1/{id}")
        public String test1(@PathVariable("id") Integer id);
    }
    @Component
    public class PaymentClientDuty implements PaymentClient {
    ​
        @Override
        public String test1(Integer id) {
            return "OpenFeign远程调用失败调用" + id;
        }
    }
    • controller

    @RestController
    public class OrderController {
    ​
        @Autowired
        private PaymentClient paymentClient;
        
        @GetMapping("/order/{id}")
        public String openfeignTest(@PathVariable("id") Integer id){
            return paymentClient.test1(id);
        }
    }
    • 启动类

    @EnableDiscoveryClient
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    @EnableFeignClients(basePackages = "com.nacos.order.clients")
    public class OrderApplication {
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class);
        }

    网关工程子模块

    • pom

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springcloud_alibaba</artifactId>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion><artifactId>gateway_8800</artifactId>
        <packaging>jar</packaging><dependencies>
            <!-- nacos -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <!-- SpringCloud ailibaba sentinel-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
            <!--gateway-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
        </dependencies><build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build></project>
    • application.yml

    server:
      port: 8800
    ​
    spring:
      application:
        name: gateway-server
    ​
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848   #作为注册中心的地址
        gateway:
          routes:
            - id: test1
              uri: http://localhost:8803
              predicates:
                - Path=/order/**
    • 启动类

    package com.ninja.gateway;
    ​
    import org.bouncycastle.math.ec.endo.GLVTypeAEndomorphism;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    ​
    /**
     * @Description
     * @Author Ninja
     * @Date 2020/8/30
     **/
    ​
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    @EnableDiscoveryClient
    public class GatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(GatewayApplication.class);
        }
    }

    配置文件详细说明

    在我们的网关工程子模块中,可以看到下面的一配置

    网关的路由配置,可以采用硬编码的方式也可以采用如下配置文件的方式

    • 当然硬编码的方式因为是写死在代码中,扩展性和动态性就受到了限制,不做过多说明

    • 我们就对配置文件的方式做一个详细的解说

    gateway:
      routes:
        - id: test1
          uri: http://localhost:8803
          predicates:
            - Path=/order/**

    上面只是一段配置,全称应该为speing.cloud.gateway.routes

    • routes:路由的复数形式,用来包含所有的路由规则等相关信息

      • id: 路由id,随便取,唯一要求就是全局唯一,一般我们配合服务名进行配置

      • uri:路由地址,这就是断言后的请求转发地址,

        • 一般不会使用具体的ip和端口,而是配合nacos注册中心一起使用

        • 具体下面详细讲解

      • predicates:断言的复数,表示包含所有的断言规则

        • path : 就是一个断言中的一种

    上面的路由配置文件中,主要实现的功能为:

    • 网关的端口8800,

    • 当我们访问localhost:8800/order/xx时,请求会转发到localhost:8803/order/xx

    可见路由转发已经生效

    断言类型详解

    path

    上面我们使用path 意思就是,路径相匹配则进行路由跳转,还有很多的规则可以配置,下面慢慢道来

    After

    • After:可以指定,只有在指定时间后,才可以路由到指定微服务

    ZonedDateTime date = ZonedDateTime.now();
    System.out.println(date); //获得时间,写个测试得到即可

    现在我们将配置文件修改为如下

    gateway:
      routes:
        - id: test1
          uri: lb://payment-server
          predicates:
            - Path=/payment/test1/**
            - After=2020-08-30T14:37:20.465+08:00[Asia/Shanghai]
    • uri 修改为指定注册中心上的服务,而不是固定的ip和端口

    • lb://payment-server :表示使用负载均衡的方式调用该服务

    • path 意思就是,路径相匹配则进行路由跳转

    • After意思为,在指定时间后才可以访问,之前访问为404

    时间到了后,根据暴露的端口信息得知:负载均衡调用服务

     

    before和between

    • 这两个和上面after都是控制时间的,顾名思义:

    before: 与after类似,他说在指定时间之前的才可以访问 between: 需要指定两个时间,在他们之间的时间才可以访问

    cookie

    • cookie:只有包含某些指定cookie(key,value),的请求才可以路由

    现在我们将配置文件修改为如下

      
    gateway:
          routes:
            - id: test1
              uri: lb://payment-server
              predicates:
                - Path=/payment/test1/**
    #            - After=2020-08-30T14:37:20.465+08:00[Asia/Shanghai]
                - Cookie=username,test

    表示:只有cookie中包含了username这个key,且值为test才路由

    在不加cookie的时候会报404

    浏览器打开控制台,键入以下命令,添加cookie再访问

    document.cookie="username=test";

    header

    • header:只有包含指定请求头的请求,才可以路由

    • 现在我们将配置文件修改为如下

      
     gateway:
          routes:
            - id: test1
              uri: lb://payment-server
              predicates:
                - Path=/payment/test1/**
    #            - After=2020-08-30T14:37:20.465+08:00[Asia/Shanghai]
    #            - Cookie=username,test
                - Header=ninja,d+

    Header 接受两个参数,第一个参数为头的名称,第二个参数为一个正则表达式

    以上的配置便是,请求头中需有一个请求头key为ninja,且值为数字类型的值时才路由,

    host

    • host:只有携带请求头中指定的Host才可以进行路由

    • 现在我们将配置文件修改为如下 

    gateway:
          routes:
            - id: test1
              uri: lb://payment-server
              predicates:
                - Path=/payment/test1/**
    #            - After=2020-08-30T14:37:20.465+08:00[Asia/Shanghai]
    #            - Cookie=username,test
    #            - Header=ninja,d+
                - Host= www.ninja.com
    • 以上的配置便是,请求头Host的值必须为www.ninja.com时才路由,其余一律不路由,

    • 这个可以使用通配符方式比如:www.ninja.**,也是可以的

    • 测试图为如下所示

    由于往下类型众多,我就不一一截图演示了,做详细的文字说明,不懂就点我

    method

    • method:指定请求类型才可路由,比如post,get等

    • 配置文件修改为如下所示

        gateway:
          routes:
            - id: test1
              uri: lb://payment-server
              predicates:
                - Path=/payment/test1/**
    #            - After=2020-08-30T14:37:20.465+08:00[Asia/Shanghai]
    #            - Cookie=username,test
    #            - Header=ninja,d+
    #            - Host= www.ninja.com
                - Method=GET

    Query

    • query:必须带有请求参数才可以访问

    • 配置文件修改为如下所示

        gateway:
          routes:
            - id: test1
              uri: lb://payment-server
              predicates:
                - Path=/payment/test1/**
    #            - After=2020-08-30T14:37:20.465+08:00[Asia/Shanghai]
    #            - Cookie=username,test
    #            - Header=ninja,d+
    #            - Host= www.ninja.com
    #            - Method=GET
                - Query=username,d+
    • 上面的规则为,请求中需携带请求参数key为username,且值为整数的值才进行路由

    基本上大致的断言类型我们以及知道了,下面对另一个概念进行讲解说明:过滤器

    过滤器Filter

    filter可用于修改的http请求和返回的http响应,相当于就是一个pre 一个post

    单一过滤器(GatewayFilter)

    也就是我们配置在某个路由规则中的过滤器,对单个路由发生作用,Gateway一共内置了20多个过滤器,分别对头部过滤器、 路径类过滤器、 Hystrix过滤器和变更请求URL的过滤器, 还有参数和状态码等其他类型的过滤器。这里就不一一说明了,我们挑几个常用的讲解一番,其余就不做讲解了,当个人吧!

    • 配置文件修改为如下所示

    gateway:
      routes:
        - id: test1
          uri: lb://payment-server
          filters:
            - AddRequestHeader=ninja, ninja_test                #添加请求头
            - AddResponseHeader=ninja_response,ninja_test       #添加响应头
            - RewritePath=/payment/(?<segment>.*), /${segment} #请求路径重写
          predicates:
            - Path=/payment/payment/test1/**

    测试之前想一想

    • 服务的提供者我们一直没有做任何改变

    • 在网关中,通过断言对请求url做了匹配

    • 然后我们使用过滤器对请求路径做了重写

      • /payment/(?<segment>.*), /${segment} ???

      • 第一个参数为原请求url,即是采用通配符的方式载入,

      • 第二个参数为重写后的请求url:/${segment},为通配符的占位符

        • 根据上面我们对第一个参数的解读,/${segment} 占位符替换即为:/payment/test1/11111

    好了,更多的过滤器就面向百度吧,这里就不啰嗦了

    全局过滤器(GlobalFilter)

    • 全局过滤器不再针对单个路由规则,全局过滤器无需在配置文件中配置,为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。

    自定义过滤器(局部和全局)

    • 除了上面网关提供的全局过滤器外,还可以自定义过滤器这也是我们经常使用的功能,下面详细说明一下

    • 全局过滤器之自定义过滤器,我们需要实现两个接口:GlobalFilter, Ordered

    • 局部过滤器子自定义过滤器,我们也需要实现两个接口:GatewayFilter, Ordered

    • 都是重写两个函数,一个filter为我们的业务函数,一个表示当前过滤器的执行级别的函数

    • 如何运用局部 / 全局过滤器 ?

      • 全局过滤器:因为无需挂载到某个路由上,全局生效,无需额外编码和配置

      • 局部过滤器:需要编码指定某个路由,局部生效,需要额外的编码

    下面,我们分别来写两三个过滤器玩一玩

    package com.ninja.gateway.custom;
    ​
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    ​
    /**
     * @Description 全局过滤器,前置与后置过滤器
     * @Author Ninja
     * @Date 2020/8/31
     **/
    ​
    @Component
    public class PreAndPostGlobalFilter implements GlobalFilter, Ordered {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            System.out.println("------this is a pre filter");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                System.out.println("------this is a post filter");
            }));
        }
    ​
        @Override
        public int getOrder() {
            //定义过滤器执行顺序
            //返回值越小,越靠前执行
            return -1;
        }
    }
    package com.ninja.gateway.custom;
    ​
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    ​
    /**
     * @Description 局部过滤器:远程调用耗时记录
     * @Author Ninja
     * @Date 2020/8/31
     **/
    ​
    @Component
    public class TimeCountNoGlaobalFilter implements GatewayFilter, Ordered {
    ​
        private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
    ​
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            //记录请求开始时间
            exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
    ​
            return chain.filter(exchange).then(Mono.fromRunnable(new Runnable() {
                @Override
                public void run() {
                    Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
                    if (startTime != null) {
                        //打印
                        System.out.println(exchange.getRequest().getURI() + " 耗时" + (System.currentTimeMillis() - startTime));
                    }
                }
            }));
        }
    ​
        @Override
        public int getOrder() {
            //定义过滤器执行顺序
            //返回值越小,越靠前执行
            return 0;
        }
    }
    package com.ninja.gateway.custom;
    ​
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    ​
    /**
     * @Description 全局过滤器
     * @Author Ninja
     * @Date 2020/8/31
     **/
    ​
    @Component
    public class UriGlobalFilter implements GlobalFilter, Ordered {
    ​
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            String path = exchange.getRequest().getURI().getPath();
            System.out.println("UrlFilter拦截器已拦截,url:" + path);
            //拦截请求,直接响应
            //return exchange.getResponse().setComplete();
            //放行请求
            return chain.filter(exchange);
        }
    ​
        @Override
        public int getOrder() {
            //定义过滤器执行顺序
            //返回值越小,越靠前执行
            return 1;
        }
    }

    上面我写了三个过滤器,分别为:

    • PreAndPostGlobalFilter:全局过滤器,直接生效

    • TimeCountNoGlaobalFilter:局部过滤器,需要额外编码指定路由

    • UriGlobalFilter:全局过滤器,直接生效

    下面我们对唯一的局部过滤器进行绑定路由的编码

    package com.ninja.gateway.config;
    ​
    import com.ninja.gateway.custom.TimeCountNoGlaobalFilter;
    import com.ninja.gateway.custom.UriGlobalFilter;
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.route.Route;
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.cloud.gateway.route.builder.GatewayFilterSpec;
    import org.springframework.cloud.gateway.route.builder.PredicateSpec;
    import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
    import org.springframework.cloud.gateway.route.builder.UriSpec;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    ​
    import java.util.function.Function;
    ​
    /**
     * @Description 将自定义局部filter注册到路由中
     * @Author Ninja
     * @Date 2020/8/31
     **/
    @Configuration
    public class FilterEureka {
    ​
        @Bean
        public RouteLocator getRouteLocator(RouteLocatorBuilder builder) {
            return builder.routes().
                    route(new Function<PredicateSpec, Route.AsyncBuilder>() {
                        @Override
                        public Route.AsyncBuilder apply(PredicateSpec predicateSpec) {
                            return predicateSpec
                                    .path("/payment/payment/test1/**")
                                    .filters(new Function<GatewayFilterSpec, UriSpec>() {
                                        @Override
                                        public UriSpec apply(GatewayFilterSpec gatewayFilterSpec) {
                                            return gatewayFilterSpec.stripPrefix(1).filter( new TimeCountNoGlaobalFilter());
                                        }
                                    })
                                    .uri("lb://payment-server")
                                    .id("test1)");
    ​
                        }
                    }).build();
        }
    ​
    }
    • 仔细看看,无非就是指定了id,path 和 uri,使其绑定到了该路由上,下面我们启动项目测试一把

    可见全局过滤器和局部过滤器都已经生效,至此 毕!

  • 相关阅读:
    【翻译】Flink Table Api & SQL —Streaming 概念 —— 时态表
    【翻译】Flink Table Api & SQL —Streaming 概念 ——在持续查询中 Join
    【翻译】Flink Table Api & SQL —Streaming 概念 ——时间属性
    【翻译】Flink Table Api & SQL —Streaming 概念 ——动态表
    【翻译】Flink Table Api & SQL ——Streaming 概念
    Kubernetes控制器之Deployment
    Kubernetes中nodeport,port,targetport对比
    Kubernetes控制器之ReplicaSet
    Kubernetes之Pods
    Kubernetes之使用ConfigMap配置Pod
  • 原文地址:https://www.cnblogs.com/msi-chen/p/13587504.html
Copyright © 2011-2022 走看看