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 环境中使用它们,您将遇到运行时错误
在我的项目中,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 环境中使用它们,您将遇到运行时错误