如何在 Spring Cloud Gateway 中创建全局过滤器、局部过滤器和自定义条件过滤器
Spring Cloud Gateway 是一个功能强大的 API 网关,能够处理 HTTP 请求、响应及路由。通过过滤器机制,您可以在请求和响应过程中进行各种处理操作,如记录日志、身份验证、限流等。Spring Cloud Gateway 提供了三种主要类型的过滤器:全局过滤器、局部过滤器和自定义条件过滤器。本文将详细介绍如何在 Spring Cloud Gateway 中创建和使用这些过滤器。
1. 全局过滤器(Global Filter)
全局过滤器是应用于所有请求的过滤器,无论请求被路由到哪个目标服务,都会先经过这些过滤器。全局过滤器适用于需要对所有请求进行操作的场景,如日志记录、请求限流、身份验证等。
创建全局过滤器的步骤
步骤 1:实现 GlobalFilter
接口
要创建全局过滤器,您需要实现 GlobalFilter
接口,并重写 filter
方法。以下是一个简单的全局过滤器,它记录请求的开始时间,并在请求完成后输出请求的处理时长。
示例代码:全局过滤器
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import reactor.core.publisher.Mono;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 记录开始时间
long startTime = System.currentTimeMillis();
exchange.getAttributes().put("startTime", startTime);
// 继续执行后续过滤器
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 计算并输出请求时长
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
log.info("Request completed in " + duration + "ms");
}));
}
}
步骤 2:设置过滤器的执行顺序(可选)
GlobalFilter
接口继承自 Ordered
接口,您可以通过 getOrder()
方法设置过滤器的执行顺序。返回值越小,优先级越高。
@Override
public int getOrder() {
return -1; // 高优先级
}
步骤 3:配置全局过滤器
使用 @Component
注解注册全局过滤器,Spring 会自动将其作为全局过滤器进行管理。
2. 局部过滤器(Local Filter)
局部过滤器是应用于特定路由或请求路径的过滤器。它仅在匹配特定路由或条件时执行,适用于只对某些服务、路径或请求类型进行处理的场景。
创建局部过滤器的步骤
步骤 1:实现 GatewayFilter
接口
局部过滤器需要实现 GatewayFilter
接口。以下是一个简单的局部过滤器,它检查请求的路径并在符合条件时记录日志。
示例代码:局部过滤器
import org.springframework.stereotype.Component;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class MyLocalFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 获取请求路径
String path = exchange.getRequest().getURI().getPath();
log.info("Request path: " + path);
// 继续执行后续过滤器
return chain.filter(exchange);
}
}
步骤 2:通过 RouteLocator
配置路由
在 Spring Cloud Gateway 中,您可以通过 RouteLocator
或 YAML 配置文件为特定的路由添加局部过滤器。
示例代码:配置局部过滤器
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.RouteLocatorBuilder;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("my_route", r -> r
.path("/api/**") // 匹配 /api/** 路径的请求
.filters(f -> f.filter(new MyLocalFilter())) // 应用 MyLocalFilter
.uri("http://example.com")) // 目标服务
.build();
}
}
在这个例子中,我们创建了一个名为 my_route
的路由,它只对 /api/**
路径的请求应用 MyLocalFilter
过滤器。
方法二:基于 YAML 配置
如果你使用 YAML 配置文件来配置路由,也可以在 application.yml
文件中指定过滤器。
spring:
cloud:
gateway:
routes:
- id: example_route
uri: http://example.com
predicates:
- Path=/api/v1/**
filters:
- name: MyLocalFilter # 使用你定义的过滤器
为了通过 YAML 使用自定义过滤器,你需要确保在配置中通过 Spring Bean 名称引用该过滤器。若 MyLocalFilter
被 Spring 管理(通过 @Component
),可以直接使用 name
来引用。
3. 自定义条件过滤器(Custom Condition Filter)
自定义条件过滤器是根据特定的条件(如请求的查询参数、请求头或路径等)来动态决定是否执行过滤器。这种过滤器提供了更高的灵活性和复杂的过滤逻辑。
创建自定义条件过滤器的步骤
步骤 1:继承 AbstractGatewayFilterFactory
创建过滤器工厂
Spring Cloud Gateway 提供了 AbstractGatewayFilterFactory
类,允许您创建自定义的过滤器工厂。您可以在工厂中设置过滤器的配置项,并根据条件来执行过滤逻辑。
示例代码:自定义条件过滤器
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerHttpRequest;
import org.springframework.http.HttpStatus;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {
public MyGatewayFilterFactory() {
super(MyGatewayFilterFactory.Config.class); // 指定配置类
}
@Override
public GatewayFilter apply(MyGatewayFilterFactory.Config config) {
// 创建实际的过滤器
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
System.out.println("进入了自定义网关过滤器,status:" + config.getStatus());
// 检查请求的查询参数
if (request.getQueryParams().containsKey("atguigu")) {
return chain.filter(exchange); // 继续请求
} else {
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST); // 返回 400 错误
return exchange.getResponse().setComplete(); // 完成响应
}
}
};
}
// 配置快捷字段的顺序
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("status"); // 配置字段名
}
// 配置类,保存过滤器的参数
public static class Config {
private String status; // 配置字段
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
}
步骤 2:在配置文件中应用自定义过滤器
您可以通过 YAML 或 Java 配置文件指定在哪些路由上应用此自定义条件过滤器,并传递参数。
示例代码:在 application.yml
中配置自定义过滤器
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://example.com
predicates:
- Path=/api/** # 匹配 /api/** 路径的请求
filters:
- name: MyGatewayFilterFactory # 引用自定义的过滤器
args:
status: "active" # 配置 status 参数
4. 过滤器类型比较
特性 | 全局过滤器 (Global Filter) | 局部过滤器 (Local Filter) | 自定义条件过滤器 (Custom Condition Filter) |
---|---|---|---|
适用范围 | 所有请求 | 特定路由或路径的请求 | 基于特定条件,如请求参数、路径等,动态判断是否执行 |
使用场景 | 日志记录、全局认证、全局限流等 | 特定服务或路径的处理 | 根据条件(如请求参数、头部等)动态处理请求 |
配置方式 | 通过实现 GlobalFilter 接口并注册为 Spring Bean | 通过 RouteLocator 或 YAML 配置路由 | 通过 AbstractGatewayFilterFactory 创建工厂 |
5. 总结
在 Spring Cloud Gateway 中,您可以根据不同的需求创建三种类型的过滤器:
- 全局过滤器:适用于需要对所有请求进行统一处理的场
景,例如日志记录、认证和授权。
- 局部过滤器:适用于特定路由或路径的请求,能够灵活地控制不同服务的请求处理。
- 自定义条件过滤器:根据请求的特定条件(如查询参数、请求头、路径等)动态决定是否执行过滤器逻辑,提供更高的灵活性。