SpringMVC拦截器HandlerInterceptor接口详解
HandlerInterceptor是SpringMVC拦截机制核心,定义preHandle、postHandle、afterCompletion方法。preHandle预处理,返回false则拦截;postHandle在控制器执行后、视图渲染前调用;afterCompletion视图渲染后执行。多拦截器时,preHandle顺序执行,postHandle和
HandlerInterceptor
HandlerInterceptor 是 Spring MVC 中实现请求拦截的核心接口,它定义了三个关键方法,犹如三道关卡,贯穿请求处理的整个生命周期。
preHandle:该方法在控制器方法执行之前被调用。你可以把它理解为一个“安检门”,非常适合进行身份验证、权限检查等预处理操作。它的返回值决定了请求是否能继续前行:返回 true 表示通过检查,请求会被放行,接着进入下一个拦截器或控制器;返回 false 则请求在此被拦截,后续的拦截器和控制器都不会再执行。
postHandle:它在控制器方法执行完毕、但视图尚未渲染之前被调用。这是一个“后加工车间”,你可以在这里对返回的 ModelAndView 对象进行修改,例如向模型添加公共数据,或者调整视图名称。
afterCompletion:这是最后一步,在视图渲染完成之后才触发。它更像一个“清道夫”,主要用于释放资源、记录日志,或者统一处理 Exception 异常信息,非常适合执行收尾工作。
单个拦截器的实现
接下来,我们通过一个完整的实例,看看单个拦截器是如何落地实现的。
定义拦截器
首先,实现 HandlerInterceptor 接口来定义一个拦截器类:
package test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import ja vax.servlet.http.HttpServletRequest;
import ja vax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 预处理逻辑,如权限检查
log.info("preHandle方法执行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 后处理逻辑,可以修改数据模型
log.info("postHandle方法执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 资源清理逻辑,比如释放资源或记录日志
log.info("afterCompletion方法执行");
}
}
配置拦截器
定义好拦截器后,需要告诉 Spring MVC 哪些请求应该被它拦截。这需要创建一个实现了 WebMvcConfigurer 接口的配置类,并在 addInterceptors 方法中进行注册。下面的示例将拦截器配置为拦截所有请求(即 /** 路径):
package test;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import ja vax.annotation.Resource;
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
@Resource
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor)
.addPathPatterns("/**");
}
}
测试拦截器
最后,准备一个简单的控制器来验证拦截器是否生效:
package test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class MyController {
@GetMapping("/test")
public String test() {
log.info("控制器方法执行");
return "OK";
}
}
启动项目,通过 HTTP 请求访问 /test 路径,控制台会输出如下结果:

从输出顺序可以清晰地看到拦截器的执行流程:preHandle 先执行,然后才是控制器方法,接着是 postHandle,最后是 afterCompletion。
多个拦截器的实现
实际项目中,我们通常会配置多个拦截器来处理不同维度的逻辑。那么多个拦截器之间是如何协作的呢?我们来一步步拆解。
定义拦截器
先定义三个拦截器,分别命名为 MyInterceptor1、MyInterceptor2 和 MyInterceptor3。它们的代码结构相同,只是日志输出不同,以便区分执行顺序。这里以第一个为例展示:
package test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import ja vax.servlet.http.HttpServletRequest;
import ja vax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class MyInterceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("【我的拦截器1】preHandle方法执行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("【我的拦截器1】postHandle方法执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("【我的拦截器1】afterCompletion方法执行");
}
}
### 配置拦截器
接下来配置这些拦截器,让它们分别拦截不同的路径:/test1、/test2 和 /test3。
package test;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import ja vax.annotation.Resource;
@Configuration
public class MyMultipleInterceptorConfig implements WebMvcConfigurer {
@Resource
private MyInterceptor1 myInterceptor1;
@Resource
private MyInterceptor2 myInterceptor2;
@Resource
private MyInterceptor3 myInterceptor3;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor1)
.addPathPatterns("/test1");
registry.addInterceptor(myInterceptor2)
.addPathPatterns("/test2");
registry.addInterceptor(myInterceptor3)
.addPathPatterns("/test3");
}
}
测试拦截器
在控制器中为这些路径添加对应的处理方法:
package test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class MyMultipleInterceptorTestController {
@GetMapping("/test1")
public String test1() {
log.info("控制器test1方法执行");
return "OK";
}
@GetMapping("/test2")
public String test2() {
log.info("控制器test2方法执行");
return "OK";
}
@GetMapping("/test3")
public String test3() {
log.info("控制器test3方法执行");
return "OK";
}
}
现在,如果访问 /test2 这个路径,控制台输出的结果会是:

这清楚地表明,访问某个路径时,只会触发专门为该路径配置的拦截器。这是一种精确的拦截控制策略。
多个拦截器的执行顺序
如果把多个拦截器配置为拦截同一个路径,结果又如何呢?我们修改配置,让三个拦截器都拦截 /test2 路径:
// ... 配置代码中,将三个拦截器的 addPathPatterns 都改为 "/test2" ...
再次访问 /test2,输出结果如下:

这里有个关键点需要注意:preHandle 方法的执行顺序与我们注册拦截器的顺序一致(1 -> 2 -> 3),但 postHandle 和 afterCompletion 方法的执行顺序却完全相反,变成了 3 -> 2 -> 1。这种“先进后出”的栈式结构,在日志处理和资源清理场景中非常常见。
某个拦截器拒绝放行的情况
如果请求在某个拦截器中被拦截(即 preHandle 返回 false),又会发生什么?我们将 MyInterceptor2 的 preHandle 返回值改为 false:
// MyInterceptor2 的 preHandle 方法中,return false;
再次访问 /test2,输出结果如下:

从结果可以总结出几条重要规则:
- 只要任何一个拦截器的
preHandle返回false,目标控制器方法就绝对不会执行。 - 对于拦截器链中,位于“拒绝拦截器”之前的拦截器(本例中的
MyInterceptor1),它们的preHandle和afterCompletion方法都会执行。 - 对于那个“拒绝拦截器”本身(
MyInterceptor2),它的preHandle会执行,但afterCompletion不会执行。 - 对于“拒绝拦截器”之后的所有拦截器(
MyInterceptor3),它们的方法都不会被执行。 - 所有拦截器的
postHandle方法都不会执行,因为控制器方法根本没被调用。
理解这个执行模型,对于调试复杂的拦截器链问题会非常有帮助。
总结
HandlerInterceptor 的三个方法形成了请求处理的前、中、后三个阶段,为我们在 Spring MVC 中实现权限控制、日志记录、数据预处理等提供了强大的支持。理解单个拦截器的配置以及多个拦截器之间的执行顺序,尤其是在异常情况下的行为,是掌握 Spring MVC 拦截器机制的关键所在。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
IDEA中SpringBoot项目热部署实现指南
Springboot项目在IDEA中实现热部署需依次完成:开启自动编译(静态与动态编译)、启用热部署策略、引入spring-boot-devtools依赖、关闭浏览器缓存,最后启动测试即可生效,省去手动重启时间,大幅提升开发效率。
Java实现Excel转JSON的代码详解
使用Java结合FreeSpire XLS库可自动将Excel转为JSON,通过读取工作表并映射为键值对,高效支持数据迁移、报表导出与系统对接,大幅提升效率并消除手动录入错误。
Golang高效布谷鸟过滤器多字符集字符串过滤
布谷鸟过滤器支持删除操作,通过指纹截断与双哈希定位实现多字符集高效过滤。指纹截断需采用fnv64a或xxhash快速哈希并取低8位,桶索引使用独立双哈希避免假阳性。并发安全需以固定数组配合sync atomic实现。
Java使用Poi-tl按Word模板生成动态表格
Poi-tl是Word导出工具,文档周全,支持多级合并表头生成。通过{{text}}、{{?var}}、{{ table}}标签处理模板,传入TableRenderData对象即可动态渲染表格。示例展示用户信息表格生成,并提供工具类消除表格首行缩进,确保格式正确。
Go语言微服务集成Swagger生成交互式API文档完整教程
在Go微服务中集成Swagger常见四大问题:swaginit初始化失败需确保存在packagemain及注释;SwaggerUI加载失败因路由映射错误或未导入docs;@Param注解必须严格遵循格式;部署后接口文档显示localhost因硬编码host,应删除或通过环境变量动态注入。
- 热门数据榜
相关攻略
2026-07-11 06:47
2026-07-11 06:47
2026-07-11 06:47
2026-07-11 06:47
2026-07-11 06:47
2026-07-11 06:46
2026-07-11 06:46
2026-07-11 06:46
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

