§前言
在深入了解本版本亮点之前,我们强烈建议您熟悉以下主题,因为它们可能与您在业务中使用 Play 框架相关
我们还想提醒您,我们目前正在寻找额外的优质赞助商。如果您的公司在财务上能够承担这样的角色,我们非常感谢您与我们联系。更多详细信息请访问 这里。
最后但并非最不重要的一点是,我们要向所有 优质赞助商和所有个人(现任和前任)表示衷心的感谢,他们的慷慨捐助使我们能够继续开发 Play 框架。
如果没有您的支持,这个版本将永远不会实现!
§Play 2.9 中的新功能
本节重点介绍 Play 2.9 的新功能。如果您想了解迁移到 Play 2.9 时需要进行的更改,请查看 Play 2.9 迁移指南。
此页面也适用于 Play 3.0,其中包含与同时发布的 Play 2.9 相同的新功能和错误修复。唯一的区别是 Play 2.9 基于 Akka 和 Akka HTTP,而 Play 3.0 基于 Pekko 和 Pekko HTTP。如果您想在迁移到 Play 2.9 后继续使用 Pekko 迁移到 Play 3.0,请参考 Play 3.0 迁移指南。
§Scala 3 支持
Play 2.9 提供 Scala 3 工件!您现在可以使用 Scala 3.3.1 或更高版本与 Play 结合使用。请注意,Scala 版本范围从 3.0 到 3.2 不受支持。请注意,某些迁移步骤是必需的。有关全面指南,请参阅 Scala 3 迁移指南。
重要的是要强调,Play 专门支持 Scala LTS(长期支持) 版本。因此,任何介于 Scala 3.3 LTS 和后续 LTS 版本之间的 Scala 版本都不会得到 Play 的官方支持。但是,使用此类 Scala 版本可能仍然可行。
目前没有立即将您的 Play 应用程序迁移到 Scala 3 的压力,因为 Scala 2.13 仍在维护中,我们预计未来几年将发布新的 Scala 2.13 版本。 不过,在您未来的路线图中开始考虑应用程序的升级是明智之举。
根据您的代码库,将现有的 Play 应用程序迁移到 Scala 3 可能是一项艰巨的任务。我们强烈建议您首先 迁移 到 Play 2.9,同时保留在 Scala 2.13 上。这种方法确保一切按预期运行。之后,您可以 迁移 到 Scala 3。
§Java 17 和 21 支持
Play 2.9 是第一个主要版本,它提供对 Java 21 LTS 和 Java 17 LTS 的开箱即用支持。虽然使用 Play 2.8.15 已经可以使用 Java 17,但 这仍然需要一些调整。
升级到 Play 2.9 时,我们强烈建议您考虑升级到至少 Java 17 LTS。值得注意的是,在即将发布的 Play 2.x 版本(版本 2.10)中,我们可能会停止对 Java 11 的支持。我们做出此建议的决定是基于 Play 依赖的库已经停止提供 Java 11 工件。因此,我们希望避免将来遇到安全问题,因为我们可能无法升级这些依赖项。此外,您可能对我们在 Play 2.9 发布之前进行的本地基准测试感兴趣,该测试使用 TechEmpower 的框架基准测试套件:结果表明,仅升级到 Java 17 就可以提高性能,这可能会提高您的应用程序的性能。
请注意,在 Java 17 和 Java 21 中使用自签名证书绑定 HTTPS 端口可能会导致问题。有关此问题的更多详细信息,请参阅 Play 2.9 迁移指南中的 "Java 17 和 Java 21 中自签名证书的生成失败"。
Play、其独立模块、示例和种子项目都针对 OpenJDK Temurin 版本 11、17 和 21 进行了严格测试。
Play 仅支持 Java LTS 版本。因此,任何介于 Java 21 LTS 和后续 LTS 之间的 Java 版本都不会从 Play 获得官方支持,即使可能仍然可以使用该版本与 Play 一起使用。
§Scala 2.12、sbt 0.13 和 Java 8 支持已停止
与 Scala 2.12 一同,我们选择在此版本中停止对 Java 8 的支持。此决定是由于 Play 依赖的越来越多的库已停止提供 Java 8 工件。此外,Play 2.9 最终告别了对 sbt 0.13 的支持。虽然 Play 可能仍然与各种 sbt 1.x 版本兼容,但我们官方支持的版本为 sbt 1.9.6 或更高版本。因此,我们强烈建议您使用 最新可用的 sbt 版本 来维护您的设置。
§Akka HTTP 10.2
虽然 Play 2.9 继续使用 Akka 2.6,但它已升级到 Akka HTTP 10.2,这是从 10.1 的升级。需要注意的是,Play 2.9 将保持这些版本,不会超过它们。此决定的依据是 Akka 2.6 和 Akka HTTP 10.2 代表了仍然受 Apache 许可证管辖的最终版本。后续的 Akka 版本受 BSL 约束,Play 故意避免使用它。我们强烈建议您查看
§Guice 升级到版本 6
Play 使用的默认依赖注入框架 Guice 已升级到版本 6.0.0(从 4.2.3)。请查看 5.0.1、5.1.0 和 6.0.0 版本说明以获取更多详细信息。如 Guice 6 版本说明中所述,您可以继续使用 javax.inject
命名空间。或者,如果您愿意,可以选择切换到 jakarta.inject
。
需要注意的是,在 Play 的下一个主要版本中,我们将升级到 Guice 7,它不再支持 javax.inject
。
§Jackson 升级到 2.14
Jackson 已经获得了期待已久的更新,超出了 2.11 版本。在 Play 2.9 中,默认的 Jackson 版本为 2.14,即使更新的版本已经可用。此决定的主要影响因素是 Akka 和更广泛的兼容性环境。Akka 和 Pekko 都尚未升级到这些更新的 Jackson 版本,我们旨在避免与这些关键组件不兼容的潜在风险。但是,如果您需要,您已经可以按照 此处 所述的方式升级到更新的版本。
§迁移到 Jakarta Persistence
从 Java Persistence API 迁移到 Jakarta Persistence API 现在为 Hibernate 6 及更高版本以及 EclipseLink 3 及更高版本提供支持。请参考相应的 迁移指南,获取有关将 Hibernate 或 EclipseLink 升级到新命名空间的详细说明。
§升级 sbt-web 和 sbt-js-engine
sbt-web 和 sbt-js-engine 进行了重大重构,带来了几个显著的改进。
sbt-web 已 移除对 Akka
的依赖,简化了两个代码库,并作为一项有益的副作用,解决了内存泄漏问题。以前独立的项目 npm 和 js-engine 已集成到 sbt-js-engine 中。
从 1.3.0 版本开始,Play 附带的 sbt-js-engine 在使用支持 Node.js 的本地安装的 js 引擎时,会尝试检测系统的 npm
命令。它将使用系统的 npm
而不是过时的 npm
webjars,后者不支持较新的 npm
命令。此行为现在是默认行为,可以通过 npmPreferSystemInstalledNpm := false
禁用。此设置确保无论使用哪个引擎,都使用 webjar npm。
此外,从 1.3.0 版本开始,可以通过设置 npmSubcommand := NpmSubcommand.Install
来指定要使用的 npm
子命令(可用选项包括 Install
、Ci
和 Update
,其中后者为默认选项)。
§HikariCP 升级
HikariCP 是 Play 的默认 JDBC 连接池,已升级到 5.0 版本。您可以查看 变更日志 以了解有关此版本的详细信息。此升级使我们能够引入一个新的配置选项:play.db.prototype.hikaricp.keepaliveTime
(或针对特定数据库,如 default
,则为 db.default.hikaricp.keepaliveTime
)。此配置接受持续时间值,例如 1 minute
。
有关此设置的更全面信息,请参阅 HikariCP GitHub README。
§其他新增功能
§结果属性
与请求属性类似,Play 现在支持结果属性。这些属性的功能相同,允许您在结果对象中存储额外的信息以供将来访问。此功能在利用动作组合或过滤器时特别有用。由于方法与用于请求属性的方法相同,您可以参考请求属性的工作原理,并对结果对象应用类似的方法。
§延迟体解析
默认情况下,体解析发生在通过动作组合定义的动作之前处理。现在可以更改此顺序。有关原因和更改方法的更多详细信息,请参阅Java 和 Scala 文档。
§在动作组合中包含 WebSocket
动作方法
在使用 Play Java 时,请考虑以下使用动作组合的控制器示例
@Security.Authenticated
public class HomeController extends Controller {
@Restrict({ @Group({"admin"}) })
public WebSocket socket() {
return WebSocket.Text.acceptOrResult(request -> /* ... */);
}
}
以前,在处理 WebSocket
(例如上面显示的 socket()
方法)时,不会应用动作组合。因此,像 @Security.Authenticated
和 @Restrict
(来自Deadbolt 2 库)这样的注释没有效果,并且从未执行。Java WebSocket 文档建议使用 acceptOrResult
方法来检查用户权限等。
从 Play 2.9 开始,您现在可以通过将其设置为 true
来启用新引入的配置选项 play.http.actionComposition.includeWebSocketActions
。在动作组合中包含 WebSocket 动作方法可确保使用 @Security.Authenticated
和 @Restrict
注释的动作现在按预期执行。这种方法的优点是您可能不需要在 acceptOrResult
方法中复制身份验证或授权代码,该方法已在注释动作方法中实现。
§可配置的 Evolutions 脚本位置
现在可以使用新的 play.evolutions[.db.default].path
配置自定义演进脚本的位置。这使得可以在 Play 项目中的特定位置存储演进脚本,甚至可以使用绝对路径或相对路径在项目根文件夹之外存储演进脚本。有关完整信息,请参阅 演进文档。
§演进脚本中的变量替换
演进脚本现在支持占位符,这些占位符将被替换为在 application.conf
中定义的相应值。
play.evolutions.db.default.substitutions.mappings = {
table = "users"
name = "John"
}
例如,像这样的演进脚本
INSERT INTO $evolutions{{{table}}}(username) VALUES ('$evolutions{{{name}}}');
将在演进应用程序过程中转换为
INSERT INTO users(username) VALUES ('John');
。
注意:演进元表保留原始 SQL 脚本,不包含替换后的占位符。
元表默认名为
play_evolutions
。您可以通过配置play.evolutions.db.default.metaTable
来修改它。
变量替换不区分大小写。因此,$evolutions{{{NAME}}}
等效于 $evolutions{{{name}}}
。
您还可以修改占位符语法的开头和结尾
# Change syntax to @{...}
play.evolutions.db.default.substitutions.prefix = "@{"
play.evolutions.db.default.substitutions.suffix = "}"
演进模块支持一种转义机制,用于在不应替换变量的情况下使用。此机制默认启用。要禁用它,请设置
play.evolutions.db.default.substitutions.escapeEnabled = false
启用后,可以使用 !$evolutions{{{...}}}
来转义变量替换。例如
INSERT INTO notes(comment) VALUES ('!$evolutions{{{comment}}}');
不会被替换为其替换,而是会变成
INSERT INTO notes(comment) VALUES ('$evolutions{{{comment}}}');
在最终的 SQL 中。
此转义机制适用于所有
!$evolutions{{{...}}}
占位符,无论在substitutions.mappings
配置中是否定义了变量映射。
§演进元数据表的自定义命名
现在可以为每个数据源重命名 play_evolutions
元数据表。例如,如果您希望将 default
数据源的元表命名为 migrations
,请设置以下配置
play.evolutions.db.default.metaTable = "migrations"
如果您通过 useLocks
配置使用锁表,锁表也将与您的演进元数据表同名,并带有 _lock
后缀(migrations_lock
而不是 play_evolutions_lock
)。有关更多信息,请参阅 演进 文档。
如果您打算在现有的 Play 应用程序中使用此功能,请在配置此功能之前手动重命名元表。
§允许具有空主体或空文件名的文件上传
现在可以设置
play.http.parser.allowEmptyFile = true
以允许空 multipart/form-data
文件上传,无论文件名或文件本身是否为空。默认情况下,此配置设置为 false
。
§包含额外错误信息的请求属性
在错误处理程序中,您现在可以访问“http 错误信息”请求属性(如果可用)。此属性包含对错误处理有用的补充信息。目前,您可以获取有关错误处理程序最初被调用位置的详细信息
- Java
-
request.attrs.getOptional(play.http.HttpErrorHandler.Attrs.HTTP_ERROR_INFO).map(info => info.origin()).orElse("<unknown error origin>")
- Scala
-
request.attrs.get(play.api.http.HttpErrorHandler.Attrs.HttpErrorInfo).map(_.origin).getOrElse("<unknown error origin>")
目前,Play 2.9 根据错误处理程序的来源提供以下值
csrf-filter
- 错误处理程序在 CSRF 过滤器代码中被调用。csp-filter
- 错误处理程序在 CSP 过滤器代码中被调用。allowed-hosts-filter
- 错误处理程序在允许的主机过滤器代码中被调用。server-backend
- 处理程序在 Netty 或 Akka HTTP 服务器后端中被调用。
第三方模块可能会引入自己的来源。此外,未来的 Play 版本可能会包含更多与错误相关的信息。
§CORS 过滤器支持 *
通配符
CORS 过滤器的 allowedOrigins
配置现在接受通配符 *
,它具有特殊含义。如果请求来源与列表中的任何其他来源不匹配,则将发送 Access-Control-Allow-Origin: *
play.filters.cors.allowedOrigins = ["*"]
有关更多详细信息,请参阅 CORS 过滤器文档。
§新的 IP 过滤器
引入了一个新的过滤器,通过将 IP 地址列入黑名单或白名单来限制访问。有关详细信息,请参阅 IP 过滤器页面。
§Play 配置项目作为独立库
Play 的 play.api.Configuration
类,它包装了 Typesafe Config,现在可以作为独立库使用。我们的目标是保持其占用空间最小。除了 Typesafe Config 之外,它只依赖于 slf4j-api
进行日志记录和 Play 的 play-exceptions
项目,其中包含 Play 本身和 Play SBT 插件所需的两个异常类。
要使用该库,请将其添加到任何 Scala 项目中,将其包含在您的 build.sbt
中
libraryDependencies += "com.typesafe.play" %% "play-configuration" % "<PLAY_VERSION>"
§添加 UUID PathBindableExtractor
路由 DSL 现在包含开箱即用的绑定 UUID 的功能。
§新的服务器后端配置键
- 配置键
play.server.akka.terminationTimeout
已扩展到 Netty 后端,并因此重命名为play.server.terminationTimeout
。 - 引入了一个新的配置键
play.server.waitBeforeTermination
,提供了一种解决Akka HTTP 问题 #3209的方法。此键也可以用于 Netty 后端。 - 对于 Netty 后端,添加了一个新的配置键
play.server.netty.shutdownQuietPeriod
,用于调整 Netty 的静默期。
要全面了解这些新配置的功能,请参阅Akka HTTP 和 Netty 服务器后端配置页面,以及有关如何“优雅地关闭服务器”的文档。
§增强的构建基础设施
另外,我们想通知您,我们已将 GitHub Play Framework 组织下的所有存储库从 Travis CI 迁移到 GitHub Actions。根据我们的经验,GitHub Actions 证明更可靠、速度更快,并且由于与 GitHub 的无缝集成,更易于维护。我们感谢Sergey Morgunov为促进此迁移所做的出色工作。他投入了大量时间来创建出色的可重用 GitHub 工作流。
由于sbt-ci-release,我们简化了发布新版本的流程。现在,我们只需将 git 标签推送到 GitHub 即可生成新版本。这消除了在开发人员机器上本地发布工件时可能出现的错误,这种情况在过去经常发生。
切换到助手,这在 Scala 开发人员社区中现在很常见,这更帮助我们实现新版本库的无缝快速发布。尽管这些工具广为人知,但我们想借此机会承认它们的重要性。我们衷心感谢Scala Steward 和 Release Drafter 等工具的创建者和维护者,感谢他们的杰出贡献。他们的努力在使我们能够继续交付 Play 方面发挥着至关重要的作用。
§Play 2.10 / Play 3.1 的计划
我们想向您提供有关我们计划在 Play 2.10 / Play 3.1 中包含的内容的初步概述,以便您开始考虑这些更改。
- 迁移到 Guice 7:拥抱 Jakarta 并停止使用
javax.inject
命名空间。 - 删除 Play 应用程序全局状态:我们旨在一劳永逸地消除 Play 应用程序全局状态。
- 移除 Java 11 支持:作为我们演进的一部分,Java 11 支持将逐步淘汰。
- 移除已弃用的 API:与往常一样,我们将移除标记为已弃用的方法和类。
- 升级到 JUnit 5:使用最新的测试框架。
- 升级到 Ehcache 3.x: (虽然我们推荐使用 Caffeine)以提高缓存功能。
- 升级到更新的 Jackson 版本:增强 JSON 处理功能。
- 为入职贡献者提供更好的文档:改进资源以帮助新贡献者了解 Play 构建设置。
- 基础设施增强:我们的发布流程与 Play 2.8 相比已经有了很大的进步,但完全自动化仍然是一个目标。我们还在考虑将我们的文档和 Play 网站迁移到 GitHub Pages。此更改将允许与 Play 版本一起自动发布,从而无需专门的 Web 服务器。我们的中期目标是最大限度地实现自动化并减少对第三方服务和外部托管的依赖,GitHub 将成为中心枢纽。简化维护人员的维护和发布流程是这项工作的关键目标。
当然,此列表并不详尽。您可以通过我们的 GitHub 路线图 和 Play 2.10 里程碑 跟踪我们的计划。
下一步:迁移指南
发现此文档中的错误?此页面的源代码可以在 此处 找到。阅读完 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?转到 我们的社区论坛 与社区开始对话。