Maven导入Servlet-api包导致无法运行报500的问题
以下解决方式适用于跟我类似的配置环境,构建servlet程序后,启动Tomcat页面报“类com.tioxy.servlet.MyServlet不是Servlet,MyServlet cannot be cast to class jakarta.servlet.Servlet”或者“实例化Servlet类异常”的500错误的问题。
我的本机配置环境:
1.IDEA 2020.1,Tomcat 10.0.0M5,Maven 3.6.3,导入的javax.servlet-api 4.0.1
最近在学习Java Servlet,并用Maven构建的模板,导入servlet-api依赖包,写了一个简单的Servlet程序,就是很简单的重写doGet、doPost,向页面输出一段“hello,servlet”文本。
然后配置Tomcat服务器,跑起来控制台输出也正常,一切看起来似乎没什么问题,心想servlet构建起来也不过如此嘛!
当我输入/hello,准备见证奇迹时......
这......,不是一个servlet类???,回去跟了跟代码,确定没写错啊,要不百度吧,看看网上怎么说。
哦,原来是导入的Servlet-api包与tomcat冲突,tomcat自带了jar包,需要在自己导入的jar包上添加作用域。原来如此那么咱也加上,这不很简单,小意思。
重新启动,重新输入/hello,正要准备结束一切,迎接结果时
这怎么跟刚才的错误还不一样,实例化Servlet类异常,说是找不到javax/servlet/http/HttpServlet,我明明导入了jar包啊,也加了作用域了,难道我用的新版兼容性不好???
于是我想,要不不用maven依赖导包了,我自己建了一个lib目录,把servlet-api包放到里面,然后再引用自己的包。
然后再次运行,输入/hello
这怎么又回到第一个错误了,心情有点烦,这么简单的都跑不起来,开始怀疑智商......然后检查生成的target目录
这也没毛病啊,于是这样反复两小时,发现不加依赖包作用域,生成的target包lib目录下有servlet-api包,加了作用域,反而没了,于是我加了作用域,在F4模块构件时添加servlet-api包,试了几次还是不行,顿时心态炸了,这么简单的玩意都搞不定,开始怀疑人生。
我又开始想,既然tomcat自带了jar包,那我直接选用tomcat依赖不就行了。
点击应用后,发现程序爆红了
玩我呢,我这不添加依赖了吗,而且还是tomcat自带的依赖。于是我删掉,重新写了一遍类
咦?这不有HttpServlet吗?为啥刚才给我爆红,思考了三秒钟。。。不管了,先跑起来再说。
撸完了代码,重新启动,抱着最后的希望,输入/hello(说实话,在输入的过程中,我向上帝祈祷了。。。)
嚯,终于通了,留下了激动的泪水,看了看表,距离我第一次启动已经过去三个小时了,跑个程序是真不容易啊,简直是玩命啊!!!,怀疑的我差点想放弃了。
成功是成功了,但是咱要分析问题,这次为什么能成功呢?还记得上面有个小疑问,为啥导入tomcat依赖,程序报错,我自己手写了一遍,发现是能索引出来HttpServlet的这个类。
经过反复的重试,我重新导入maven依赖包,这次tomcat与maven的两个包同时存在。果真,真发现了猫腻:
这两个包的包名不一致
重新看了第一次报错500的原因,注意标注的位置,人家报的是找不到jakarta.servlet.Servlet。
于是大概明白了,Tomcat10竟然改包名了。在tomcat运行的时候,首先会加载tomcat自带的servlet-api包,因为自己导入的包名与tomcat自带的不一致,所以一致报错500,真相大白!
解决方法
看了这么长苦逼的操作,总算是解决了问题,那么同样问题的小伙伴该怎么解决呢,我提供了两种方案:
- 降Tomcat版本,降到9版本的。
- 不用降版本,不要使用maven导入的servlet-api包,在F4的项目模块中引入Tomcat依赖,操作步骤在上面有说明。
这只是我自己的解决方式,如果哪位小伙伴有更好的方式,也可以在评论区留言。