Spring Cloud Gateway 中的自定义过滤器
在 Spring Cloud Gateway 中,过滤器是用于对请求和响应进行预处理和后处理的组件。通过自定义过滤器,您可以控制请求的生命周期,做如日志记录、身份认证、限流、重试、请求改写等操作。Spring Cloud Gateway 允许您创建 Global Filters(全局过滤器)和 Gateway Filters(局部过滤器),它们可以在不同的场景下提供灵活的定制。
下面我们将深入介绍如何在 Spring Cloud Gateway 中实现自定义过滤器。
1. 过滤器的种类
Spring Cloud Gateway 提供了三种类型的过滤器:
- Global Filters(全局过滤器):对所有路由生效的过滤器。常用于全局性的跨路由处理。
- Gateway Filters(局部过滤器):仅对特定路由生效的过滤器。
- Pre and Post Filters(前置和后置过滤器):
- Pre Filters:请求到达路由之前执行,适用于身份验证、日志记录等。
- Post Filters:请求到达路由后,返回响应之前执行,适用于响应修改、日志记录等。
2. 创建自定义过滤器
2.1 创建一个简单的 GatewayFilter
我们首先来创建一个简单的局部过滤器,它会记录每个请求的路径。
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> {
// 定义配置类
public static class Config {
// 可定义配置参数
private String prefix;
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
}
// 构造器
public CustomGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
// 返回一个自定义的过滤器
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getURI().getPath();
System.out.println("Request path: " + config.getPrefix() + path);
return chain.filter(exchange); // 放行请求
}
};
}
}
解释:
CustomGatewayFilterFactory
继承了AbstractGatewayFilterFactory
,并实现了apply()
方法,返回一个具体的过滤器。- 配置类
Config
可以用来传递配置参数,如添加请求路径的前缀。 filter()
方法中的ServerWebExchange
可以获取请求的详细信息,GatewayFilterChain
用于继续链式处理请求。
2.2 注册自定义过滤器
自定义过滤器需要注册到 Spring Boot 上,以便在配置文件中应用。您可以通过 @Component
注解自动注册,也可以通过手动配置方式注册。
通过 @Component
自动注册:
- 直接使用
@Component
注解使得过滤器在 Spring 容器中注册,Spring Boot 会自动扫描和创建实例。
通过手动注册:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
@Configuration
public class GatewayFilterConfig {
@Bean
public GatewayFilterFactory customGatewayFilterFactory() {
return new CustomGatewayFilterFactory();
}
}
3. 配置过滤器应用于路由
一旦我们创建了自定义的过滤器,就可以在 application.yml
配置文件中将其应用到特定的路由。
spring:
cloud:
gateway:
routes:
- id: custom_route
uri: http://httpbin.org:80
predicates:
- Path=/get
filters:
- name: CustomGatewayFilterFactory
args:
prefix: "Request path: "
解释:
name: CustomGatewayFilterFactory
表示使用我们自定义的过滤器。args
部分传递了配置参数(例如,prefix
)到过滤器。
4. 全局过滤器的实现
全局过滤器是对所有路由生效的,可以通过实现 GlobalFilter
接口来创建全局过滤器。
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class CustomGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getURI().getPath();
System.out.println("Global filter: Request path: " + path);
return chain.filter(exchange); // 放行请求
}
}
解释:
- 实现
GlobalFilter
接口并覆盖filter()
方法。 - 这个过滤器会在每次请求进入网关时执行,适用于全局场景。
5. 高级过滤器:认证与权限控制
在实际项目中,过滤器常常用于实现认证与权限控制。比如我们可以在 pre
过滤器中检查请求的 Authorization 头信息,并判断用户是否有权限访问该路由。
@Component
public class AuthenticationFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (token == null || !isValidToken(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete(); // 返回 401 状态码
}
return chain.filter(exchange); // 验证成功,放行请求
}
private boolean isValidToken(String token) {
// 这里实现具体的 token 校验逻辑
return token.equals("valid_token");
}
}
解释:
AuthenticationFilter
会在每个请求中检查是否存在Authorization
头。- 如果没有 token 或者 token 无效,则返回
401 Unauthorized
状态码。
6. 过滤器的执行顺序
- 前置过滤器:
GatewayFilter
的前置过滤器会在请求到达目标服务之前执行,可以用来修改请求、验证身份、日志记录等。 - 后置过滤器:
PostFilter
会在目标服务响应后执行,可以用来修改响应、日志记录、性能分析等。
Spring Cloud Gateway 提供了丰富的过滤器,可以在路由配置中灵活组合它们。
spring:
cloud:
gateway:
routes:
- id: route1
uri: http://httpbin.org:80
predicates:
- Path=/get
filters:
- name: RequestTimeGatewayFilterFactory
7. 结论
在 Spring Cloud Gateway 中,过滤器为处理请求和响应提供了灵活的处理机制。通过自定义过滤器,您可以轻松实现认证、权限校验、日志记录、请求重定向等功能。具体应用时可以根据需要创建 全局过滤器 或 局部过滤器。
在开发过程中,建议:
- 使用 全局过滤器 处理与所有路由相关的操作,如认证、日志等。
- 使用 局部过滤器 实现特定路由的功能,如请求路径修改、负载均衡等。
过滤器不仅提供了强大的功能扩展点,还能帮助优化性能、增强安全性和灵活性,充分发挥 Spring Cloud Gateway 的优势。
发表回复