“案发现场”:一个看似完美的 Hello Servlet

我的开发环境如下:

  • JDK: Java 17

  • 服务器 (Server): Apache Tomcat/9.0.96

  • 构建工具 (Build Tool): Maven

  • IDE: IntelliJ IDEA

我按照教程写下了一个经典的 HelloServlet,代码逻辑清晰,编译一切正常。但当我兴冲冲地部署 并访问它时,却直接出现500 内部服务器错误。

我开始疯狂地排查:URL 拼写错了吗?web.xml 配置漏了 / 吗? @WebServlet 注解替代 pom.xml 配置可行吗? 用自带模板Tomcat 能启动吗?甚至,我经历了“删库跑路”的经典新手操作——删掉旧项目,重建一个,结果因为忘了停止旧的 Tomcat 进程,又遇到了端口占用 (Port Conflict) 的问题。

在解决了端口占用后,那个可恶的 500 依旧屹立不倒。

柳暗花明:一句关键的报错信息

在我各种简化测试的尝试下,终于将范围缩小到java文件本身,我发现还是得面对页面的一大串报错信息。终于定位到了一条关键的异常 (Exception):javax.servlet.ServletException:实例化Servlet类com, liu.web.HelloServlet]异常。

类实例化异常! 这意味着 Tomcat 服务器在尝试加载我的 Servlet 时,根本没法找到 javax.servlet 这个类。但是啊但是,我明明没有在 pom.xml 里引入 javax,用的是  jakatra.servlet

解决方案随之而来:将我代码中所有的 import jakarta.servlet.* 全部替换为 import javax.servlet.*

改完后,重启 Tomcat。 ̄へ ̄——我的 "Hello Servlet" 页面成功显示!

刨根问底:javaxjakarta 的“前世今生”

问题解决了,为什么会有两套 Servlet API?啥关系噻?

经过一番 探索 AI ,我终于理清了这背后的历史脉络:

  1. javax 时代:最初,Java 的企业级规范被称为 Java EE (Java Enterprise Edition),由 Oracle 公司主导。其下所有的 API 都位于 javax 包中,javax.servlet 便是其中之一。

  2. 开源移交:2017年,Oracle 将 Java EE 移交给开源的 Eclipse 基金会 (Eclipse Foundation)。但由于“Java”是 Oracle 的商标,基金会不能在新项目中使用 javax 这个名字。

  3. jakarta 诞生:因此,Eclipse 基金会为这个新项目命名为 Jakarta EE。从 Jakarta EE 9 开始,为了彻底与过去的版权问题告别,社区进行了一次“大爆炸”式的重构——将所有 API 的包名从 javax.* 强制切换到了 jakarta.*

所以,javax.servletjakarta.servlet 本质上是同一套规范在不同历史时期的不同命名

核心关键:Tomcat 版本与 Servlet 规范的对应关系

这也就解释了我的问题所在。问题的根源不在于 JDK 版本,而在于我使用的 Tomcat 版本是9.0的

TOMCAT 版本 实现的 SERVLET 规范 必须使用的包名
Tomcat 8.5 / 9.0 Servlet 4.0 javax.servlet
Tomcat 10.0 Servlet 5.0 jakarta.servlet
Tomcat 10.1 / 11.0 Servlet 6.0 jakarta.servlet

而 Tomcat 9.0.96 是一个实现了 Servlet 4.0 规范的服务器,它诞生于“jakarta 改名”事件之前,因此,它的世界里只认识 javax.servlet。当它看到我代码中 importjakarta.servlet 时,自动的忽略掉了,还一直问我 (*´ノ皿`) :“朕的 javax 呢 !? ”,在下跪了へ(;´Д`へ)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐