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类型。这里也提醒我们养成良好的编程习惯,执行强制转换之前一定要做类型检查。

时间: 2024-11-15 16:13:50

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

解决SpringMVC拦截器中Request数据只能读取一次的问题

解决SpringMVC拦截器中Request数据只能读取一次的问题 开发项目中,经常会直接在request中取数据,如Json数据,也经常用到@RequestBody注解,也可以直接通过request.getParameter()从Request中取数据. 但是有时候我们要在请求到具体的业务之前做一些操作比如日志记录.数据校验.统一的处理等等,可以在拦截器中处理. 由于 request中getReader()和getInputStream()只能调用一次,我们在拦截器中获取Request中数据后

Springboot中SpringMvc拦截器配置与应用(实战)

一.什么是拦截器,及其作用 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对象,允许开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行.同时也是提供了一种可以提取action中可重用的部分的方式. 拦截器的使用场景越来越多,尤其是面向切片编程流行之后.那通常拦截器可以做什么呢? 之前我们在Agent介绍中,提到过统计函数的调用耗时.这

在JSP中常见问题,防止SpringMVC拦截器拦截js等静态资源文件的解决方案

方案一.拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml) <mvc:resources location="/" mapping="/**/*.js"/> <mvc:resources location="/" mapping="/**/*.css"/> <mvc:resources location="/assets/" mapping="/a

springmvc拦截器使用和原理理解

与struts2类似,springmvc的拦截器主要作用也是在服务端真正处理请求前后进行一些相关的操作. 例如初始化资源,权限监控,会话设置,菜单获取,资源清理等. 步骤: 1. 定义拦截器 自定义拦截器一般继承自HandlerInterceptorAdapter 或者实现 HandlerInterceptor 接口. 实现接口需要实现对应的3中方法,继承父类只需要实现需要的方法即可.preHandle,postHandle,afterCompletion public class MyInte

SpringMVC 拦截器理解

SpringMVC 配置拦截器 1. 作为拦截器当然是为了拦截 (这不是废话嘛) 那拦截是为了干嘛? 它可以帮我们拦截未登录用户   验证是否登录.设置日志记录.统计一些接口访问量啊 进行统一异常处理  设置一些数据啊 或者计算下应用接口方法执行效率啊 等等   2. 配置拦截器 由于用的是SpringMVC所以要知道 它是有个统一的 DispatcherServlet 控制器, 所以就不用传统的bean方式了,人家给我们提供了其他简单的方式 如下所示:  (我设置了三个方便测试用的) <!--

SpringMVC拦截器(实现登录验证拦截器)

本例实现登陆时的验证拦截,采用SpringMVC拦截器来实现 当用户点击到网站主页时要进行拦截,用户登录了才能进入网站主页,否则进入登陆页面 核心代码 首先是index.jsp,显示链接 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <% 3 String path = request.getContextPath(); 4 St

SpringMVC拦截器+Spring自定义注解实现权限验证

设计思路 主要针对需要登录后操作的接口进行校验.接入层在对外暴露接口后,网页.APP.第三方等等途径进行访问接口.用户请求首先会被SpringMVC拦截器拦截到,在拦截器里第一步就是需要校验用户的登录身份(由于是分布式系统这里采用的是userId+accessToken方式来校验),登录校验通过之后再进行用户权限校验,此时会自动拦截@AuthValidate注解的method(核心),如果权限校验失败则抛出权限不足异常,否则校验通过之后再执行具体接口并返回结果. 1.自定义注解 1 packag

SpringMVC拦截器的使用

SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判断当前时间是否是购票时间. 一.springMVC拦截器的实现方式 springMVC拦截器的实现一般有两种方式:第一种方式是要定义的Interceptor类要实现了Spring的HandlerInterceptor 接口.第二种方式是继承实现了HandlerInterceptor接口的类,比

SpringMVC拦截器详解[附带源码分析]

目录 前言 重要接口及类介绍 源码分析 拦截器的配置 编写自定义的拦截器 总结 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/springMVC-introduction.html 拦截器是每个Web框架必备的功能,也是个老生常谈的主题了. 本文将分析SpringMVC的拦截器功能是如何设计的,让读者了解该功能设计的原理. 重要接口及类介绍 1. Hand