Spring Cloud Gateway Filter 详解:GlobalFilter 与 GatewayFilter
在微服务架构中,网关(Gateway)作为系统的统一入口,承担着路由转发、鉴权、限流、日志记录等重要职责。Spring Cloud Gateway 提供了强大的过滤器(Filter)机制来实现这些功能。
本文将结合实际开发经验,深入剖析 Spring Cloud Gateway 中两种核心过滤器:GatewayFilter 和 GlobalFilter 的区别、使用方法及底层原理。
1. 核心概念
Spring Cloud Gateway 的 Filter 生命周期分为 Pre(处理请求前)和 Post(处理请求后)。而从作用范围上来分,主要分为两种:
-
GatewayFilter(局部过滤器):
- 应用在单个路由或一组路由上。
- 需要在配置文件中显式配置,或者通过代码创建
RouteLocator时指定。 - Spring Cloud Gateway 内置了许多工厂类(GatewayFilterFactory),如
StripPrefix、AddRequestHeader等。
-
GlobalFilter(全局过滤器):
- 应用在所有的路由上。
- 无需在配置文件中针对每个路由配置。
- 通常用于实现全局性的逻辑,如统一鉴权、全局日志、监控指标等。
2. GlobalFilter 详解与实战
GlobalFilter 是实现全局业务逻辑的首选。它不需要复杂的配置,只需要实现 GlobalFilter 接口并注册为 Spring Bean 即可。
2.1 接口定义
public interface GlobalFilter {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
2.2 实战案例:全局鉴权过滤器
以下是一个通用的全局鉴权过滤器示例,演示了如何拦截请求、校验 Token 以及处理放行逻辑。
代码实现
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 自定义全局鉴权过滤器
* 实现了 GlobalFilter 和 Ordered 接口
*/
@Component
public class CustomAuthGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取请求路径
String reqPath = exchange.getRequest().getURI().getPath();
// 2. 白名单放行逻辑 (如登录接口、公共资源等)
if (isWhiteList(reqPath)) {
return chain.filter(exchange);
}
// 3. 获取 Token (通常从 Header 或 Query Param 中获取)
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
// 或者从参数获取: String token = exchange.getRequest().getQueryParams().getFirst("token");
// 4. Token 校验
if (token == null || token.isEmpty()) {
// 拒绝访问,返回 401 Unauthorized
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 5. 模拟 Token 验证 (例如校验 JWT 签名或查询 Redis)
if (!validateToken(token)) {
// Token 无效,返回 403 Forbidden
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
// 6. 校验通过,传递给下一个过滤器
return chain.filter(exchange);
}
/**
* 过滤器优先级,数字越小越优先
*/
@Override
public int getOrder() {
// 设置较高的优先级,确保鉴权尽早执行
return -1;
}
/**
* 判断路径是否在白名单中
*/
private boolean isWhiteList(String path) {
// 示例逻辑:放行登录接口和 Swagger 文档
return path.startsWith("/auth/login") || path.contains("swagger");
}
/**
* 验证 Token 有效性
*/
private boolean validateToken(String token) {
// TODO: 这里接入具体的业务逻辑,如 JWT 解析或 Redis 查询
return true;
}
}
关键点解析
- 实现接口:必须实现
GlobalFilter。通常也会实现Ordered接口来控制执行顺序。 - Order 顺序:
getOrder()返回的值越小,优先级越高,越先执行。鉴权通常需要较高的优先级。 - 放行逻辑:调用
chain.filter(exchange)将请求传递给下一个过滤器。 - 拦截逻辑:不调用
chain.filter,直接设置 Response 状态码并返回response.setComplete(),从而阻断请求。
3. GatewayFilter 详解与实战
GatewayFilter 更加灵活,可以针对特定的业务场景只对部分路由生效。
3.1 接口定义
public interface GatewayFilter extends ShortcutConfigurable {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
3.2 使用方式
方式一:配置文件(使用内置过滤器)
这是最常见的使用方式。例如,在 application.yml 中配置:
spring:
cloud:
gateway:
routes:
- id: user_route
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- StripPrefix=1 # 内置 GatewayFilter,去除路径第一节
- AddRequestHeader=X-Request-Foo, Bar # 添加请求头
方式二:代码配置(自定义 RouteLocator)
如果需要通过代码动态配置路由,可以使用 RouteLocatorBuilder:
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("path_route", r -> r.path("/get")
.filters(f -> f.addRequestHeader("Hello", "World"))
.uri("http://httpbin.org"))
.build();
}
方式三:自定义 GatewayFilter 工厂
如果需要自定义一个可以在配置文件中使用的 GatewayFilter,需要实现 GatewayFilterFactory。
@Component
public class MyCustomGatewayFilterFactory extends AbstractGatewayFilterFactory<MyCustomGatewayFilterFactory.Config> {
public MyCustomGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// Pre 逻辑
System.out.println("Pre: Custom GatewayFilter executed");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// Post 逻辑
System.out.println("Post: Custom GatewayFilter executed");
}));
};
}
public static class Config {
// 配置属性
}
}
然后在 YAML 中使用:
filters:
- name: MyCustom
4. 深度对比与原理分析
4.1 GlobalFilter vs GatewayFilter
| 特性 | GlobalFilter (全局过滤器) | GatewayFilter (局部过滤器) |
|---|---|---|
| 作用范围 | 所有路由 | 指定的路由 |
| 配置方式 | 声明为 Bean 自动生效 | 需在 YAML 或 Java Config 中显式配置 |
| 典型场景 | 统一鉴权、全局监控、全局日志 | 请求重写、限流、熔断、特定业务逻辑 |
| 实现难度 | 简单 (实现接口 + @Component) | 中等 (通常需实现 Factory 以便配置) |
4.2 底层原理:统一的 GatewayFilterChain
尽管在使用上分为两种,但在 Spring Cloud Gateway 的底层执行过程中,它们是等价的。
GlobalFilter 会被 GatewayFilterAdapter 包装成 GatewayFilterChain 可识别的过滤器。
对一个应用来说,GatewayFilter 和 GlobalFilter 是等价的,order 也会按照顺序进行拦截。
核心流程:
- 当请求到达网关时,DispatcherHandler 会匹配到对应的
Route。 - 网关会将该 Route 配置的
GatewayFilter列表和所有的GlobalFilter列表合并。 GlobalFilter会被适配器GatewayFilterAdapter包装成GatewayFilter。- 合并后的过滤器列表会根据
Ordered接口的返回值进行排序(数字越小越靠前)。 - 排序后的列表构建成一个
GatewayFilterChain链式执行。
排序规则注意事项:
- 如果
GlobalFilter和GatewayFilter的order值相同,具体的执行顺序是不确定的(取决于具体的排序算法实现,通常是稳定的,但建议避免相同 Order)。 - 建议为不同类型的过滤器规划固定的 Order 范围。
5. 总结
- GlobalFilter 是处理全局通用逻辑的最佳场所,例如实现统一的入口鉴权。
- GatewayFilter 提供了细粒度的控制能力,适合针对不同微服务定制不同的请求处理逻辑。
- 理解它们最终都会合并到同一个过滤链中执行,有助于我们更好地设计系统的过滤器体系,避免顺序冲突。
如果这篇文章对你有帮助,请 点赞、收藏、关注 一波!你的支持是我持续输出高质量技术干货的最大动力!!!
更多推荐




所有评论(0)