在 Spring MVC 中,拦截器(Interceptor)用于在请求处理的前后或完成时执行自定义逻辑(如权限验证、日志记录、性能监控等)。以下是拦截器的开发步骤及示例:
在 Spring MVC 中开发拦截器,需要引入 Spring Web MVC 相关依赖。以下是具体依赖配置(以 Maven 和 Gradle 为例):
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.30version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
<scope>providedscope>
dependency>
Spring Boot 已集成 Spring MVC,只需引入 spring-boot-starter-web
:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<version>2.7.18version>
dependency>
依赖 | 作用 |
---|---|
spring-webmvc |
提供 Spring MVC 核心功能(包括拦截器、控制器、视图解析等)。 |
javax.servlet-api (或 jakarta.servlet-api ) |
Servlet 规范接口(如 HttpServletRequest ),Spring MVC 基于 Servlet 实现。 |
spring-boot-starter-web |
Spring Boot 对 Spring MVC 的自动化配置依赖,包含 spring-webmvc 及其他组件。 |
javax.servlet-api
应设置为 provided
,避免打包冲突。WebMvcConfigurer
(Java 配置)或 WebMvcConfigurerAdapter
(旧版)完成,无需额外依赖。实现 HandlerInterceptor
接口,并重写其中的方法:
preHandle
:在请求到达控制器(Controller)前执行,返回 boolean
(true
表示放行,false
表示中断请求)。postHandle
:在控制器处理完成后、视图渲染前执行。afterCompletion
:在请求完成(视图渲染结束)后执行,常用于资源释放。import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LoginInterceptor implements HandlerInterceptor {
// 在Controller方法执行前调用
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println("拦截器 preHandle");
// 示例:检查用户是否登录
if (request.getSession().getAttribute("user") == null) {
response.sendRedirect("/login"); // 未登录则跳转到登录页
return false; // 中断请求
}
return true; // 放行请求
}
// 在Controller方法执行后、视图渲染前调用
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("拦截器 postHandle");
}
// 在整个请求完成后调用(视图渲染结束后)
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
System.out.println("拦截器 afterCompletion");
}
}
在 Spring MVC 配置文件中注册拦截器,并指定拦截路径。
applicationContext.xml
或 spring-mvc.xml
)<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/resources/**"/>
<mvc:exclude-mapping path="/login"/>
<mvc:exclude-mapping path="/doLogin"/>
<bean class="com.example.interceptor.LoginInterceptor"/>
mvc:interceptor>
mvc:interceptors>
WebMvcConfigurer
)@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") // 拦截所有路径
.excludePathPatterns("/login", "/doLogin"); // 排除特定路径
}
}
public class AuthInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 记录请求信息
logger.info("请求 URL: {}, 请求方法: {}, IP: {}",
request.getRequestURL(),
request.getMethod(),
request.getRemoteAddr());
// 检查用户权限(示例)
if (!hasPermission(request)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "无权访问");
return false;
}
return true;
}
private boolean hasPermission(HttpServletRequest request) {
// 实际业务中从 Session 或 Token 中获取用户权限
String userRole = (String) request.getSession().getAttribute("role");
return "ADMIN".equals(userRole); // 仅管理员可访问
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/admin/**") // 只拦截管理路径
.excludePathPatterns("/admin/login");
}
}
特性 | 拦截器(Interceptor) | 过滤器(Filter) |
---|---|---|
所属规范 | Spring MVC | Servlet 规范 |
作用范围 | Controller 层(Handler ) |
整个请求(ServletRequest 和 ServletResponse ) |
依赖关系 | 依赖 Spring 上下文 | 不依赖 Spring,纯 Servlet API |
访问能力 | 可访问 Handler 对象(如 Controller 方法) |
只能操作请求和响应对象 |
执行时机 | 在 DispatcherServlet 之后执行 |
在 DispatcherServlet 之前执行 |
preHandle
返回值:
boolean
,true
表示放行,false
会中断后续流程(包括 postHandle
和 afterCompletion
)。addPathPatterns
和 excludePathPatterns
精确控制拦截范围。通过拦截器,可以轻松实现业务无关的横切关注点(Cross-Cutting Concerns),提升代码复用性和可维护性。