Spring拦截器作为请求处理的关键组件,能有效实现权限校验等统一操作。本文将详细介绍拦截器实现原理及使用技巧。
图书管理系统采用Session校验登录状态的传统方式存在明显缺陷:需要修改每个接口处理逻辑、调整返回结果,并同步改动前端代码。为解决这些问题,Spring提供的拦截器机制能统一拦截请求进行Session校验。
拦截器作为Spring框架核心功能,可以在指定方法前后执行预设的业务代码。

实现拦截器功能主要分为两个步骤:
通过实现HandlerInterceptor接口并重写其方法创建LoginInterceptor:
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("LoginInterceptor 目标方法执行前执行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("LoginInterceptor 目标方法执行后执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("LoginInterceptor 视图渲染完毕后执行,最后执行");
}
}
通过实现WebMvcConfigurer接口配置拦截器:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
;
}
}
启动服务后观察日志输出,可以看到拦截器各方法的执行顺序。

当preHandle返回false时,只会执行该方法:

通过addPathPatterns()指定拦截路径,excludePathPatterns()设置排除路径。例如登录校验可排除登录接口:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/user/login")
;
}
常见拦截路径配置示例如下:

正常调用顺序示意图:

完整执行流程:

改进后的登录拦截器实现:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
UserInfo userInfo = (UserInfo) session.getAttribute(Constants.USER_SESSION_KEY);
if (userInfo==null || userInfo.getId()<=0){
response.setStatus(401);
return false;
}
return true;
}
配置排除静态资源路径:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/user/login")
.excludePathPatterns("/css/**")
.excludePathPatterns("/js/**")
.excludePathPatterns("/pic/**")
.excludePathPatterns("/**/*.html")
;
}
访问效果对比:


登录后正常访问:

服务启动日志显示DispatcherServlet控制程序执行流程:

请求处理流程示意图:

DispatcherServlet初始化方法调用链:

初始化Web容器:

初始化日志输出:

初始化SpringMVC容器:

doDispatch方法处理请求:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 方法实现...
}
重点关注三个核心方法:

对应HandlerInterceptor接口:

HandlerAdapter采用适配器模式实现。
适配器模式将一个类的接口转换成客户端期望的另一个接口,使不兼容的类能够协同工作。
Log4j适配器实现:
public class Log4jAdapter implements Slf4jLog{
private Log4j log4j;
public Log4jAdapter(Log4j log4j) {
this.log4j = log4j;
}
@Override
public void log(String message) {
log4j.log4jPrint("我是是适配器, 打印日志为: "+ message);
}
}
运行结果:

优点:
缺点:
本文详细介绍了Spring拦截器的实现原理、使用方法和底层机制,帮助开发者深入理解并有效应用这一重要组件。掌握这些知识能显著提升系统开发的效率和质量。