spring cloud gateway-filter过滤器篇

spring cloud gateway-filter过滤器篇

  • filter介绍
  • filter作用
  • filter生命周期
  • 内置的单路由过滤器
  • 自定义单个路由过滤器
  • 自定义全局路由过滤器

filter介绍

前篇对predicate断言进行了介绍,对于前端发送的请求,先通过网关的predicate断言找到对应路由处理,在路由处理之前,需要经过前置过滤器处理,处理返回响应之后,可以由后置过滤器处理,然后转发到相应服务。

与zuul不同的是,filter除了分为“pre前置”和“post后置”两种方式的filter外,在Spring Cloud Gateway中,filter从作用范围可分为另外两种,一种是针对于单个路由的gateway filter,它在配置文件中的写法同predict类似;另外一种是针对于所有路由的global gateway filer。

filter作用

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

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

filter生命周期

Spring Cloud Gateway 的 Filter 的生命周期有两个:“pre” 和 “post”。“pre”和 “post” 分别会在请求被执行前调用和被执行后调用
spring cloud gateway-filter过滤器篇_第1张图片

内置的单路由过滤器

Spring Cloud Gateway已经给我们提供了许多已经定义好的过滤器
这里介绍常用的几个,如果想更多了解可以到提供的Jar包内学习
spring cloud gateway-filter过滤器篇_第2张图片
spring cloud gateway-filter过滤器篇_第3张图片

1.AddRequestHeader GatewayFilter Factory
在请求头添加信息

routes: 
- id: add_request_header_route 
  uri: http://httpbin.org:80/get 
  filters: - AddRequestHeader=X-Request-Foo, Bar

2.RewritePath GatewayFilter Factory
改变请求路径

filters:
  # 访问localhost:8080/test, 请求会转发到localhost:8001/app/test
  - RewritePath=/test, /app/test
 url: localhost:8001

3.StripPrefixGatewayFilter Factory
进行请求路径截断

filters:
  # 访问localhost:8080/test/user, 请求会转发到localhost:8001/user
  - StripPrefix=1 #去除请求第一个级前缀
url: localhost:8001

4.PrefixPath GatewayFilter Factory
PrefixPath Filter 的作用和 StripPrefix 正相反,是在 URL 路径前面添加一部分的前缀

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: http://example.org
        filters:
        - PrefixPath=/mypath

自定义单个路由过滤器

以上简单介绍了几种常见的过滤器使用配置,如果想自定义过滤器使用,怎么做?
在这里插入图片描述
在这里插入图片描述
跟据内置的那些过滤器,他们都是继承AbstractGatewayFilterFactory抽象类并重写apply方法。
以此自定义过滤器需要2步
第一步:
创建一个以GatewayFilterFactory结尾的类继承AbstractGatewayFilterFactory抽象类,并重写里面的apply方法

第二步:
注入到Spring Ioc容器里

第三步:
配置文件(这里需要注意的就是名称,举个例子)

比如:我自定义了DenfineGatewayFilterFactory类
这里的配置就是
filters:
- Denfine=false(值跟据场景,可以随意设置,配置名称DenfineGatewayFilterFactory必须为Denfine)

这里写一个案例,在某个路由下具备打印日志,统计该请求的耗时时间

@Component
public class DenfineGatewayFilterFactory  extends AbstractGatewayFilterFactory<DenfineGatewayFilterFactory.Config> {


    Logger logger=LoggerFactory.getLogger(DenfineGatewayFilterFactory.class);
    private static final String NAME_KEY="name";


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


    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            exchange.getAttributes().put("attrbute_time", System.currentTimeMillis());
            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {
                        Long startTime = exchange.getAttribute("attrbute_time");
                        if (startTime != null) {
                            StringBuilder sb = new StringBuilder(exchange.getRequest().getURI().getRawPath())
                                    .append("---此接口耗时")
                                    .append(": ")
                                    .append(System.currentTimeMillis() - startTime)
                                    .append("ms");
                            logger.info(sb.toString());
                        }
                    })
            );
        };
    }


    public List<String> shortcutFieldOrder() {
        return Arrays.asList(NAME_KEY);
    }


    public static class Config{
        private String name;


        public String getName() {
            return name;
        }


        public void setName(String name) {
            this.name = name;
        }
    }
}
server:
  port: 8082
spring:
  cloud:
    gateway:
      routes: #路由配置
      - id: auto-office-user
        uri: http://localhost:8084
        predicates: #谓词匹配
        - Path=/test/user/** #匹配路径
        filters:
        - StripPrefix=1 #去除第一个级前缀
        - Denfine=false

在这里插入图片描述

自定义全局路由过滤器

Spring Cloud Gateway与zuul不同的地方,Gateway可以跟据作用范围分为局部和全局的过滤器。局部过滤器前面已经介绍,下面对全局的过滤器进行介绍。

这里比较好理解直接上代码了
1.实现接口 GlobalFilter, Ordered

public class GlobelFilterTest implements GlobalFilter, Ordered {

    Logger logger= LoggerFactory.getLogger(GlobelFilterTest.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put("start_time", System.currentTimeMillis());
        return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    Long startTime = exchange.getAttribute("start_time");
                    if (startTime != null) {
                        StringBuilder sb = new StringBuilder("全局拦截---")
                                .append(exchange.getRequest().getURI().getRawPath())
                                .append("---接口耗时")
                                .append(": ")
                                .append(System.currentTimeMillis() - startTime)
                                .append("ms");
                        logger.info(sb.toString());
                    }
                })
        );
    }

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

在上面的代码中,Ordered中的int getOrder()方法是来给过滤器设定优先级别的,值越大则优先级越低。

2.注入到spring容器

@Configuration
public class FilterConfig {
    @Bean
    public GlobelFilterTest globelFilterTest(){
        return new GlobelFilterTest();
    }


//    @Bean
//    public DenfineGatewayFilterFactory denfineGatewayFilterFactory(){
//        return new DenfineGatewayFilterFactory();
//    }
}

在这里插入图片描述

你可能感兴趣的:(微服务,过滤器,网关,spring,cloud,alibaba)