【避坑指南】Spring拦截器中instanceof HandlerMethod失效的问题排查

【避坑指南】Spring拦截器中instanceof HandlerMethod失效的问题排查

问题背景

最近在使用Spring MVC开发项目时,我遇到了一个诡异的问题:在自定义拦截器的preHandle方法中,明明请求的是Controller层的方法,但handler instanceof HandlerMethod判断却总是返回false,导致拦截逻辑无法正常执行。

1
2
3
4
5
6
7
8
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 问题代码:总是进入if分支
if (!(handler instanceof HandlerMethod)) {
return true;
}
// 业务逻辑...
}

点击并拖拽以移动

排查过程

第一步:确认请求确实到达Controller

首先我通过断点确认请求确实调用了目标Controller方法:

1
handler值显示为:com.csuft.mianshimao.controller.QuestionController#addQuestion(QuestionAddRequest)

点击并拖拽以移动

这说明请求路由是正确的,Spring确实找到了对应的Controller方法。

第二步:检查Handler类型

我打印了handler的实际类型:

1
System.out.println(handler.getClass().getName());

点击并拖拽以移动

输出结果是org.springframework.web.method.HandlerMethod的子类(具体类名可能包含代理信息),这证明它确实是HandlerMethod类型。

第三步:验证类加载器

排除了类加载器问题:

1
2
3
System.out.println(handler.getClass().getClassLoader()); 
System.out.println(HandlerMethod.class.getClassLoader());
// 输出相同的类加载器

点击并拖拽以移动

第四步:检查AOP代理

排除了AOP代理问题:

1
System.out.println(AopUtils.isAopProxy(handler)); // false

点击并拖拽以移动

第五步:发现关键问题 - 错误的import

最后,我注意到我的import语句:

1
import org.springframework.messaging.handler.HandlerMethod; // ❌错误的import

点击并拖拽以移动

而实际上应该导入的是:

1
import org.springframework.web.method.HandlerMethod; // ✅正确的import

点击并拖拽以移动

问题原因

Spring框架中有多个模块都定义了HandlerMethod类:

  1. 消息处理模块org.springframework.messaging.handler.HandlerMethod
    • 用于处理WebSocket、STOMP等消息
  2. Web MVC模块org.springframework.web.method.HandlerMethod
    • 用于处理HTTP请求
    • 封装Controller方法信息

由于IDE自动导入(或开发者疏忽)导入了错误的HandlerMethod类,导致instanceof判断始终为false。

解决方案

  1. 修正import语句
1
2
// 删除旧的import
import org.springframework.web.method.HandlerMethod; // 使用正确的import

点击并拖拽以移动

  1. 预防措施
    • 使用IDE的”Optimize Imports”功能(IDEA: Ctrl+Alt+O)
    • 关注自动导入时的完整路径提示
    • 对框架核心类保持导入路径敏感

经验总结

  1. 框架模块要分清:Spring不同模块可能有同名类,要特别注意
  2. 自动导入要谨慎:不要完全依赖IDE的自动导入
  3. 排查问题要系统:从现象出发,逐步缩小范围
  4. 基础知识点很重要:理解Spring MVC和Messaging的区别