Tomcat 如何知道为 运行 servlet 选择哪个 jar?

How does Tomcat know which jar to choose for running a servlet?

在我的项目中,Apache Tomcat 8.5 context.xml配置如下

<Context path="/helloWorld" docBase="C:\projects\helloWorld\app" crossContext="false" debug="0" reloadable="false"/>

C:\projects\helloWorld\app 有一个 web-inf\lib 文件夹,其中包含一个 servlet.jar 以及应用程序需要的其余 jar。

此应用程序部署到 Tomcat 8.5 网络服务器,%TOMCAT_HOME%\lib 文件夹还包含一个 servlet-api.jar .

应用程序按预期工作。

我检查了这两个 jar,servlet.jar 包含常规 servlet api 类 而 tomcat 的 servlet-api.jar 包含这些常规 servlet api 类 以及许多其他相关的 servlet 功能 类。

查询: 由于运行一个servlet有两个jar,servlet.jar和servlet-api.jar,Tomcat如何知道在运行一个servlet时选择哪个jar ?

TLDR:

Tomcat 将加载自己版本的 servlet API,因为这是 JavaEE 规范所要求的。

长答案

JavaEE 定义了 classes 的加载和解析方式。

通常 class-loaders 是 parent-first - 即尝试从 parent class-loader 加载 classes只有当失败时,他们才会尝试自己加载 class。

但是网络应用程序有一个 self-first class-loader 可以从自身加载 classes 并且只有在失败时才会尝试加载来自 parent。但也有一些例外:

  • 那些 self-first class-loaders 无法覆盖 JRE classes
  • 他们总是“parent-first”加载 JavaEE classes

您可以在 Apache Tomcat's docs

上阅读更多详细信息

只要 servlet api 版本匹配应该没有任何问题。但是,如果您的 servlet 是针对不同的 api 版本编译的,例如它们是使用 Servlet v4 编译的,但您尝试在 Servlet v3 环境中使用它们,您将遇到运行时错误