SSM 框架之 SpringMVC 拦截器全解析:原理、实现与实战
一、拦截器核心概念
1. 什么是 SpringMVC 拦截器
SpringMVC 拦截器是基于 AOP 思想设计的请求拦截组件,仅作用于 SpringMVC 接管的 Controller 请求,可在请求处理的不同阶段插入自定义业务逻辑。它是 SpringMVC 框架专属组件,与 Spring 容器深度集成,能直接调用容器中的 Service、Mapper 等 Bean,灵活性远高于 Servlet 过滤器。
2. 拦截器的核心应用场景
- 登录状态校验:拦截未登录用户访问受保护的页面 / 接口,跳转至登录页;
- 权限精细化控制:根据用户角色拦截非法访问(如普通用户访问管理员接口);
- 请求日志记录:记录请求 URL、请求参数、执行耗时、响应状态等;
- 参数预处理 / 后处理:统一格式化请求参数、封装响应数据;
- 资源清理:请求完成后释放连接、关闭流等资源。
3. 拦截器与 Servlet 过滤器(Filter)的核心区别
| 特性 | SpringMVC 拦截器 | Servlet 过滤器 |
|---|---|---|
| 所属规范 | SpringMVC 框架 | Servlet 规范 |
| 拦截范围 | 仅拦截 Controller 请求 | 拦截所有请求(含静态资源) |
| Spring 集成度 | 可直接注入 Service/Bean | 需通过容器上下文获取 Spring Bean |
| 执行时机 | DispatcherServlet 调度后 | DispatcherServlet 调度前 |
二、拦截器核心接口与方法
SpringMVC 通过HandlerInterceptor接口定义拦截器的核心行为,该接口包含 3 个核心方法,对应请求处理的不同阶段,开发者可按需重写:
| 方法名 | 执行时机 | 返回值 / 核心作用 |
|---|---|---|
preHandle | 请求到达 Controller 之前 | boolean 类型:true放行,false拦截 |
postHandle | Controller 执行完成、视图渲染之前 | 可修改 ModelAndView(如添加公共数据) |
afterCompletion | 视图渲染完成后(请求完全结束) | 用于资源清理、日志收尾 |
其中,preHandle是最常用的方法,几乎所有核心拦截逻辑(如登录验证)都在此实现。
三、拦截器完整实现步骤(登录验证实战)
以下以 “登录状态校验” 为例,完整演示 SSM 拦截器的实现流程。
步骤 1:自定义拦截器类(实现 HandlerInterceptor 接口)
创建拦截器类并实现HandlerInterceptor接口,重写核心方法完成登录校验逻辑:
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义登录拦截器:校验用户是否已登录
*/
public class LoginInterceptor implements HandlerInterceptor {
// 核心方法:请求到达Controller前执行(登录校验核心逻辑)
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 1. 从Session中获取登录用户标识
Object loginUser = request.getSession().getAttribute("loginUser");
// 2. 未登录:拦截请求,跳转至登录页并提示
if (loginUser == null) {
request.setAttribute("msg", "请先登录后再访问!");
request.getRequestDispatcher("/login").forward(request, response);
return false; // 返回false表示拦截请求
}
// 3. 已登录:放行请求,继续执行Controller逻辑
return true;
}
// Controller执行完成、视图渲染前执行(可选)
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
org.springframework.web.servlet.ModelAndView modelAndView) throws Exception {
// 示例:给所有视图添加公共参数(如系统时间)
if (modelAndView != null) {
modelAndView.addObject("sysTime", System.currentTimeMillis());
}
}
// 视图渲染完成后执行(可选,用于资源清理/日志收尾)
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
// 示例:记录请求完成日志
System.out.println("请求完成,URL:" + request.getRequestURI() + ",异常:" + (ex == null ? "无" : ex.getMessage()));
}
}步骤 2:在 SpringMVC 配置文件中注册拦截器
拦截器需在 SpringMVC 配置文件(通常为spring-mvc.xml)中注册,并通过mapping和exclude-mapping精准控制拦截范围(避免拦截登录页、静态资源导致死循环):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 开启SpringMVC注解驱动(必备) -->
<mvc:annotation-driven/>
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截所有层级的请求:/** 表示拦截所有请求 -->
<mvc:mapping path="/**"/>
<!-- 排除不需要拦截的路径 -->
<mvc:exclude-mapping path="/login"/> <!-- 登录页 -->
<mvc:exclude-mapping path="/doLogin"/> <!-- 登录接口 -->
<mvc:exclude-mapping path="/static/**"/> <!-- 静态资源(css/js/img) -->
<!-- 注册自定义拦截器类 -->
<bean class="com.example.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
<!-- 基础配置:Controller组件扫描 + 视图解析器 -->
<context:component-scan base-package="com.example.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/> <!-- JSP文件路径前缀 -->
<property name="suffix" value=".jsp"/> <!-- JSP文件后缀 -->
</bean>
<!-- 静态资源放行(可选,避免静态资源被拦截) -->
<mvc:default-servlet-handler/>
</beans>步骤 3:编写测试 Controller 验证拦截器
创建登录相关 Controller,验证拦截器的拦截效果:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
// 跳转到登录页(不被拦截)
@GetMapping("/login")
public String toLogin() {
return "login"; // 对应/WEB-INF/pages/login.jsp
}
// 登录逻辑处理(不被拦截)
@PostMapping("/doLogin")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
HttpSession session) {
// 模拟登录校验(实际项目中需查询数据库)
if ("admin".equals(username) && "123456".equals(password)) {
session.setAttribute("loginUser", username); // 登录成功,存入用户信息
return "redirect:/index"; // 跳转至首页
} else {
request.setAttribute("msg", "用户名或密码错误!");
return "login"; // 登录失败,返回登录页
}
}
// 系统首页(需登录才能访问,未登录会被拦截)
@GetMapping("/index")
public String index() {
return "index"; // 对应/WEB-INF/pages/index.jsp
}
}四、关键补充知识点
1. 多拦截器的执行顺序
若配置多个拦截器,方法执行顺序遵循以下规则:
- preHandle:按配置顺序执行(先配置的拦截器先执行);
- postHandle/afterCompletion:按配置逆序执行(后配置的拦截器先执行)。
例如配置拦截器 A、B,执行顺序为:A.preHandle() → B.preHandle() → Controller 执行 → B.postHandle() → A.postHandle() → 视图渲染 → B.afterCompletion() → A.afterCompletion()。
2. 静态资源的拦截处理
默认情况下,SpringMVC 拦截器不会拦截静态资源(如 CSS、JS、图片),若需拦截静态资源,需在配置文件中通过<mvc:resources>指定资源路径,并取消<mvc:default-servlet-handler/>配置。
3. 拦截器与过滤器的选择原则
- 需拦截 Controller 请求 + 依赖 Spring Bean → 优先使用拦截器;
- 需拦截静态资源、请求编码统一处理等全局场景 → 优先使用过滤器;
- 复杂业务逻辑(如权限校验)→ 拦截器(集成 Spring 生态更便捷)。
五、总结
- SpringMVC 拦截器基于HandlerInterceptor接口实现,preHandle是核心方法,通过返回true/false控制请求是否放行;
- 拦截器需在 SpringMVC 配置文件中注册,通过mapping/exclude-mapping精准控制拦截范围,避免拦截登录页、静态资源;
- 拦截器是 SSM 开发中实现登录验证、权限控制的首选方案,相比 Servlet 过滤器,它与 Spring 生态深度集成,使用更灵活;
- 多拦截器的执行顺序有明确规则,需根据业务逻辑合理配置顺序。
版权所属:SO JSON在线解析
原文地址:https://www.sojson.com/blog/571.html
转载时必须以链接形式注明原始出处及本声明。
如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。
