解决访问出现404和500的问题(Tomcat与ServletJSPJDK的版本适配问题)
Posted 石工记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决访问出现404和500的问题(Tomcat与ServletJSPJDK的版本适配问题)相关的知识,希望对你有一定的参考价值。
一、问题描述
在Maven创建Java Web项目的过程中,常出现了配置Servlet后访问出现404和500的问题,如下
二、出现原因
在网上查了许多资料之后,我发现这是因为Tomcat版本的适配问题。
在Tomcat的官网中,我们可以看到不同版本的Tomcat适配的JDK、Servlet、Jsp以及EL的版本,如下:
由于我使用的是Tomcat10.0.12的版本,而我使用Maven导入的依赖如下
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.2-b01</version>
</dependency>
这将导致Tomcat版本无法兼容Servlet版本(tomcat10将JavaEE更换成了Jakarta® EE,所以原Servlet包"javax.servlet.“更改成了"jakarta.servlet.”),我们在500的图中根本原因的第一行也可以看到:Register cannot be cast to class Jakarta.servlet.Servlet,即我使用的是Servlet是javax包里的,而Tomcat能够识别(适配)的是Jakarta包里的,而javax包里的Servlet类无法转换为Jakarta包里的Servlet类,所以显示了例外情况里的第一行:类cn.ken.controller.Register不是Servlet。
三、解决方法
既然是由于Tomcat版本与Servlet版本不匹配造成,那么自然就有对应的两种解决方法
1、降低Tomcat版本
因为tomcat10才改成Jakarta,故只需将Tomcat版本降低到10以下,例如Tomcat9等。
当然还要结合具体情况进行分析,让使用的Tomcat版本能够匹配自己使用的JSP或JDK等的版本
除了通过下载安装新的Tomcat(这显然比较麻烦),我们也可以通过Maven安装低版本的Tomcat插件来运行,具体操作可见Maven继承Tomcat插件
2、提高Servlet版本
将pom.xml中的Servlet更换为最新的依赖,与使用的Tomcat匹配,如下
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>10.0.12</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
<version>10.0.12</version>
</dependency>
重新加载Maven变更后即可成功访问Sevrlet
四、相关内容
对于 JDK,高版本的Tomcat是可以正常使用低版本的JDK,反之则不行
JAVA servlet 2.x规范:
项目目录结构必须要有WEB-INF,web.xml等文件夹和文件
在web.xml中配置servlet,filter,listener,以web.xml为java web项目的统一入口
JAVA servlet 3.x规范:
项目中可以不需要WEB-INF,web.xml等文件夹和文件
在没有web.xml文件的情况下,通过注解实现servlet,filter, listener的声明,例如
@WebServlet, @WebFilter,@WebListener,当使用注解时,容器自动进行扫描。
五、Tomcat使用注意事项——Servlet版本
解决
但是这个filter作为一个基础SDK,已经被接近200个业务方使用,所以不得不考虑升级的成本,为了使得推动升级的过程可以较为顺利,所以希望尽量减少业务方升级的成本(最好是只需要改一下POM文件中的版本就可以)。
于是乎,想了个主意,自定义一个XXXRequest implements HttpServletRequest ,然后重写getAttribute方法。其实就是简单的代理。
把filter中的逻辑移到这个XXXRequest中,原先filter中的doFilter改为:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
chain.doFilter(new XXXRequest(request), response);
在XXXRequest的getAttribute时,才会真正的来调用服务,进行原先的逻辑处理。可以理解为懒处理了,只有在真正需要的时候才走这块逻辑。
问题暴露
开始推动业务方升级了,一开始兴高采烈,直到有一天一个人来找我,说,升级完之后项目启动不了了。自己debug完之后,发现:
java.lang.NoClassDefFoundError: javax/servlet/http/HttpUpgradeHandler
1
盯着代码沉默一会,我觉得自己的代码没有问题,自信是程序员的本能!但是,问题就是这么发生了!本人有个习惯,电脑上必装jdk6,jdk7,jdk8,tomcat6,tomcat7,tomcat8,就是为了这一刻。于是尝试了不同的环境,发现在tomcat7下,会报上面的错,如果是tomcat6的话:
java.lang.NoClassDefFoundError: javax/servlet/http/Part
1
好吧,还是NoClassDefFoundError。可是我的POM里是有依赖的啊:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
去看了看Tomcat官网的介绍,才明白,不同版本的Tomcat支持的Servlet规范的版本是不一样的:
错竟然就是我用的javax.servlet-api版本太高,只有Tomcat8.0.x之后才支持。
于是试了Tomcat8,果然可以!当然,解决方案其实是降低我这个sdk中的javax.servlet-api的版本。
六、ideaij布署方式与eclipse布署方式区别:
1.intellij idea使用Tomcat部署项目后并不会把编译后的项目复制到tomcat的webapps目录下,但是它会把编译好的项目路径告诉Tomcat,让Tomcat来找到这个项目,其它的项目比如Tomcat的主页项目ROOT是打不开的,因为intellij idea 只让Tomcat运行了一个项目.
所以web项目不是必须放在webapps文件夹里面才能部署的,放在其它位置为也可以部署,
eclipse默认放在工作空间的.metadata文件夹,可以修改到其它地方,一般配置在webapps文件夹.
而idea是配置到out文件夹,就是输出目录.
2.tomcat部署方式分别是:
(1)eclipse 利用Tomcat自动部署
项目放到webapps目录下,启动tomcat,就回自动部署
(2)ideaIJ利用控制台进行部署
控制台不是说cmd,而是tomcat启动后进入root页面,有个manager管理部署项目.
进入tomcat的manager控制台的deploy区域进行设置就可以部署
以上是关于解决访问出现404和500的问题(Tomcat与ServletJSPJDK的版本适配问题)的主要内容,如果未能解决你的问题,请参考以下文章
解决访问出现404和500的问题(Tomcat与ServletJSPJDK的版本适配问题)
Myeclipse中tomcat启动,index.jsp访问出现404或者500错误!!