内容

目录

常规

请首先阅读常规 迁移指南页面,了解适用于 Apache Tomcat® 版本之间迁移或升级的常见注意事项。

从 7.0.x 迁移到 8.0.x

本部分列出了 7.0.x 和 8.0.x 之间的所有已知更改,这些更改可能会在升级时导致向后兼容性问题。

需要 Java 7

Apache Tomcat 8.0.x 需要 Java 7 或更高版本。Apache Tomcat 7.0.x 需要 Java 6。

规范 API

Apache Tomcat 8 支持 Java Servlet 3.1、JavaServer Pages 2.3、Java Unified Expression Language 3.0 和 Java API for WebSocket 1.1 规范。规范版本之间的变更可能在每个规范文档的变更附录中找到。

Servlet 3.1 API

在使用通配符导入语法的 JSP 页面中,Servlet API 中添加的新类可能与 Web 应用程序中的类发生冲突。例如,如果包 "a" 包含类 ReadListener,则以下 JSP 页面将无法在 Tomcat 8 中编译

<%@page import="a.*"%>
<% ReadListener listener = new ReadListener(); %>

这是因为隐式导入 javax.servlet.* 和显式导入 a.* 将提供 Servlet 3.1 中添加的类 ReadListener 的冲突定义。解决方案是使用显式导入 import="a.ReadListener"

JavaServer Pages 2.3

Unified Expression Language 3.0 添加了对引用静态字段和方法的支持。在 JSP 中支持此功能需要更改 javax.servlet.jsp.el.ScopedAttributeELResolver 实现,以便它还检查标识符以查看它们是否是导入类或字段的名称。在某些情况下,此更改会触发显着减慢。这会影响可能引用页面、请求、会话或应用程序作用域变量的标识符,或者可能是未定义的。当未定义时,解析标识符需要花费更长的时间,因为它现在还会检查它是否是导入的类或字段。为避免这种减慢,诸如

${undefined}

应替换为

${requestScope.undefined}

或类似内容,使用变量定义的适当作用域。

Jar 扫描

在 Servlet 3.1 的实现过程中,在 Tomcat 7 的 Servlet 3.0 可插拔性实现中发现了许多错误。具体来说

  • SCI 扫描不遵守类加载器排序;
  • 容器 JAR 中的片段被处理而不是忽略;
  • 有时会忽略容器提供的 SCI。

这些问题已针对 Tomcat 8 进行了更正,但没有反向移植到 Tomcat 7,因为修复需要对 JarScanner 组件进行重大的 API 更改以及对配置选项进行更改。

在迁移到 Tomcat 8 时,需要查看 Jar 扫描配置并针对新的配置选项进行调整,并且需要更新自定义 JarScanner 实现以实现新的 API。

默认连接器实现

默认 HTTP 和 AJP 连接器实现已从 Java 阻塞 IO 实现 (BIO) 切换到 Java 非阻塞 IO 实现 (NIO)。仍然可以使用 BIO,但使用非阻塞 IO 的 Servlet 3.1 和 WebSocket 1.0 功能将改为使用阻塞 IO,这可能会导致意外的应用程序行为。

默认 URL 编码

HTTP 和 AJP 连接器的 URIEncoding 属性的默认值已从“ISO-8859-1”更改为“UTF-8”(如果“严格 servlet 兼容性”模式关闭,这是默认设置)。此设置指定用于解码请求 URI 的路径和查询中“%xx”编码字节的字符编码。

如果服务器配置为“严格 servlet 兼容性”打开,则连接器的 URIEncoding 属性的默认值是“ISO-8859-1”,与早期版本的 Tomcat 相同。

参考:HTTP 连接器AJP 连接器

领域

已将摘要密码的处理移至新的 CredentialHandler 组件。关联的 Realm 属性在 8.0.x 中仍将起作用,但它们已被弃用,并且已从 Tomcat 8.5.x 开始被移除。

Web 应用程序资源

别名、VirtualLoader、VirtualDirContext、JAR 资源和外部存储库功能都提供了一种向 Web 应用程序添加资源的方法,它们已被一个单一框架替换,而不是分别实现(这变得越来越难以维护)。资源文档提供了有关如何使用新实现的详细信息。

资源重构还导致从默认上下文实现(org.apache.catalina.core.StandardContext)中移除了一些属性。现在可以通过 Web 应用程序使用的 资源 实现配置以下属性

  • allowLinking
  • cachingAllowed
  • cacheMaxSize
  • cacheObjectMaxSize
  • cacheTtl(已重命名:在 Tomcat 7 中为 cacheTTL)

例如,Tomcat 7 和 Tomcat 8 中的配置

<!-- Tomcat 7: -->
<Context allowLinking="true" />

<!-- Tomcat 8: -->
<Context>
  <Resources allowLinking="true" />
</Context>

数据库连接池

Tomcat 8 和 Tomcat 7 都附带了数据库连接池的两个实现。第一个实现(默认实现;尽管从技术上讲,可以通过 javax.sql.DataSource.Factory 系统属性更改此实现)是 Apache Commons DBCP 2.x 项目的副本,已重命名为不同的包。第二个实现是 Tomcat JDBC 连接池,这是一个独立的项目。

Apache Commons DBCP 1.x(Tomcat 7 及更早版本使用)和 Apache Commons DBCP 2.x 之间有一些值得注意的更改,这些更改可能需要配置更改。

  • maxActive 配置选项已重命名为 maxTotal
  • maxWait 配置选项已重命名为 maxWaitMillis
  • JDBC 驱动程序 JAR 可以放在 WEB-INF/lib 中,作为 $CATALINA_BASE/lib 的替代方案,前提是该驱动程序类仅由该 Web 应用程序使用。
  • 连接验证不再需要验证查询和至少一个 testXxx 属性都设置为 true。如果未定义验证查询,并且至少一个 testxxx 属性为 true,则将使用 Connection.isValid() 验证连接。
  • removeAbandoned 配置选项已被 removeAbandonedOnBorrowremoveAbandonedOnMaintenance 取代。

此外,Commons DBCP 已添加了许多新的配置选项。应查看这些选项以确定是否应使用这些选项,以及使用哪些选项。

请注意,如果您使用的是 Tomcat JDBC 连接池(或任何第三方数据库连接池实现),则不需要上述更改。

集群

Servlet 3.1 中添加了 HttpServletRequest.changeSessionId() 方法,使得 org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener 变得不再必要,因此已将其移除。在升级到 Tomcat 8 时,必须将其从集群配置中移除。

调试

当使用 jpda 选项启动 Tomcat 以启用远程调试时,Tomcat 8 默认监听 localhost:8000。早期版本监听 *:8000。如果需要,可以通过在 setenv.[bat|sh] 中设置 JPDA_ADDRESS 环境变量来覆盖此默认设置。

内部 API

虽然 Tomcat 8 内部 API 与 Tomcat 7 基本兼容,但在细节级别上已进行了许多更改,并且它们在二进制上不兼容。与 Tomcat 内部交互的自定义组件的开发人员应查看相关 API 的 JavaDoc。

特别需要注意的是

  • Manager、Loader 和 Resources 已从 Container 移至 Context,因为 Context 是它们唯一使用的地方。
  • Mapper 已从 Connector 移至 Service,因为 Mapper 对于给定 Service 的所有 Connector 都是相同的。
  • 一个新的 Resources 实现将别名、VirtualLoader、VirtualDirContext、JAR 资源和外部存储库合并到一个框架中,而不是为每个功能提供一个单独的框架。
  • 已添加一个新的接口 SessionIdGenerator,使会话 ID 生成变得可扩展。已将获取和设置 ID 生成器类名的方法添加到 Manager 接口中。

部署

将 Web 应用程序部署为 WAR 文件,并且将 Tomcat 配置为不解压缩 WAR,将导致启动时间和运行时性能显著降低。已测量到启动时间慢了三到十倍。运行时影响将很大程度上取决于应用程序结构。

强烈建议不要在 Host 上设置 unpackWARs="false" 或在 Context 上设置 unpackWAR="false"。以下是禁用解压缩的常见原因以及 Tomcat 8 的建议替代方案的列表

  • 安全(appBase 对 Tomcat 用户是只读的) - 将解压缩的目录(作为不同的用户)部署到 appBase,而不是 WAR 文件。
  • 在多个主机之间共享 appBase - 将 WAR 文件部署到一个公共位置,然后使用 context.xml 文件根据需要将 Web 应用程序添加到主机。请注意,强烈不建议在任何情况下在多个主机之间共享 appBase。
  • 脱机部署 - 从 Tomcat 8.0.21 开始,当 WAR 在未运行时已更新,Tomcat 将检测到它,并且在下一次启动时,它将删除过时的扩展目录并部署更新的 WAR 文件,因此只需使用 unpackWAR="true",并在 Tomcat 未运行时继续部署 WAR。

升级 8.0.x

在将 Apache Tomcat 实例从一个 Tomcat 8 版本升级到另一个版本时,特别是当为 $CATALINA_HOME 和 $CATALINA_BASE 使用单独的位置时,必须确保在升级过程中应用配置文件中的任何更改,例如新属性和对默认值的更改。为了帮助识别这些更改,可以使用下面的表单查看 Tomcat 8 不同版本中配置文件之间的差异。

Tomcat 8.0.x 值得注意的更改

Tomcat 开发人员的目标是让每个修补程序版本与之前的版本完全向后兼容。有时,为了修复错误,必须打破向后兼容性。在大多数情况下,这些更改将不会被注意到。本部分列出了不完全向后兼容且在升级时可能导致中断的更改。

  • 从 8.0.24 开始,连接器上 maxPostSize 属性的值 0 的含义已更改为表示零限制,而不是无限制,以使其与 maxSavePostSize 保持一致并更直观。

    参考:HTTP 连接器AJP 连接器

Tomcat 8.0.x 配置文件差异

从下面的框中选择一个配置文件、旧版本和新版本,然后单击“查看差异”以查看差异。差异将显示在一个新选项卡/窗口中。

您还可以使用类似于以下内容的 Subversion 命令(全部在一行中)

svn diff
  --old=http://svn.apache.org/repos/asf/tomcat/archive/tc8.0.x/tags/TOMCAT_8_0_1/conf/
  --new=http://svn.apache.org/repos/asf/tomcat/archive/tc8.0.x/tags/TOMCAT_8_0_3/conf/