Filter和Interceptor的区别
Filter
(过滤器)和 Interceptor
(拦截器)都是用于在请求处理前后插入额外逻辑的组件,下面依次介绍,并额外介绍Spring Gateway的
过滤器(GlobalFilter/GatewayFilter
)和Spring Security
的过滤器(SecurityFilter
)
过滤器(Filter)
基本概念
-
所属规范:
Java Servlet
规范(javax.servlet.Filter
),只依赖于servlet
,不需要依赖spring
框架 -
作用层级:
Web
容器层(Tomcat/Jetty
等)。 -
拦截范围:所有
HTTP
请求(包括静态资源、JSP、Controller 等)。 -
执行时机:在请求进入
DispatcherServlet
之前执行。HTTP Request → Tomcat → Filter1 → Filter2 → ... → DispatcherServlet → Interceptor → Controller
核心方法
public interface Filter {
void init(FilterConfig filterConfig); // 初始化
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain); // 核心逻辑
void destroy(); // 销毁
}
init(FilterConfig filterConfig)
- 在过滤器实例被创建后由容器调用一次。
- 用于读取配置参数、初始化资源。
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- 每次请求都会调用。
- 可在调用
chain.doFilter()
前后添加逻辑:chain.doFilter(request, response)
表示放行,进入下一个过滤器或目标资源(如 Servlet)。- 可以在放行前做请求预处理,放行后做响应后处理。
destroy()
- 服务器关闭或过滤器被移除前调用。
- 用于释放资源。
自定义Filter
以springboot
项目中为例自定义日志Filter
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("LogFilter 初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI();
String ip = request.getRemoteAddr();
long start = System.currentTimeMillis();
System.out.println("[LogFilter] 请求路径: " + path + ", 来自 IP: " + ip);
chain.doFilter(request, response); // 放行
long duration = System.currentTimeMillis() - start;
System.out.println("[LogFilter] 请求耗时: " + duration + " ms");
}
@Override
public void destroy() {
System.out.println("LogFilter 销毁");
}
}
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<LogFilter> logFilterRegistration() {
FilterRegistrationBean<LogFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new LogFilter());
registration.addUrlPatterns("/*"); // 过滤所有请求
registration.setName("logFilter");
registration.setOrder(1); // 优先级,值越小越优先
return registration;
}
}
FilterRegistrationBean
是 Spring Boot 提供的一个工具类,用于在代码中显式注册一个自定义 Filter,而不依赖 @WebFilter
或 web.xml
。它封装了 Filter
的注册信息,允许你控制:
- 注册的 URL 路径(
addUrlPatterns
) - 执行顺序(
setOrder
) - 是否启用(
setEnabled
) - 初始化参数(
addInitParameter
)
拦截器(Interceptor)
基本概念
-
所属框架:Spring MVC(
HandlerInterceptor
)。 -
作用层级:Spring 框架层(仅拦截
Controller
请求)。 -
拦截范围:仅拦截
@RequestMapping
方法,不拦截静态资源。 -
执行时机:在
DispatcherServlet
之后、Controller
之前执行。HTTP Request → DispatcherServlet → Interceptor.preHandle() → Controller → Interceptor.postHandle() → 视图渲染 → Interceptor.afterCompletion()
核心方法
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler); // Controller 前执行
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView); // Controller 后执行
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); // 请求完成后执行
}
preHandle
- 时机: 在 Controller 的方法调用之前执行。
- 返回值:
- 返回
true
:继续流程(如调用下一个拦截器或 Controller 方法)。 - 返回
false
:中断流程,请求不会传到 Controller。
- 返回
- 常见用途: 登录校验、权限验证、请求签名校验等。
postHandle
- 时机: Controller 方法执行之后,视图渲染之前执行。
- 作用: 可以修改
ModelAndView
中的数据或视图。
afterCompletion
- 时机: 整个请求完成后(包括视图渲染后)执行。
- 作用: 用于资源清理、日志记录、异常处理等。
- 总会调用,除非服务器崩溃。
自定义Interceptor
// 实现 HandlerInterceptor
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("Interceptor: 请求前校验");
return true; // true=放行,false=拦截
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) {
System.out.println("Interceptor: 控制器执行后,视图渲染前");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
System.out.println("Interceptor: 请求完成后(视图渲染完毕)");
}
}
// 注册 Interceptor
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**"); // 拦截 /api 开头的路径
}
}
addInterceptors
是 Spring Boot 中用于注册自定义拦截器的方法,定义在 WebMvcConfigurer
接口中。
addInterceptor
:注册你的拦截器实例addPathPatterns
:指定哪些 URL 会被拦截(支持通配符,如/**
表示全部)excludePathPatterns
:指定哪些 URL 不被拦截
应用场景
Filter:(适用请求前统一处理)
- 请求/响应预处理:修改请求头、请求体或响应头、响应体
- 编码设置:统一设置请求和响应的字符编码
- 跨域处理:添加 CORS 相关头信息
- 登录验证:简单的身份验证(但不如Interceptor灵活)
- 日志记录:记录原始请求信息
- 静态资源过滤:对特定文件类型进行特殊处理
- 数据压缩:对响应内容进行压缩
Interceptor(适用controller
前后业务逻辑)
- 业务逻辑拦截:如权限验证、操作日志记录
- 用户认证:更细粒度的权限控制(如基于角色的访问控制)
- 性能监控:记录方法执行时间
- 参数校验:对Controller方法的参数进行校验
- AOP功能:实现类似面向切面编程的功能
执行顺序
若有两个filter
和两个interceptor
,执行顺序如下,Filter.before
是指放行前处理,Filter.after
是指放行后处理。
Request →
Filter1.before →
Filter2.before →
InterceptorA.preHandle →
InterceptorB.preHandle →
Controller →
InterceptorB.postHandle →
InterceptorA.postHandle →
InterceptorB.afterCompletion →
InterceptorA.afterCompletion →
Filter2.after →
Filter1.after →
Response ←
Spring Cloud Gateway
基本概念
-
所属框架:
Spring Cloud Gateway,
基于 WebFlux 的过滤器链(非Servlet
体系)。WebFlux
是Spring Framework 5
引入的一个全新基于 Reactor 构建响应式编程框架,用于构建非阻塞、异步的 Web 应用程序。它是Spring MVC
的补充,特别适合需要高并发、低延迟的场景(如实时数据处理、流式 API 或 I/O 密集型应用)。 -
作用层级:API 网关层(在请求到达微服务前)。
-
拦截范围:所有经过 Gateway 的请求(可路由到不同服务)。
-
执行时机:在请求被转发到目标服务前执行。
HTTP Request → WebFlux 底层 → GlobalFilter1 → GlobalFilter2 → GatewayFilter → 路由转发到目标服务
-
过滤器类型:
- GlobalFilter:全局过滤器,对所有路由生效。
- GatewayFilter:针对特定路由的过滤器。需要在路由规则中显式声明(通过
filters
字段)。
-
特点:
- 非阻塞(基于 Reactor 模型)。
- 可修改请求/响应(如添加 Header、重定向)。
核心接口
public interface GlobalFilter {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
ServerWebExchange exchange
:封装了 HTTP 请求和响应的信息。GatewayFilterChain chain
:用于将请求传递给下一个过滤器。
自定义GatewayFilter
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 请求前逻辑
System.out.println(">>> 请求路径:" + exchange.getRequest().getURI());
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 响应后逻辑
System.out.println("<<< 响应状态码:" + exchange.getResponse().getStatusCode());
}));
}
@Override
public int getOrder() {
return 0; // 数值越小,优先级越高
}
}
Spring Security
基本概念
-
所属框架:
Spring Security
,基于 Servlet 过滤器链(FilterChainProxy
)。 -
作用层级:应用安全层(在请求到达
Controller
前)。 -
拦截范围:所有进入
Spring MVC
的请求(可配置忽略静态资源)。 -
执行时机:在
DispatcherServlet
之前HTTP Request → Spring Security 过滤器链 → DispatcherServlet -> Controller
-
特点:
- 阻塞式(基于 Servlet 规范)。
- 专注于认证(Authentication)和授权(Authorization)。
核心过滤器链
Spring Security
的过滤器链(FilterChainProxy
)包含多个 核心过滤器,例如:
过滤器类 | 说明 |
---|---|
SecurityContextPersistenceFilter | 加载与保存 SecurityContext |
UsernamePasswordAuthenticationFilter | 表单登录认证 |
BasicAuthenticationFilter | HTTP Basic 认证 |
BearerTokenAuthenticationFilter | Bearer Token(如 OAuth2 或 JWT)认证 |
ExceptionTranslationFilter | 处理认证异常和权限异常 |
FilterSecurityInterceptor | 最终权限校验逻辑 |
CsrfFilter | CSRF 防护 |
LogoutFilter | 处理退出登录 |
AuthorizationFilter | 授权过滤器(Spring Security 6 引入) |
如何使用这些核心过滤器?
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable()) // 配置 CsrfFilter(禁用)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN") // 配置 FilterSecurityInterceptor 的权限规则
.anyRequest().authenticated()
)
.formLogin(withDefaults()) // 开启 UsernamePasswordAuthenticationFilter
.logout(withDefaults()) // 开启 LogoutFilter
.build();
}
配置语句 | 对应过滤器 |
---|---|
csrf().disable() | CsrfFilter |
authorizeHttpRequests() | FilterSecurityInterceptor |
formLogin() | UsernamePasswordAuthenticationFilter |
logout() | LogoutFilter |
自定义过滤器
推荐继承 OncePerRequestFilter
类,因为 OncePerRequestFilter
可以确保每个请求只被过滤一次。
public class CustomFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 在这里添加自定义逻辑
System.out.println("CustomFilter is processing the request");
// 继续执行过滤器链
filterChain.doFilter(request, response);
}
}
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class); // 在UsernamePasswordAuthenticationFilter 之前添加自定义过滤器
return http.build();
}
}
执行流程总览
如果一个项目中集成了Spring Cloud Gateway
和 Spring Security
Servlet Filter
、Interceptor
、Spring Gateway Filter
、Spring Security FilterChain
的执行顺序
HTTP Request
├─ 0. 进入网关服务
│
├─ 1. Spring Gateway Filter(GlobalFilter/GatewayFilter)
│
├─ 2. Spring Security FilterChain(SecurityFilter)
│
├─ 3. 路由转发到目标服务
│
├─ 4. Servlet Filter(如 CharacterEncodingFilter)
│
├─ 5. DispatcherServlet(Spring MVC 入口)
│
├─ 6. HandlerInterceptor(preHandle)
│
├─ 7. Controller 方法
│
├─ 8. HandlerInterceptor(postHandle)
│
├─ 9. 视图渲染(如 Thymeleaf)
│
└─ 10. HandlerInterceptor(afterCompletion)