Tomcat10的servlet依赖问题

项目场景:

项目场景:简单的SSM架构CRM项目,属于一个练习项目,由于视频上使用的较旧的技术,所以在自己做的时候全部替换为新的内容。
开发环境:
1. JAVA:21.0.2
2. Maven:3.9.6
3. Spring:6.1.6
4. 数据库:MariaDB11.0
5. MyBatis:3.5.16
6. IDE:eclipse


问题描述

在编写了Controller方法后(方法接收参数HttpServletRequest),当前端访问Controller时,会报错,报错信息如下:

518, 2024 9:30:42 下午 org.apache.catalina.core.StandardWrapperValve invoke
严重: 在路径为[/crm-core]的上下文中,Servlet[dispatcher]Servlet.service()引发了具有根本原因的异常[Reque
st processing failed: java.lang.IllegalArgumentException: Name for argument of t
ype [java.lang.String] not specified, and parameter name information not availab
le via reflection. Ensure that the compiler uses the '-parameters' flag.]
java.lang.IllegalArgumentException: Name for argument of type [java.lang.String]
 not specified, and parameter name information not available via reflection. Ens
ure that the compiler uses the '-parameters' flag.
	at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentRe
solver.updateNamedValueInfo(AbstractNamedValueMethodArgumentResolver.java:187)
	at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentRe
solver.getNamedValueInfo(AbstractNamedValueMethodArgumentResolver.java:162)
	at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentRe
solver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:108)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposit
e.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgum
entValues(InvocableHandlerMethod.java:224)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForReque
st(InvocableHandlerMethod.java:178)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandle
rMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA
dapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA
dapter.handleInternal(RequestMappingHandlerAdapter.java:831)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapt

确保了依赖引入完全无漏项,Controller方法参数无拼写错误。

/**
     * 用户输入账号及密码,请求登录
     * 
     * @param loginAcc     账号
     * @param loginPwd     密码
     * @param isRemembered 是否记住密码
     * @return
     */
    @RequestMapping("/settings/qx/user/login.do")
    @ResponseBody
    public Object login(HttpServletRequest request, String loginAcc, String loginPwd, String isRemembered) {
    //做了一些事情
    }

用AI问了一下,提示Maven构建工具要添加==-parameters==选项,那就加上呗,实际上Maven的settings里面已经设置了。

<build>
    <plugins>
         <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.13.0</version>
              <configuration>
              	<source>21</source>
              	<target>21</target>
              	<compilerArgs>
             		 <arg>-parameters</arg>
              	</compilerArgs>
              </configuration>
         </plugin>
   </plugins>
</build>

添加后又出现了另一个错误,实际上这个错误才是最主要的错误,在网上检索了很久才发现。
报错信息如下:

Servlet[dispatcher]Servlet.service()引发了具有根本原因的异常[Reque
st processing failed: java.lang.IllegalStateException: No primary or single uniq
ue constructor found for interface javax.servlet.http.HttpServletRequest]
java.lang.IllegalStateException: No primary or single unique constructor found f
or interface javax.servlet.http.HttpServletRequest
	at org.springframework.beans.BeanUtils.getResolvableConstructor(BeanUtils.java:
265)
	at org.springframework.validation.DataBinder.createObject(DataBinder.java:924)
	at org.springframework.validation.DataBinder.construct(DataBinder.java:903)
	at org.springframework.web.bind.ServletRequestDataBinder.construct(ServletReque
stDataBinder.java:116)

这个报错似乎在说Spring在想注入HttpServletRequest的时候没有找到,AI的回答具有很强的误导性,但是也给了我一些启发:

这个异常java.lang.IllegalStateException: No primary or single unique constructor found for interface javax.servlet.http.HttpServletRequest 是由于Spring框架在尝试为HttpServletRequest接口实例化一个对象时遇到的问题。但是,HttpServletRequest是一个接口,它不能被直接实例化,而应该由Servlet容器(如Tomcat, Jetty等)在HTTP请求到达时提供实现。
这个异常很可能是由于Spring框架的某个配置错误或误用导致的。这里有几个可能的原因和相应的解决方案:
错误的注解使用:你可能在某个地方错误地使用了@Autowired或其他Spring的注入注解来尝试注入HttpServletRequest。HttpServletRequest应该作为方法的参数,通过Spring的HandlerMethodArgumentResolver自动解析,而不是作为类的成员变量通过注解注入。
解决方法:将HttpServletRequest作为方法参数,而不是类成员变量。
错误的配置:可能在某个Spring配置类中,你尝试使用@Bean注解来创建一个HttpServletRequest的Bean,这是不正确的。
解决方法:移除或更正任何尝试创建HttpServletRequest Bean的配置。


原因分析:

Java Servlet API 是由 Sun Microsystems(现在是 Oracle)开发和维护的,其包名以 javax.servlet 开头。从 Java EE 8 开始,Servlet API 的维护权转交给了 Eclipse Foundation 的 Jakarta EE 社区,因此,在最新的 Jakarta EE 版本中,Servlet API 的包名已经更改为 jakarta.servlet。
Tomcat10以后的版本需要 jakarta.servlet,而不是javax.servlet
原文链接:javax.servlet 和 jakarta.servlet的关系和使用tomcat部署 jakarta.servlet

也就是我的依赖中Servlet导入的是javax.servlet-api,但是服务器却使用的是Tomcat10,而Tomcat10不再依赖javax.servlet-api,而是依赖jakarta.servlet-api,这个就是根本的原因:依赖导入的问题,但是报错信息以及AI的解答均有一定的迷惑性,所以走了一些弯路。


解决方案:

导入jakarta.servlet-api依赖替换javax.servlet-api

<dependency>
	<groupId>jakarta.servlet</groupId>
	<artifactId>jakarta.servlet-api</artifactId>
	<version>6.0.0</version>
	<scope>provided</scope>
</dependency>

举一反三

在使用各类中间件的时候,必须考虑中间件的依赖,因为中间件的依赖可能存在一定的滞后性,如果遇到类似的报错,需要考虑到这一点。

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉拌糖醋鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值