在构建Web应用时,统一处理用户请求的登录校验、权限验证和日志记录是常见需求。Spring Boot拦截器(Interceptor)正是解决这类问题的利器。本文将带你深入理解拦截器的原理、实现方式及执行流程,助你快速掌握这一关键技能。

1. 为什么需要拦截器?从图书管理系统的痛点说起

假设你正在开发一个图书管理系统,需要实现强制登录功能——用户必须登录后才能访问其他页面。传统做法是在每个接口中手动编写Session校验逻辑,但这会带来三个问题:

  • 代码冗余:每个接口都需要重复编写校验代码,维护成本高。
  • 耦合性强:业务逻辑与校验逻辑混杂,修改一处可能影响全局。
  • 前后端联动复杂:接口定义变更时,前端代码也需要同步调整。

有没有更优雅的解决方案?答案是使用拦截器。它允许你在请求到达Controller之前统一执行预定义逻辑,如Session校验、权限检查等,从而将通用功能从业务代码中剥离出来。

2. 什么是拦截器?用生活场景来理解

拦截器是Spring框架提供的核心功能之一,主要用于拦截用户请求,在目标方法执行前后执行预设代码。以下是两个生活化的例子:

场景一:大学校园的人脸识别门禁

学生回校时,需通过人脸识别验证身份;校外访客则需保安登记信息。无论是人脸识别还是保安登记,都是在进入校园(执行目标操作)前的“拦截”环节。拦截器的作用与此类似:在请求到达Controller前,执行校验逻辑,决定是否放行。

场景二:银行办理业务

办理业务前需取号并验证身份证,业务结束后需评价服务。这些“前置”和“后置”操作正是拦截器的典型应用。通过拦截器,你可以在请求处理前后添加通用逻辑,如日志记录、性能监控等。

核心定义:拦截器允许开发人员预定义逻辑,在用户请求响应前后执行,或在请求前阻止其执行。例如,判断Session中是否存在登录用户信息:

  • ✅ 有:放行请求。
  • ❌ 无:拦截请求并返回提示。
在这里插入图片描述

3. 拦截器的基本使用:两步搞定

在Spring Boot中,使用拦截器只需两步:定义拦截器注册配置拦截器。下面以图书管理系统为例进行演示。

3.1 定义拦截器

创建一个intercepter包,定义LoginIntercepter类,实现HandlerInterceptor接口并重写方法:

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Slf4j
@Component
public class LoginIntercepter implements HandlerInterceptor {
/**
*
* @param request
* @param response
* @param handler
* @return
* true:对目标方法放行,不会拦截
* false:拦截目标方法,通过验证之后,才能访问
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {
log.info("preHandle方法,目标方法执行前。。。");
//        true: 放行目标方法
//        false:拦截目标方法
return true;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception {
log.info("postHandle方法,目标方法执行后!!!");
HandlerInterceptor.super.postHandle(request,response,handler,modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) throws Exception {
log.info("LoginInterceptor 视图渲染完毕后执行,最后执行");
HandlerInterceptor.super.afterCompletion(request,response,handler,ex);
}
}

HandlerInterceptor接口包含三个方法:

  • preHandle():在目标方法执行前调用。返回true表示放行,返回false表示拦截。
  • postHandle():在目标方法执行后、视图渲染前调用。
  • afterCompletion():在视图渲染完毕后执行,是整个请求处理流程的最后一步。

3.2 注册配置拦截器

创建一个config包,定义WebConfig类,实现WebMvcConfigurer接口并重写addInterceptors方法:

import lombok.extern.slf4j.Slf4j;
import org.example.book_system_20251107.book.intercepter.LoginIntercepter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Slf4j
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginIntercepter loginIntercepter;
@Override
public void addInterceptors(InterceptorRegistry registry) {
log.info("拦截器启动拦截");
registry.addInterceptor(loginIntercepter).addPathPatterns("/**");
//        这句代码做了两件事情:
//        1. 添加拦截器对象,指定使用的拦截器
//        2.  设置拦截器拦截的请求路径( /** 表⽰拦截所 有请求)
}
}

⚠️ 重要提示WebConfig类必须添加@Configuration注解,否则addInterceptors方法不会执行,拦截器也不会生效。

在这里插入图片描述

常见拦截路径配置

  • /**:拦截所有请求路径。
  • /book/**:拦截路径中包含book的所有请求。
在这里插入图片描述

4. 测试拦截器:放行与拦截的对比

启动图书管理系统,使用Postman测试登录接口(URL = http://127.0.0.1:8080/user/login name=admin&password=admin):

4.1 返回true:放行

preHandle()返回true时,请求被放行,正常执行Controller中的方法:

在这里插入图片描述在这里插入图片描述

4.2 返回false:拦截

preHandle()返回false时,请求被拦截,不会执行后续任何操作:

在这里插入图片描述在这里插入图片描述

在实际开发中,你需要在拦截器中编写业务逻辑来判断是否拦截。例如,检查Session中是否存在用户信息:

  • 存在:返回true,放行。
  • 不存在:返回false,并返回提示信息。

排除拦截请求:拦截器还支持排除特定路径,例如登录页、注册页等。这一功能将在后续文章(图书管理系统(7)完善强制登录功能)中详细演示。

[AFFILIATE_SLOT_1]

5. 拦截器执行流程:从请求到响应的完整路径

理解拦截器的执行流程至关重要。以下是添加拦截器前后的对比:

5.1 无拦截器时的调用顺序

请求直接到达Controller,执行方法后返回响应:

在这里插入图片描述

5.2 有拦截器时的调用顺序

请求先被拦截器拦截,执行preHandle()方法:

  • 返回true:放行,继续执行Controller中的方法。
  • 返回false:拦截,Controller中的方法不会执行。

Controller方法执行完毕后,依次执行postHandle()afterCompletion()方法,最后返回响应给客户端。

在这里插入图片描述

5.3 拦截器与过滤器的执行顺序

当同时存在拦截器(Interceptor)和过滤器(Filter)时,执行顺序如下:

  • Filter → Interceptor.preHandle() → Controller → Interceptor.postHandle() → Interceptor.afterCompletion() → Filter后续逻辑
在这里插入图片描述

技术要点:在Java、JavaScript、C++、Go、TypeScript等语言中,拦截器(或中间件)的概念类似,都是用于在请求处理管道中插入通用逻辑。Spring Boot的拦截器实现与这些语言的中间件设计思想一脉相承。

[AFFILIATE_SLOT_2]

6. 总结:拦截器的核心价值

本文从图书管理系统的痛点出发,详细介绍了Spring Boot拦截器的概念、使用方法和执行流程。拦截器的核心价值在于:

  • 统一处理:将登录校验、权限验证、日志记录等通用逻辑集中管理。
  • 解耦业务:避免业务代码与基础设施代码混杂,提升可维护性。
  • 灵活控制:支持放行、拦截和路径排除,满足复杂业务需求。

下一篇我们将探讨统一数据返回格式,敬请期待!