全局过滤器作用于所有的路由,不需要单独配置,我们可以用它来实现很多统一化处理的业务需求,比如权限认证,IP访问限制等等。

接口定义类:org.springframework.cloud.gateway.filter.GlobalFilter

public interface GlobalFilter {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

gateway自带的GlobalFilter实现类有很多,如下图:

有转发,路由,负载等相关的GlobalFilter,感兴趣的可以自己去看下源码,了解下。

我们自己如何定义GlobalFilter来实现我们自己的业务逻辑?

给出一个官方文档上的案例:

@Configuration
public class ExampleConfiguration {
private Logger log = LoggerFactory.getLogger(ExampleConfiguration.class); @Bean
@Order(-1)
public GlobalFilter a() {
return (exchange, chain) -> {
log.info("first pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("third post filter");
}));
};
} @Bean
@Order(0)
public GlobalFilter b() {
return (exchange, chain) -> {
log.info("second pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("second post filter");
}));
};
} @Bean
@Order(1)
public GlobalFilter c() {
return (exchange, chain) -> {
log.info("third pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("first post filter");
}));
};
}
}

上面定义了3个GlobalFilter,通过@Order来指定执行的顺序,数字越小,优先级越高。下面就是输出的日志,从日志就可以看出执行的顺序:

2018-10-14 12:08:52.406  INFO 55062 --- [ioEventLoop-4-1] c.c.gateway.config.ExampleConfiguration  : first pre filter
2018-10-14 12:08:52.406 INFO 55062 --- [ioEventLoop-4-1] c.c.gateway.config.ExampleConfiguration : second pre filter
2018-10-14 12:08:52.407 INFO 55062 --- [ioEventLoop-4-1] c.c.gateway.config.ExampleConfiguration : third pre filter
2018-10-14 12:08:52.437 INFO 55062 --- [ctor-http-nio-7] c.c.gateway.config.ExampleConfiguration : first post filter
2018-10-14 12:08:52.438 INFO 55062 --- [ctor-http-nio-7] c.c.gateway.config.ExampleConfiguration : second post filter
2018-10-14 12:08:52.438 INFO 55062 --- [ctor-http-nio-7] c.c.gateway.config.ExampleConfiguration : third post filter

当GlobalFilter的逻辑比较多时,我还是推荐大家单独写一个GlobalFilter来处理,比如我们要实现对IP的访问限制,不在IP白名单中就不让调用的需求。

单独定义只需要实现GlobalFilter, Ordered这两个接口就可以了。

@Component
public class IPCheckFilter implements GlobalFilter, Ordered { @Override
public int getOrder() {
return 0;
} @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
HttpHeaders headers = exchange.getRequest().getHeaders();
// 此处写死了,演示用,实际中需要采取配置的方式
if (getIp(headers).equals("127.0.0.1")) {
ServerHttpResponse response = exchange.getResponse();
ResponseData data = new ResponseData();
data.setCode(401);
data.setMessage("非法请求");
byte[] datas = JsonUtils.toJson(data).getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(datas);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
}
return chain.filter(exchange);
} // 这边从请求头中获取用户的实际IP,根据Nginx转发的请求头获取
private String getIp(HttpHeaders headers) {
return "127.0.0.1";
} }

过滤的使用没什么好讲的,都比较简单,作用却很大,可以处理很多需求,上面讲的IP认证拦截只是冰山一角,更多的功能需要我们自己基于过滤器去实现。

比如我想做a/b测试,那么就得在路由转发层面做文章,前面我们有贴一个图片,图片中有很多默认的全局过滤器,其中有一个LoadBalancerClientFilter是负责选择路由服务的负载过滤器,里面会通过loadBalancer去选择转发的服务,然后传递到下面的路由NettyRoutingFilter过滤器去执行,那么我们就可以基于这个机制来实现。

Filter中往下一个Filter中传递数据实用下面的方式:

exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);

获取方直接获取:

URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);

如果我想改变路由的话,就可以这样做:

@Component
public class DebugFilter implements GlobalFilter, Ordered { @Override
public int getOrder() {
return 10101;
} @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
try {
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, new URI("http://192.168.31.245:8081/house/hello2"));
} catch (URISyntaxException e) {
e.printStackTrace();
}
return chain.filter(exchange);
} }

LoadBalancerClientFilter的order是10100,我们这边比它大1,这样就能在它执行完之后来替换要路由的地址了。

欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course)

spring cloud gateway 全局过滤器的更多相关文章

  1. spring cloud gateway自定义过滤器

    在API网关spring cloud gateway和负载均衡框架ribbon实战文章中,主要实现网关与负载均衡等基本功能,详见代码.本节内容将继续围绕此代码展开,主要讲解spring cloud g ...

  2. Spring Cloud Gateway自定义过滤器实战(观测断路器状态变化)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. Spring Cloud Alibaba学习笔记(19) - Spring Cloud Gateway 自定义过滤器工厂

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的内置过滤器工厂,若Spring Cloud Gateway内置的过滤器工厂无法满足我们的业务需求,那么此时就需要自定义自己的过 ...

  4. Spring Cloud Gateway 全局通用异常处理

    为什么需要全局异常处理 在传统 Spring Boot 应用中, 我们 @ControllerAdvice 来处理全局的异常,进行统一包装返回 // 摘至 spring cloud alibaba c ...

  5. 微服务网关实战——Spring Cloud Gateway

    导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...

  6. 微服务网关 Spring Cloud Gateway

    1.  为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...

  7. spring cloud gateway获取response body

    网关发起请求后,微服务返回的response的值要经过网关才发给客户端.本文主要讲解在spring cloud gateway 的过滤器中获取微服务的返回值,因为很多情况我们需要对这个返回进行处理.网 ...

  8. 快速突击 Spring Cloud Gateway

    认识 Spring Cloud Gateway Spring Cloud Gateway 是一款基于 Spring 5,Project Reactor 以及 Spring Boot 2 构建的 API ...

  9. Spring Cloud Gateway 实现Token校验

    在我看来,在某些场景下,网关就像是一个公共方法,把项目中的都要用到的一些功能提出来,抽象成一个服务.比如,我们可以在业务网关上做日志收集.Token校验等等,当然这么理解很狭隘,因为网关的能力远不止如 ...

随机推荐

  1. laravel he stream or file "..laravel-2019-02-14.log" could not be opened: failed to open stream: Permission denied

    错误:The stream or file "/var/www/jianshu/storage/logs/laravel-2019-02-14.log" could not be ...

  2. 10道Python常见面试题

    1.MySQL索引种类 1.普通索引 2.唯一索引 3.主键索引 4.组合索引 5.全文索引 2.索引在什么情况下遵循最左前缀的规则? 最左前缀原理的一部分,索引index1:(a,b,c),只会走a ...

  3. JavaScript addEventListener()事件监听方法

    addEventListener()方法将事件处理程序附加到指定的元素. addEventListener()方法将事件处理程序附加到元素,而不覆盖现有的事件处理程序. 您可以向一个元素添加许多事件处 ...

  4. pushad与popad

    版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明.2019-08-24,00:40:12作者By-----溺心与沉浮----博客园 PUSHAD与POPAD 这两条指令其实就是讲EAX,E ...

  5. Django forms 主要的标签介绍

    修改 forms.py from django import forms as DForms from django.forms import fields from django.forms imp ...

  6. Redis缓存实战教程

    目录 Redis缓存 使用缓存Redis解决首页并发问题 1.缓存使用的简单设计 2.Redis的整合步骤 A 将Redis整合到项目中(Redis+Spring) B 设计一个数据存储策越 3.Re ...

  7. LGBMClassifier参数

    本文链接:https://blog.csdn.net/starmoth/article/details/845867091.boosting_type=‘gbdt’# 提升树的类型 gbdt,dart ...

  8. Everybody Dance Now

    一.摘要 作者提出了一种简单的动作迁移方法,实现了"do as I do":给定一个人跳舞的源视频,作者可以在目标对象表演标准动作的短短几分钟后,将该表演转移到一个新的(业余的)目 ...

  9. css 最后的终章

    相对定位:参考点 相对原来的位置 1.如果是一个单独的文档流盒子,及你姐设置了相对定位,和普通盒子一样 2.相对定位后,如果调整位置,会留下坑 作用:微调元素 子绝父相 提升层级 绝对定位 参考点:父 ...

  10. JS高阶---闭包应用(自定义JS模块)

    [自定义JS模块] [闭包案例] (1)案例1 对应的模块文件 (2)案例2---使用匿名函数 对应的模块文件 案例2分析:因为内部函数引用了外部函数的变量,且存在嵌套关系,所以是闭包,分析结构图如下 ...