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("\n描述:{}\n路徑: {}\n方法: {}\n參數:{}\n耗時:{}", 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("\n描述:{}\n路徑: {}\n方法: {}\n參數:{}\n耗時:{}", methodDesc, uri, methodName, parameters, expendTime);
            }
        }

    }
}

如果你的項目中,還有靜態資源,需要也在攔截器中,進行排除。

image-20210309154655590


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM