SpringMVC拦截器中通过反射得到Controller方法注解时ClassCastException解决方案

22 篇文章 1 订阅

错误应用场

Controller中,我们自定义了一个@Auth注解来实现权限控制功能,如:

@Auth(verifyLogin=false,verifyURL=false)
    @RequestMapping("/login")
    public ModelAndView  login(HttpServletRequest request,HttpServletResponse response) throws Exception{
        Map<String,Object>  context = getRootMap();
        return forword("login", context);
    }

表示该方法不需要登陆验证,也不需要URL权限验证。

  • AOP. 通过Spring AOP拦截方法调用实现
  • Interceptor. 注册一个拦截器,在拦截器中通过反射得到被调用的控制器方法的@Auth注解,从而实现业务功能

显然使用拦截器更方便,代码量更少。看一下拦截器的preHandle()方法的签名:

public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception;

通过文档得知,第三个参数就是即将调用的控制器方法。于是我们可以通过反射得到@Auth注解:

HandlerMethod method = (HandlerMethod)handler;
Auth  auth = method.getMethod().getAnnotation(Auth.class);

但是实际运行中发现很严重的问题,那就是handler的实际类型并不总是HandlerMethod类型,因此第一行代码经常会扔ClassCastException。经过研究发现,只有当GET请求是请求静态文件时(在spring配置文件里会配置静态文件的URI),handler的实际类型会是DefaultServletHttpRequestHandler,此时强制转换就会报错。

解决方法

在执行强制转换之前用instanceof检查参数handler的实际类型,如果不是HandlerMethod类型,则拦截器不执行任何验证逻辑,直接放行。

为什么要记录一下?因为我发现老外给的Demo中都没有执行类型检查,误导了很多人,让使用者以为handler一定是HandlerMethod类型。这里也提醒我们养成良好的编程习惯,执行强制转换之前一定要做类型检查。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值