zoukankan      html  css  js  c++  java
  • Spring boot 2.0 版本报错 ResourceHttpRequestHandler cannot be cast to HandlerMethod

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

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

    image-20210309144020573

    代码如下:

    @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时抛出了异常。

    image-20210309152654781

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

    /**
     * @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);
                }
            }
    
        }
    }
    

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

    image-20210309154655590

  • 相关阅读:
    Java设计模式(十二) 策略模式
    Java设计模式(二) 工厂方法模式
    Java设计模式(一) 简单工厂模式不简单
    Kafka设计解析(四)- Kafka Consumer设计解析
    Kafka设计解析(三)- Kafka High Availability (下)
    Kafka设计解析(二)- Kafka High Availability (上)
    Spark 灰度发布在十万级节点上的成功实践 CI CD
    Spark SQL / Catalyst 内部原理 与 RBO
    Java进阶(七)正确理解Thread Local的原理与适用场景
    Kafka设计解析(八)- Exactly Once语义与事务机制原理
  • 原文地址:https://www.cnblogs.com/dalianpai/p/14505988.html
Copyright © 2011-2022 走看看