全局过滤器作用于所有的路由,不需要单独配置,我们可以用它来实现很多统一化处理的业务需求,比如权限认证,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. springboot 使用 freemarker 无法正常跳转的问题?

    1.springboot 使用 freemarker 无法正常跳转的问题? 参考:https://blog.csdn.net/Lin_xiaofeng/article/details/79122053 ...

  2. C# 委托补充01

    上一篇文章写了委托的最基本的一些东西,本篇咱们扯扯委托其他的东西. 示例1插件编程 根据对委托的理解,委托可以把一个方法当作参数进行传递,利用这个特性我们可以使用委托,实现插件编程. public d ...

  3. python 跟踪IP模块

    #coding=utf-8 import re import subprocess def tracertIP(ip): p = subprocess.Popen(['tracert',ip],std ...

  4. python接口上传图片和文件的方法

    import requests def sendImg(img_path, img_name, img_type='image/jpeg'): """ :param im ...

  5. java进销存管理系统的设计与实现-springboot源码

    开发环境: Windows操作系统 开发工具:MyEclipse/Eclipse + JDK+ Tomcat + MySQL 数据库   项目简介:   系统前段页面采用jsp + JavaScrip ...

  6. Linux入门——注意事项

    Linux入门——注意事项 摘要:本文主要说明了在使用Linux操作系统时,需要注意的问题. 严格区分大小写 和Windows不同,Linux是严格区分大小写的,包括文件名和目录名.命令.命令选项.配 ...

  7. CSS box-sizing属性的正确用法

    CSS自定义属性(变量) CSS box-sizing属性允许我们在元素的总宽度和高度中包含填充和边框. 没有CSS box-sizing属性 默认情况下,元素的宽度和高度计算如下: width + ...

  8. sess文件编译输出css的四种方式以及使用

    sess文件输出css有下面四种方式: :nested(嵌套) :compact(紧凑) :expanded(展开) :compressed(压缩) 如何使用: sass --watch style. ...

  9. Windows下面startup.bat启动Tomcat偶发死锁问题

    Windows下面startup.bat启动Tomcat时,因为日志都打印到了cmd里面,存在偶发卡死Tomcat的问题,该问题确认是Windows系统的问题,而且一直没有解决.解决的办法是把日志重定 ...

  10. 6、Routing

    Routing In the previous tutorial we built a simple logging system. We were able to broadcast log mes ...