1. 什么是拦截器?一个生动的比喻 🎭
想象一下你去电影院看电影的流程:
- 检票员检查票(preHandle)- 没有票就不能进去
- 你看电影(Controller处理请求)
- 散场时工作人员引导(postHandle)- 电影结束后的处理
- 你离开影院,清洁工打扫(afterCompletion)- 最后的收尾工作
拦截器就是这个"检票员+工作人员+清洁工"的组合,它在请求处理的不同阶段执行一些操作。
2. 拦截器的三个重要方法 📋
拦截器有三个关键方法,对应三个不同时间点:
public class MyInterceptor implements HandlerInterceptor {
// 方法1:控制器执行前调用 - 像检票员
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println("❶ 检票员:正在检查你的票...");
return true; // true=通过, false=拒绝
}
// 方法2:控制器执行后调用 - 像散场工作人员
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("❷ 工作人员:电影结束了,请慢慢离场...");
}
// 方法3:整个请求完成后调用 - 像清洁工
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("❸ 清洁工:观众已离场,开始打扫卫生...");
}
}
3. 如何配置拦截器? 🛠️
方式1:XML配置(传统但清晰)
在springmvc.xml文件中添加:
<!-- 告诉SpringMVC我们要使用拦截器 -->
<mvc:interceptors>
<!-- 定义一个拦截器 -->
<mvc:interceptor>
<!-- 拦截所有请求 -->
<mvc:mapping path="/**"/>
<!-- 指定使用哪个拦截器类 -->
<bean class="com.example.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
方式2:Java配置(现代推荐)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**"); // 拦截所有路径
}
}
4. 实际应用:登录检查 🔐
让我们看一个最常用的例子:检查用户是否登录
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 获取Session中的用户信息
HttpSession session = request.getSession();
Object user = session.getAttribute("user");
// 如果用户未登录
if (user == null) {
// 重定向到登录页面
response.sendRedirect(request.getContextPath() + "/login");
return false; // 中断请求,不让它继续执行
}
return true; // 用户已登录,放行
}
}
配置这个登录拦截器:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/**"/> <!-- 拦截用户相关路径 -->
<mvc:mapping path="/admin/**"/> <!-- 拦截管理相关路径 -->
<mvc:exclude-mapping path="/login"/> <!-- 不拦截登录页面 -->
<bean class="com.example.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
5. 多个拦截器的执行顺序 🔢
如果有多个拦截器,它们的执行顺序是这样的:
请求 → 拦截器1.preHandle → 拦截器2.preHandle → Controller
→ 拦截器2.postHandle → 拦截器1.postHandle → 视图渲染
→ 拦截器2.afterCompletion → 拦截器1.afterCompletion → 响应
记忆技巧:
preHandle:按配置顺序执行(1→2→3)postHandle和afterCompletion:按配置逆序执行(3→2→1)
6. 拦截器 vs 过滤器:有什么区别? 🤔
| 特性 | 拦截器 (Interceptor) | 过滤器 (Filter) |
|---|---|---|
| 工作层面 | SpringMVC层面 | Servlet层面 |
| 依赖 | 依赖Spring框架 | 只依赖Servlet API |
| 使用场景 | 业务逻辑处理 | 通用功能(编码、安全等) |
| 获取Bean | 可以获取Spring容器中的Bean | 不能直接获取 |
简单说:过滤器是"大门保安",拦截器是"楼层管理员"。
7. 常见问题及解决方案 ❓
问题1:静态资源也被拦截了
解决方案: 排除静态资源路径
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/css/**"/> <!-- 排除CSS -->
<mvc:exclude-mapping path="/js/**"/> <!-- 排除JS -->
<mvc:exclude-mapping path="/images/**"/><!-- 排除图片 -->
<bean class="com.example.MyInterceptor"/>
</mvc:interceptor>
问题2:拦截器不生效
检查清单:
- 拦截器配置路径是否正确
- 拦截器类是否被Spring管理
- 是否有多個拦截器冲突
8. 总结 🎯
| 概念 | 说明 | 类比 |
|---|---|---|
| preHandle | 控制器执行前调用,返回boolean | 检票员 |
| postHandle | 控制器执行后,视图渲染前调用 | 散场工作人员 |
| afterCompletion | 整个请求完成后调用 | 清洁工 |
| 路径配置 | 使用/**拦截所有路径 |
设置安检区域 |
| 排除配置 | 使用exclude-mapping排除路径 |
VIP通道免检 |
拦截器的核心价值: 在不修改原有代码的情况下,为请求处理添加额外功能。
浙公网安备 33010602011771号