问题背景
最近在使用Spring MVC开发项目时,我遇到了一个诡异的问题:在自定义拦截器的preHandle
方法中,明明请求的是Controller层的方法,但handler instanceof HandlerMethod
判断却总是返回false
,导致拦截逻辑无法正常执行。
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 问题代码:总是进入if分支
if (!(handler instanceof HandlerMethod)) {
return true;
}
// 业务逻辑...
}
排查过程
第一步:确认请求确实到达Controller
首先我通过断点确认请求确实调用了目标Controller方法:
handler值显示为:com.csuft.mianshimao.controller.QuestionController#addQuestion(QuestionAddRequest)
这说明请求路由是正确的,Spring确实找到了对应的Controller方法。
第二步:检查Handler类型
我打印了handler的实际类型:
System.out.println(handler.getClass().getName());
输出结果是org.springframework.web.method.HandlerMethod
的子类(具体类名可能包含代理信息),这证明它确实是HandlerMethod类型。
第三步:验证类加载器
排除了类加载器问题:
System.out.println(handler.getClass().getClassLoader());
System.out.println(HandlerMethod.class.getClassLoader());
// 输出相同的类加载器
第四步:检查AOP代理
排除了AOP代理问题:
System.out.println(AopUtils.isAopProxy(handler)); // false
第五步:发现关键问题 - 错误的import
最后,我注意到我的import语句:
import org.springframework.messaging.handler.HandlerMethod; // ❌错误的import
而实际上应该导入的是:
import org.springframework.web.method.HandlerMethod; // ✅正确的import
问题原因
Spring框架中有多个模块都定义了HandlerMethod
类:
-
消息处理模块:
org.springframework.messaging.handler.HandlerMethod
-
用于处理WebSocket、STOMP等消息
-
-
Web MVC模块:
org.springframework.web.method.HandlerMethod
-
用于处理HTTP请求
-
封装Controller方法信息
-
由于IDE自动导入(或开发者疏忽)导入了错误的HandlerMethod
类,导致instanceof
判断始终为false。
解决方案
-
修正import语句:
// 删除旧的import
import org.springframework.web.method.HandlerMethod; // 使用正确的import
-
预防措施:
-
使用IDE的"Optimize Imports"功能(IDEA: Ctrl+Alt+O)
-
关注自动导入时的完整路径提示
-
对框架核心类保持导入路径敏感
-
经验总结
-
框架模块要分清:Spring不同模块可能有同名类,要特别注意
-
自动导入要谨慎:不要完全依赖IDE的自动导入
-
排查问题要系统:从现象出发,逐步缩小范围
-
基础知识点很重要:理解Spring MVC和Messaging的区别