内容
目录
通用
请首先阅读通用的迁移指南页面,了解适用于 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 统一表达式语言 3.0 和 Java WebSocket API 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
统一表达式语言 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 编码
Realm 域
摘要密码的处理已移至新的 CredentialHandler 组件。相关的 Realm
属性在 8.0.x 中仍然有效,但它们已被弃用,并已从 Tomcat 8.5.x 及更高版本中移除。
Web 应用程序资源
Aliases、VirtualLoader、VirtualDirContext、JAR 资源和外部存储库功能都提供了向 Web 应用程序添加资源的方式,它们已被一个统一的框架取代,而不是各自独立实现(这变得越来越难以维护)。资源文档详细说明了如何使用新实现。
资源的重构还导致从默认的 Context 实现 (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
配置选项已被removeAbandonedOnBorrow
和removeAbandonedOnMaintenance
取代。
此外,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 实现,将 Aliases、VirtualLoader、VirtualDirContext、JAR 资源和外部存储库合并到一个单一框架中,而不是为每个功能单独实现。
- 新增了一个 SessionIdGenerator 接口,使会话 ID 生成可扩展。Manager 接口中已添加获取和设置 ID 生成器类名的方法。
部署
将 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 开始,Tomcat 将检测到在它未运行时 WAR 文件是否已更新,并在下次启动时移除过时的已展开目录并部署更新的 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.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/