基于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 接口),通过「线程安全的规则容器 + 接口更新规则」实现动态过滤。

实现步骤(极简版)

  1. 封装动态规则
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); }
}
  1. 实现拦截器
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;
    }
}
  1. 注册拦截器 + 提供规则更新接口
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 拦截器。

实现步骤

  1. 实现动态 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;
    }
}
  1. 动态注册 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)

  1. 添加网关依赖
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>
  1. 实现动态全局过滤器
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; // 高优先级执行
    }
}
  1. Nacos 动态更新规则

    修改 Nacos 配置 blocked.ips=192.168.1.100,10.0.0.5,网关自动刷新规则,无需重启。

核心特点

  • ✅ 优点:集中管控所有微服务请求、规则动态推送、支持流量路由 / 限流 / 熔断一体化;
  • ❌ 缺点:需引入网关组件、增加部署复杂度、性能略低于本地过滤;
  • 🎯 适用:微服务集群的全局请求过滤(如跨服务 IP 封禁、接口限流)。

四、方案 4:自定义 FilterRegistrationBean(动态增删过滤器)

核心原理

通过 Spring 的 FilterRegistrationBean 动态注册 / 移除 Servlet Filter,实现「按需添加过滤规则」(如临时封禁某个接口)。

实现步骤

  1. 定义可动态注册的 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);
    }
}
  1. 动态注册 / 移除 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)

  1. 添加 Sentinel 依赖
xml
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  1. 动态配置 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";
    }
}
  1. 接口接入 Sentinel
java
运行
@GetMapping("/api/test")
@SentinelResource(value = "/api/test")
public String test() {
    return "正常响应";
}

核心特点

  • ✅ 优点:规则动态推送、支持 IP / 参数 / 接口多维度过滤、自带监控 / 告警、集成简单;
  • ❌ 缺点:需引入第三方组件、轻量场景略重;
  • 🎯 适用:高并发场景(如电商秒杀)的限流、熔断、IP 封禁。

六、方案 6:Nginx 动态配置(网关层 / 容器层)

核心原理

在 Nginx 层实现全局请求过滤,通过「配置中心 + Nginx 热加载」动态更新规则,无需修改应用代码,性能最优。

实现步骤

  1. 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;
        }
    }
}
  1. 动态更新配置 + 热加载 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
  1. 进阶:结合配置中心

    通过 Nacos/Apollo 推送 Nginx 配置,脚本自动更新 blocked_ips.conf 并热加载 Nginx,实现规则动态同步。

核心特点

  • ✅ 优点:性能极高(Nginx 原生处理)、全局管控所有请求、无需修改应用代码;
  • ❌ 缺点:规则同步有延迟(秒级)、需运维配合、不支持应用层复杂逻辑;
  • 🎯 适用:集群级全局 IP 封禁、域名 / 路径拦截(如防爬虫、恶意请求)。

三、方案选择建议

  1. 单体应用 + 轻量需求:优先选 Spring HandlerInterceptor(开发快)或 Servlet Filter(覆盖广);
  2. 微服务集群 + 集中管控:优先选 Spring Cloud Gateway(应用层)或 Nginx(容器层);
  3. 高并发 + 限流 / 熔断:优先选 Sentinel(集成简单、功能全);
  4. 临时过滤需求:优先选 FilterRegistrationBean(动态增删);
  5. 全局高性能过滤:优先选 Nginx(性能最优)或 Tomcat Valve(应用内全局)。

四、总结

除了 Tomcat 原生 Valve,实现动态请求过滤规则的核心方式可分为三类:
  1. 应用层:Spring HandlerInterceptor、Servlet Filter、FilterRegistrationBean(开发简单,适配业务逻辑);
  2. 网关层:Spring Cloud Gateway、Nginx(集中管控,性能优);
  3. 组件层:Sentinel 等第三方组件(功能全,适配高并发)。
选择的核心原则是:轻量场景选应用层(HandlerInterceptor/Filter),集群场景选网关层(Gateway/Nginx),高并发场景选组件层(Sentinel)。所有方案都需保证「规则存储线程安全、更新实时生效、逻辑轻量化」,避免影响请求性能。
阅读剩余
THE END
阿里云ECS特惠活动
阿里云ECS服务器 - 限时特惠活动

云服务器爆款直降90%

新客首单¥68起 | 人人可享99元套餐,续费同价 | u2a指定配置低至2.5折1年,立即选购享更多福利!

新客首单¥68起
人人可享99元套餐
弹性计费
7x24小时售后
立即查看活动详情
阿里云ECS服务器特惠活动