














@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("Filter 前置处理");
chain.doFilter(request, response); // 放行
System.out.println("Filter 后置处理");
}
@Override
public void destroy() {
// 销毁
}
}
方式一:@WebFilter 注解(需在启动类加 @ServletComponentScan)
@SpringBootApplication
@ServletComponentScan
public class Application { }
方式二:FilterRegistrationBean 配置
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> myFilter() {
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new MyFilter());
bean.addUrlPatterns("/*");
bean.setOrder(1);
return bean;
}
}
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println("preHandle:Controller 执行前");
// 返回 false 则中断请求
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle:Controller 执行后,视图渲染前");
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
System.out.println("afterCompletion:视图渲染后");
}
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login", "/static/**")
.order(1);
}
}
| 方法 | 执行时机 | 常见用途 |
|---|---|---|
preHandle |
Controller 方法执行前 | 登录校验、权限校验、参数校验 |
postHandle |
Controller 执行后,视图渲染前 | 修改 ModelAndView、日志 |
afterCompletion |
视图渲染后(请求完成) | 资源清理、耗时统计 |
注意:若
preHandle返回false,后续的postHandle和afterCompletion都不会执行(但已通过的前置拦截器的afterCompletion会执行)。
五、执行顺序
多个 Filter:按 @Order 或注册顺序执行,chain.doFilter 之前正序,之后逆序。
多个 Filter 组成过滤器链时,代码的执行顺序。核心点在于:chain.doFilter() 是一个"分界线",它之前和之后的代码执行方向相反。
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
// ① chain.doFilter 之前的代码
System.out.println("前置");
chain.doFilter(req, resp); // ② 放行,进入下一个 Filter 或目标资源
// ③ chain.doFilter 之后的代码
System.out.println("后置");
}
① 之前:请求进入时执行(前置处理)
② 放行:把请求交给链中的下一个环节
③ 之后:下一个环节处理完、返回响应时执行(后置处理)
所以同一个 Filter 内部就是"先进后出"的栈式结构。
假设注册顺序(或 @Order 值)为:
FilterA (order = 1)
FilterB (order = 2)
代码:
public class FilterA implements Filter {
public void doFilter(...) {
System.out.println("A - 前置");
chain.doFilter(req, resp);
System.out.println("A - 后置");
}
}
public class FilterB implements Filter {
public void doFilter(...) {
System.out.println("B - 前置");
chain.doFilter(req, resp);
System.out.println("B - 后置");
}
}
执行结果:
A - 前置
B - 前置
← 到达 Controller / 目标资源
B - 后置
A - 后置
可以把过滤器链想象成洋葱或递归调用:
A.doFilter 开始
│
├─ 打印 "A-前置"
│
├─ chain.doFilter() → 进入 B
│ │
│ ├─ 打印 "B-前置"
│ │
│ ├─ chain.doFilter() → 进入 Controller
│ │ │
│ │ └─ 处理请求,返回
│ │
│ ├─ 打印 "B-后置" ← 从 Controller 返回后
│ │
│ └─ B 结束
│
├─ 打印 "A-后置" ← 从 B 返回后
│
└─ A 结束
多个 Interceptor:
preHandle:按注册顺序正序执行
postHandle:按注册顺序逆序执行
afterCompletion:按注册顺序逆序执行
Filter 与 Interceptor 的顺序:
Filter.pre → Interceptor.preHandle → Controller
→ Interceptor.postHandle → Interceptor.afterCompletion → Filter.post
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。