Spring boot 2.0 版本报错 ResourceHttpRequestHandler cannot be cast to HandlerMethod

Spring boot 2.0 版本报错 ResourceHttpRequestHandler cannot be cast to HandlerMethod

在写自定义的starter的时候,做了一个拦截器,但是在强转的时候,抛出了异常,具体如图。

Spring boot 2.0 版本报错 ResourceHttpRequestHandler cannot be cast to HandlerMethod

代码如下:

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //其实在请求的时候,requestMapping会把所有的方法封装成HandlerMethod,最后放到拦截器中,一起返回。
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        if(method.isAnnotationPresent(Log.class)){
            //  设置开始时间
            long startTime = System.currentTimeMillis();
            threadLocal.set(startTime);
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Log log = method.getAnnotation(Log.class);
        if(method.isAnnotationPresent(Log.class)){
            //  设置开始时间
            Long startTime = threadLocal.get();
            Long endTime = System.currentTimeMillis();
            Long expendTime = endTime - startTime;

            // 方法参数
            String uri = request.getRequestURI();
            String methodName = method.getDeclaringClass().getName() + "#" + method.getName();
            String methodDesc = log.value();
            String parameters = JSON.toJSONString(request.getParameterMap());
            MyLogInterceptor.log.info("
描述:{}
路径: {}
方法: {}
参数:{}
耗时:{}", methodDesc, uri, methodName, parameters, expendTime);
        }

    }

原因:简单的说,ResourceHttpRequestHandler是用来处理静态资源的;而HandlerMethod则是springMVC中用@Controller声明的一个bean及对应的处理方法。好像用到的是SimpleUrlHandlerMapping,导致来处理请求,并返回了一个ResourceHttpRequestHandler实例!而正是这ResourceHttpRequestHandler,在代码中强转HandlerMthod时抛出了异常。

Spring boot 2.0 版本报错 ResourceHttpRequestHandler cannot be cast to HandlerMethod

解决:在拦截器中加入判断

/**
 * @author WGR
 * @create 2021/3/9 -- 13:48
 */
@Slf4j
public class MyLogInterceptor implements HandlerInterceptor {

    //线程隔离,每个线程都有自己的其实时间,但是它有内存泄漏的风险。
    private static final ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //其实在请求的时候,requestMapping会把所有的方法封装成HandlerMethod,最后放到拦截器中,一起返回。
        if(handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();

            if (method.isAnnotationPresent(Log.class)) {
                //  设置开始时间
                long startTime = System.currentTimeMillis();
                threadLocal.set(startTime);
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            Log log = method.getAnnotation(Log.class);
            if(method.isAnnotationPresent(Log.class)){
                //  设置开始时间
                Long startTime = threadLocal.get();
                Long endTime = System.currentTimeMillis();
                Long expendTime = endTime - startTime;

                // 方法参数
                String uri = request.getRequestURI();
                String methodName = method.getDeclaringClass().getName() + "#" + method.getName();
                String methodDesc = log.value();
                String parameters = JSON.toJSONString(request.getParameterMap());
                MyLogInterceptor.log.info("
描述:{}
路径: {}
方法: {}
参数:{}
耗时:{}", methodDesc, uri, methodName, parameters, expendTime);
            }
        }

    }
}

如果你的项目中,还有静态资源,需要也在拦截器中,进行排除。

Spring boot 2.0 版本报错 ResourceHttpRequestHandler cannot be cast to HandlerMethod