自定义SpringMVC拦截器中HandlerMethod类型转换问题调研

本文详细探讨了在将SpringMVC模块迁移到Spring Boot并使用内嵌Tomcat时,遇到的HandlerMethod类型转换异常问题。通过分析发现,问题源于内嵌Tomcat未正确处理context-path,导致请求被误识别为静态资源。解决方案是在`application.properties`中指定`server.contextPath`,从而避免问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘要

在将a模块迁移到spring boot项目下、使用embeded tomcat启动项目后,在调用RESTfule接口时,模块中声明的一个SpringMVC拦截器"cn.xxx.thread.common.web.speedctrlforuser.SpeedctrlForUserInterceptor"中抛出了ClassCastException。但是使用外置Tomcat启动就没有这个问题。在逐行debug后发现是spring boot缺失一项配置导致了这个问题。

问题

在 TECHSTUDY-91 - THREAD模块接入服务注册/订阅服务 进行中 任务中,我为a模块定义了一个启动类(注解了@SpringBootApplication),并配置了对应的application.properties。由于目前只需要注册到eureka上,配置文件中只有如下两行配置:

applictaion.properties
spring.application.name=a
eureka.client.serviceUrl.defaultZone=http://10.255.33.207:8080/eureka,http://10.255.33.208:8080/eureka,http://10.255.33.209:8080/eureka

在其它配置(如maven依赖关系、xml配置文件引入等)都整理好之后,用eclipse将a模块发布到tomcat上(即打成war包后发布),调用auth模块接口(如http://localhost:8080/a/rest/users/admin),一切正常。
但是,在使用启动类将模块发布到内置tomcat上(相当于打成jar包后发布),再调用上述auth模块的接口,会出现以下异常:

17:52:31,864 ERROR [org.apache.juli.logging.DirectJDKLog.log] (http-nio-8080-exec-2) Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.web.servlet.resource.ResourceHttpRequestHandler cannot be cast to org.springframework.web.method.HandlerMethod] with root cause^|TraceId.-http-nio-8080-exec-2
java.lang.ClassCastException: org.springframework.web.servlet.resource.ResourceHttpRequestHandler cannot be cast to org.springframework.web.method.HandlerMethod
at cn.xxx.thread.common.web.speedctrlforuser.SpeedctrlForUserInterceptor.preHandle(SpeedctrlForUserInterceptor.java:66) ~[classes/:?]
at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:133) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:962) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.proce***equest(FrameworkServlet.java:970)

分析

从上文的异常信息可知,问题出现在SpeedctrlForUserInterceptor的第66行。这里的代码是这样的:

public boolean preHandle(HttpServletRequest request,
        HttpServletResponse response, Object handler)
        throws TooManyRequestsException {
    User user = SecurityUtils.getUserFromPrincipal(SecurityContextHolder
        .getContext().getAuthentication());
    if (user == null) {
        return true;
    }
    HandlerMethod method = (HandlerMethod) handler; // 这里是第66行
    // 省略后续代码
}

在第66行,代码中做了一个强制类型转换。根据异常信息,在这里得到的handler是一个ResourceHttpRequestHandler,而不是HandlerMethod。所以会报错。
这里的ResourceHttpRequestHandler和HandlerMethod分别是什么呢?我们可以简单的看一下二者的Javadoc。

org.springframework.web.servlet.resource.ResourceHttpRequestHandler
HttpRequestHandler that serves static resources in an optimized way according to the guidelines of Page Speed, YSlow, etc.
The "locations" property takes a list of Spring Resource locations from which static resources are allowed to be served by this handler. Resources could be served from a classpath location, e.g. "classpath:/META-INF/public-web-resources/", allowing convenient packaging and serving of resources such as .js, .css, and others in jar files.
This request handler may also be configured with a resourcesResolver and resourceTransformer chains to support arbitrary resolution and transformation of resources being served. By default a PathResourceResolver simply finds resources based on the configured "locations". An application can configure additional resolvers and transformers such as the VersionResourceResolver which can resolve and prepare URLs for resou

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值