代码:
handler instanceof HandlerMethod
是用于判断当前请求是否由一个具体的控制器方法(Controller Method)来处理。为了更清楚地解释它为什么能“判断”,我们先从 Spring MVC 的请求处理机制谈起。
🌐 1. Spring MVC 中的请求处理流程
在 Spring MVC 中,每个 HTTP 请求最终都会被映射到一个“处理器”(Handler)。这个“处理器”可以是以下几种形式:
- 一个实现了
Controller
接口的类(旧式写法) - 一个带有
@RequestMapping
注解的方法(现代常用方式),Spring 会将它封装为HandlerMethod
- 一个
HttpRequestHandler
(用于静态资源等)
所以,handler
是一个通用的 Object
类型对象,Spring 并不能一开始就确定它是哪种类型。
✅ 2. 为什么要用 instanceof HandlerMethod
判断?
原因:只有 HandlerMethod
才代表一个具体的方法
如果你要对某个 Controller 方法做拦截(比如权限检查、日志记录等),你就必须确保这个 handler 是一个方法级别的处理器(即 HandlerMethod
),而不是一个类级别或其他类型的处理器。
举个例子:
// UserController.java
@GetMapping("/user/login")
public Result login() {
return Result.success();
}
上面的 /user/login
接口会被 Spring 封装为一个 HandlerMethod
,表示调用的是 UserController.login() 这个方法。
而如果你不加 if (handler instanceof HandlerMethod)
判断,就可能会遇到如下问题:
if (handler.getClass() == HandlerMethod.class) { /* 错误写法 */ }
这种方式不如 instanceof
安全,因为子类无法匹配。使用 instanceof
更加稳妥。
🔍 3. 举个实际场景说明它的作用
假设你正在编写一个 VIP 权限拦截器:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod hm = (HandlerMethod) handler;
if (hm.getMethod().isAnnotationPresent(VipRequired.class)) {
// 如果该方法需要 VIP 权限,则进一步判断用户是否是 VIP
if (!isUserVip(request)) {
throw new VipRequiredException();
}
}
}
return true;
}
这段逻辑中:
- 首先判断
handler
是否是HandlerMethod
类型; - 如果是,才去获取方法上的注解
@VipRequired
; - 然后根据是否有这个注解进行 VIP 权限校验。
如果跳过 instanceof
判断,直接强制转换成 HandlerMethod
,会导致运行时错误(ClassCastException)。
🧠 总结:为什么能判断?
表达式 | 含义 |
---|---|
handler instanceof HandlerMethod |
检查当前请求的目标是否是一个具体的方法(而非类或其它处理器) |
为什么能判断? | 因为 Spring 在处理请求时,会根据请求路径找到对应的处理器(handler),这个 handler 可以是多种类型,而 HandlerMethod 是专门用来封装 Controller 方法的类。通过 instanceof ,我们可以准确判断当前 handler 是否是我们想要操作的对象。 |
💡 类比理解:
你可以把它想象成这样的场景:
你走进一家餐厅,服务员问你:“你是来吃饭的吗?”
如果你说“是”,那他才会继续问你要点什么菜;
如果你说“不是”,比如你是来开会的,那他就不会让你点菜了。
同理,handler instanceof HandlerMethod
就是在问:“这个请求是不是要执行一个具体的方法?”
如果是,就继续处理;如果不是,就跳过。