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


    错误应用场

    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类型。

    这里也提醒我们养成良好的编程习惯。运行强制转换之前一定要做类型检查。

  • 相关阅读:
    PC端微信扫码支付和支付宝跳转支付 斧头帮
    微信支付 斧头帮
    PC端实现浏览器点击分享到QQ好友,空间,微信,微博等 斧头帮
    图片,word,Excel等附件上传 斧头帮
    java定时任务详解 斧头帮
    手机浏览器实现分享给好友或是朋友圈 斧头帮
    Java缓存EhcacheEhcache的Cache在SSM框架中的配置 斧头帮
    通过精确地址获取经纬度 斧头帮
    SpringBoot中设置自定义拦截器 斧头帮
    Visual Studio 2008创建项目(ATL)
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7270569.html
Copyright © 2020-2023  润新知