基于Tomcat原生的Valve,其他方式可以实现的动态请求过滤规则
除了 Tomcat 原生
Valve 之外,还有哪些方式能在 Spring Boot 中实现动态请求过滤规则(如封禁 IP、拦截接口、限流等),核心思路是从「应用层、网关层、容器层」三个维度出发,覆盖不同粒度的过滤需求。以下是 6 种主流方案,包含适用场景、实现步骤、优缺点对比,方便你根据业务场景选择。核心选型维度
所有方案的核心目标都是「运行时动态更新过滤规则,无需重启应用」,区别在于过滤粒度、性能、开发成本、适用场景,先看整体对比:
表格
| 实现方式 | 技术核心 | 过滤粒度 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|---|
| Spring HandlerInterceptor | Spring 拦截器 | 应用层(仅 Spring 接口) | 开发简单、与 Spring 生态深度融合 | 不拦截静态资源 / 非 Spring 接口 | 业务接口级过滤(如接口限流、IP 封禁) |
| Spring Cloud Gateway 过滤器 | Gateway Filter | 网关层(所有入站请求) | 集中管控、支持微服务、规则动态更新 | 需引入网关组件,增加部署成本 | 微服务集群的全局请求过滤 |
| Servlet Filter | 原生 Servlet 过滤器 | 应用层(所有 Servlet 请求) | 标准规范、覆盖所有接口 / 静态资源 | 配置相对繁琐,优先级低于 Valve | 单体应用的全局请求过滤 |
| 自定义 FilterRegistrationBean | Spring 动态注册 Filter | 应用层(按需指定路径) | 运行时动态添加 / 移除过滤器 | 需手动管理 Filter 生命周期 | 临时 / 按需的请求过滤(如临时封禁) |
| 第三方组件(如 Sentinel) | 限流 / 熔断组件 | 接口 / IP / 参数维度 | 规则动态推送、监控告警一体化 | 需引入第三方依赖,学习成本高 | 高并发场景的限流、熔断、IP 封禁 |
| Nginx 动态配置 | Nginx + 配置中心 | 网关层(所有入站请求) | 性能极高、全局管控、无需修改应用代码 | 规则同步有延迟,需运维配合 | 集群级全局 IP 封禁、域名 / 路径拦截 |
一、方案 1:Spring HandlerInterceptor(应用层首选)
核心原理
Spring 提供的拦截器,拦截
DispatcherServlet 处理的所有请求(即 Spring 接口),通过「线程安全的规则容器 + 接口更新规则」实现动态过滤。实现步骤(极简版)
- 封装动态规则:
java
运行
@Component
public class DynamicRuleManager {
// 线程安全的封禁IP列表
private Set<String> blockedIps = ConcurrentHashMap.newKeySet();
// 动态更新规则
public void addBlockedIp(String ip) { blockedIps.add(ip); }
public boolean isBlocked(String ip) { return blockedIps.contains(ip); }
}
- 实现拦截器:
java
运行
@Component
public class DynamicInterceptor implements HandlerInterceptor {
@Autowired
private DynamicRuleManager ruleManager;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String ip = request.getRemoteAddr();
if (ruleManager.isBlocked(ip)) {
response.setStatus(403);
response.getWriter().write("IP已封禁");
return false;
}
return true;
}
}
- 注册拦截器 + 提供规则更新接口:
java
运行
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private DynamicInterceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor).addPathPatterns("/**");
}
}
// 规则更新接口
@RestController
@RequestMapping("/rule")
public class RuleController {
@Autowired
private DynamicRuleManager ruleManager;
@PostMapping("/blockIp")
public String blockIp(@RequestParam String ip) {
ruleManager.addBlockedIp(ip);
return "IP封禁成功";
}
}
核心特点
- ✅ 优点:开发成本极低、与 Spring 无缝集成、支持注解 / 参数级过滤;
- ❌ 缺点:仅拦截 Spring 接口(静态资源、非 Spring Servlet 不生效);
- 🎯 适用:单体应用的业务接口过滤(如接口级 IP 封禁、参数校验)。
二、方案 2:Servlet 原生 Filter(应用层全局过滤)
核心原理
基于 Servlet 标准的
Filter,拦截所有通过 Servlet 容器的请求(包括静态资源、非 Spring 接口),优先级低于 Tomcat Valve,但高于 Spring 拦截器。实现步骤
- 实现动态 Filter:
java
运行
@Component
public class DynamicServletFilter implements Filter {
private volatile Set<String> blockedIps = ConcurrentHashMap.newKeySet();
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String ip = req.getRemoteAddr();
if (blockedIps.contains(ip)) {
((HttpServletResponse) response).setStatus(403);
response.getWriter().write("IP已封禁(Servlet Filter)");
return;
}
chain.doFilter(request, response);
}
// 动态更新规则
public void updateBlockedIps(Set<String> ips) {
this.blockedIps = ips;
}
}
- 动态注册 Filter(可选):
若需运行时添加 / 移除 Filter,用
FilterRegistrationBean:
java
运行
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<DynamicServletFilter> dynamicFilter() {
FilterRegistrationBean<DynamicServletFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new DynamicServletFilter());
bean.addUrlPatterns("/*"); // 拦截所有请求
bean.setOrder(1); // 执行优先级(数字越小越先执行)
return bean;
}
}
核心特点
- ✅ 优点:符合 Servlet 标准、覆盖所有 Servlet 请求(静态资源 / 接口)、开发简单;
- ❌ 缺点:优先级低于 Tomcat Valve、不支持 Tomcat 底层请求(如 AJP 协议);
- 🎯 适用:单体应用的全局请求过滤(如所有请求的 IP 封禁、请求头校验)。
三、方案 3:Spring Cloud Gateway 过滤器(网关层全局过滤)
核心原理
在微服务网关层实现请求过滤,规则存储在配置中心(Nacos/Apollo),动态推送更新,所有微服务的请求都经过网关过滤,实现「集中管控」。
实现步骤(基于 Gateway + Nacos)
- 添加网关依赖:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 实现动态全局过滤器:
java
运行
@Component
public class DynamicGatewayFilter implements GlobalFilter, Ordered {
// 从 Nacos 动态获取封禁IP列表(配置中心推送)
@Value("${blocked.ips:}")
private Set<String> blockedIps;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
if (blockedIps.contains(ip)) {
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100; // 高优先级执行
}
}
- Nacos 动态更新规则:
修改 Nacos 配置
blocked.ips=192.168.1.100,10.0.0.5,网关自动刷新规则,无需重启。
核心特点
- ✅ 优点:集中管控所有微服务请求、规则动态推送、支持流量路由 / 限流 / 熔断一体化;
- ❌ 缺点:需引入网关组件、增加部署复杂度、性能略低于本地过滤;
- 🎯 适用:微服务集群的全局请求过滤(如跨服务 IP 封禁、接口限流)。
四、方案 4:自定义 FilterRegistrationBean(动态增删过滤器)
核心原理
通过 Spring 的
FilterRegistrationBean 动态注册 / 移除 Servlet Filter,实现「按需添加过滤规则」(如临时封禁某个接口)。实现步骤
- 定义可动态注册的 Filter:
java
运行
public class TemporaryBlockFilter implements Filter {
private String blockPath; // 要拦截的路径
public TemporaryBlockFilter(String blockPath) {
this.blockPath = blockPath;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getRequestURI();
if (path.equals(blockPath)) {
((HttpServletResponse) response).setStatus(503);
response.getWriter().write("接口临时维护");
return;
}
chain.doFilter(request, response);
}
}
- 动态注册 / 移除 Filter:
java
运行
@RestController
@RequestMapping("/filter")
public class DynamicFilterController {
@Autowired
private ApplicationContext context;
// 动态添加过滤器(拦截 /api/test)
@PostMapping("/add")
public String addFilter() {
FilterRegistrationBean<TemporaryBlockFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new TemporaryBlockFilter("/api/test"));
bean.addUrlPatterns("/*");
bean.register(context); // 动态注册
return "过滤器已添加,拦截 /api/test";
}
// 动态移除过滤器
@PostMapping("/remove")
public String removeFilter() {
FilterRegistrationBean<TemporaryBlockFilter> bean = context.getBean(FilterRegistrationBean.class);
bean.unregister(); // 动态移除
return "过滤器已移除";
}
}
核心特点
- ✅ 优点:运行时动态增删过滤器、按需拦截指定路径、无侵入式;
- ❌ 缺点:需手动管理 Filter 生命周期、规则复杂时维护成本高;
- 🎯 适用:临时过滤需求(如接口临时维护、活动结束后移除过滤)。
五、方案 5:第三方组件(如 Sentinel/Spring Cloud Alibaba)
核心原理
基于成熟的限流 / 熔断组件(如 Sentinel),通过「规则动态推送」实现 IP 封禁、接口限流、参数过滤等,自带监控和告警能力。
实现步骤(基于 Sentinel)
- 添加 Sentinel 依赖:
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 动态配置 IP 黑名单规则:
java
运行
@RestController
@RequestMapping("/sentinel")
public class SentinelRuleController {
// 动态添加 IP 黑名单规则
@PostMapping("/blockIp")
public String blockIp(@RequestParam String ip) {
// 构建 IP 黑名单规则
AuthorityRule rule = new AuthorityRule();
rule.setResource("/api/test"); // 要保护的资源
rule.setStrategy(AuthorityRuleType.BLACK); // 黑名单
rule.setLimitApp(ip); // 封禁的IP
// 推送规则到 Sentinel
AuthorityRuleManager.loadRules(Collections.singletonList(rule));
return "IP " + ip + " 已封禁访问 /api/test";
}
}
- 接口接入 Sentinel:
java
运行
@GetMapping("/api/test")
@SentinelResource(value = "/api/test")
public String test() {
return "正常响应";
}
核心特点
- ✅ 优点:规则动态推送、支持 IP / 参数 / 接口多维度过滤、自带监控 / 告警、集成简单;
- ❌ 缺点:需引入第三方组件、轻量场景略重;
- 🎯 适用:高并发场景(如电商秒杀)的限流、熔断、IP 封禁。
六、方案 6:Nginx 动态配置(网关层 / 容器层)
核心原理
在 Nginx 层实现全局请求过滤,通过「配置中心 + Nginx 热加载」动态更新规则,无需修改应用代码,性能最优。
实现步骤
- Nginx 配置基础过滤规则:
nginx
# nginx.conf
http {
# 引入动态配置文件(存储封禁IP)
include /etc/nginx/conf.d/blocked_ips.conf;
server {
listen 80;
server_name example.com;
# IP 封禁规则
if ($blocked_ip) {
return 403;
}
# 路径拦截规则
location /api/test {
if ($blocked_path) {
return 503;
}
proxy_pass http://backend;
}
}
}
- 动态更新配置 + 热加载 Nginx:
bash
运行
# 1. 修改 blocked_ips.conf,添加封禁IP
echo "map \$remote_addr \$blocked_ip { default 0; 192.168.1.100 1; }" > /etc/nginx/conf.d/blocked_ips.conf
# 2. 热加载 Nginx 配置(无需重启,不中断服务)
nginx -s reload
- 进阶:结合配置中心:
通过 Nacos/Apollo 推送 Nginx 配置,脚本自动更新
blocked_ips.conf并热加载 Nginx,实现规则动态同步。
核心特点
- ✅ 优点:性能极高(Nginx 原生处理)、全局管控所有请求、无需修改应用代码;
- ❌ 缺点:规则同步有延迟(秒级)、需运维配合、不支持应用层复杂逻辑;
- 🎯 适用:集群级全局 IP 封禁、域名 / 路径拦截(如防爬虫、恶意请求)。
三、方案选择建议
- 单体应用 + 轻量需求:优先选
Spring HandlerInterceptor(开发快)或Servlet Filter(覆盖广); - 微服务集群 + 集中管控:优先选
Spring Cloud Gateway(应用层)或Nginx(容器层); - 高并发 + 限流 / 熔断:优先选
Sentinel(集成简单、功能全); - 临时过滤需求:优先选
FilterRegistrationBean(动态增删); - 全局高性能过滤:优先选
Nginx(性能最优)或 TomcatValve(应用内全局)。
四、总结
除了 Tomcat 原生
Valve,实现动态请求过滤规则的核心方式可分为三类:- 应用层:Spring HandlerInterceptor、Servlet Filter、FilterRegistrationBean(开发简单,适配业务逻辑);
- 网关层:Spring Cloud Gateway、Nginx(集中管控,性能优);
- 组件层:Sentinel 等第三方组件(功能全,适配高并发)。
选择的核心原则是:轻量场景选应用层(HandlerInterceptor/Filter),集群场景选网关层(Gateway/Nginx),高并发场景选组件层(Sentinel)。所有方案都需保证「规则存储线程安全、更新实时生效、逻辑轻量化」,避免影响请求性能。
阅读剩余
版权声明:
作者:SE_Yang
链接:https://www.cnesa.cn/10656.html
文章版权归作者所有,未经允许请勿转载。
THE END
阿里云ECS服务器 - 限时特惠活动
云服务器爆款直降90%
新客首单¥68起 | 人人可享99元套餐,续费同价 | u2a指定配置低至2.5折1年,立即选购享更多福利!
新客首单¥68起
人人可享99元套餐
弹性计费
7x24小时售后