Spring boot 2.0 版本报错 ResourceHttpRequestHandler cannot be cast to HandlerMethod
在写自定义的starter的时候,做了一个拦截器,但是在强转的时候,抛出了异常,具体如图。
代码如下:
@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时抛出了异常。
解决:在拦截器中加入判断
/**
* @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);
}
}
}
}
如果你的项目中,还有静态资源,需要也在拦截器中,进行排除。