§Play 2.5 中的新功能
本页重点介绍了 Play 2.5 的新功能。如果您想了解迁移到 Play 2.5 所需的更改,请查看 Play 2.5 迁移指南。
§基于 Akka Streams 的新流式 API
Play 2.5 的主要主题是从 Play 的基于迭代器的异步 IO API 迁移到 Akka Streams。
从本质上讲,无论何时您通过网络进行通信,或者将某些数据写入/读取到文件系统,都涉及一些流式处理。在许多情况下,这种流式处理是在低级别完成的,框架将物化的值暴露给您的应用程序,作为内存中的消息。对于许多 Play 操作来说,情况就是这样,一个主体解析器将请求主体流转换为一个对象,例如一个解析后的 JSON 对象,应用程序会使用该对象,返回的结果主体是一个 JSON 对象,Play 然后将其转换回流。
传统上,在 JVM 上,流式处理是使用阻塞的 InputStream
和 OutputStream
API 完成的。这些 API 需要一个专用线程来使用它们 - 读取时,该线程必须阻塞并等待数据,写入时,该线程必须阻塞并等待数据被刷新。像 Play 这样的异步框架提供了许多优势,因为它通过不使用诸如此类的阻塞 API 来限制其所需的资源。相反,对于流式处理,需要使用异步 API,其中框架会收到有关要读取的数据或已写入数据的通知,而不是让线程阻塞并等待它。
在 Play 2.5 之前,Play 使用 Iteratee 作为这种异步流式处理机制,但现在它使用 Akka Streams。
§为什么不使用 Iteratee?
Iteratee 是一种处理异步流式处理的功能方法。它们非常强大,同时还提供了一个非常小的 API 表面积 - Iteratee API 包含一个方法,fold
,其余的只是在此方法之上构建的帮助程序。Iteratee 还提供了非常高的安全性,只要您的代码编译,您不太可能遇到与 Iteratee 本身实现相关的任何错误,例如并发或错误处理,大多数错误都将在 Iteratee 的“业务”逻辑中。
虽然这种安全性与简易性很棒,但其后果是它具有非常陡峭的学习曲线。使用迭代器进行编程需要从传统的 IO 处理方式转变思维,许多开发人员发现,为实现这种转变所需的投入对于他们的 IO 需求来说过高。迭代器的另一个缺点是它们实际上无法在 Java 中实现,因为它们依赖于许多高级函数式编程特性。
§为什么选择 Akka Streams
Akka Streams 在安全性、简易性和熟悉性之间取得了良好的平衡。Akka Streams 有意地限制了你所能做的事情,以便你只能正确地做事,但不像迭代器那样限制。从概念上讲,它们对大多数开发人员来说更加熟悉,提供了功能性和命令式两种方式来处理它们。Akka Streams 还具有一个一流的 Java API,可以轻松地实现 Java 中所需的任何流式需求。
§Akka Streams 在哪里使用?
在 Play 应用程序中,你会遇到 Akka Streams 的地方包括
- 过滤器
- 流式响应体
- 请求体解析器
- WebSockets
- 流式 WS 客户端响应
§响应式流
响应式流 是一个用于异步流的新规范,计划将其包含在 JDK9 中,并作为独立库提供给 JDK6 及更高版本。一般来说,它不是一个最终用户库,而是一个 SPI,流式库可以实现它以相互集成。Akka Streams 和迭代器都提供了响应式流 SPI 实现。这意味着,现有的迭代器代码可以轻松地与 Play 的新 Akka Streams 支持一起使用。这也意味着 Play 中可以使用任何其他响应式流实现。
§迭代器的未来
迭代器在某些用例中仍然具有优势。目前,没有计划在 Play 中弃用或删除它们,尽管它们可能会被移到一个独立的库中。由于迭代器提供了响应式流实现,因此它们始终可以在 Play 中使用。
§更好地控制 WebSocket 帧
Play 2.5 WebSocket API 使你可以直接控制 WebSocket 帧。你现在可以发送和接收二进制、文本、ping、pong 和关闭帧。如果你不想担心这种级别的细节,Play 仍然会自动将你的 JSON 或 XML 数据转换为正确的帧类型。
§新的 Java API
Play 2.5 的 Java API 提供了与 Scala API 相同的功能。为此,我们引入了几个新的 Java API。
HttpRequestHandler
,它允许在请求发送到路由器之前拦截传入的请求。EssentialAction
,一种低级操作,用于EssentialFilter
和HttpRequestHandler
。EssentialFilter
/Filter
用于在 Java 中编写过滤器。BodyParser
,它允许在 Java 中编写自定义的正文解析器。
§Java API 更新为使用 Java 8 类
Play 2.0 于 2012 年发布时,Java 对 Play 的异步函数式编程风格支持很少。当时没有 lambda 表达式,future 只有阻塞接口,而且常见的函数式类也不存在。Play 提供了自己的类来填补空白。
随着 Play 2.5 的发布,这种情况发生了变化。Java 8 现在提供了对 Play 的编程风格更好的支持。在 Play 2.5 中,Java API 已经过改进,可以使用标准的 Java 8 类。这意味着 Play 应用程序将更好地与其他 Java 库集成,并且看起来更像惯用的 Java。
以下是主要变化:
- 使用 Java 函数式接口 (
Runnable
、Consumer
、Predicate
等)。(参见迁移指南。) - 使用 Java 8 的
Optional
而不是 Play 的F.Option
。(参见迁移指南。) - 使用 Java 8 的
CompletionStage
而不是 Play 的F.Promise
。(参见迁移指南。)
§支持其他日志框架
许多用户希望使用自己选择的日志框架,但直到 Play 2.5 之前,这是不可能的。现在,Play 对 Logback 的固定依赖关系已移除,Play 应用程序现在可以使用任何 SLF4J 兼容的日志框架。Logback 默认包含在内,但您可以通过在 build.sbt
文件中包含一个设置来禁用它,并将其替换为您自己的框架。有关在 Play 中使用其他日志框架的更多信息,请参见 Play 的 有关日志记录的文档。
Play 应用程序需要对其配置进行一些小的更改,因为 Play 的 Logback 类之一已移至单独的包中,作为更改的一部分。有关更多详细信息,请参见 迁移指南。
§记录 SQL 语句
Play 现在提供了一种简单的方法来记录 SQL 语句,它基于 jdbcdslog,适用于所有 JDBC 数据库、连接池实现和持久性框架(Anorm、Ebean、JPA、Slick 等)。当您启用日志记录时,您将看到发送到数据库的每个 SQL 语句,以及有关语句运行时间的信息。
有关如何使用 SQL 日志记录的更多信息,请参见 Play 的 Java 和 Scala 数据库文档。
§Netty 原生套接字传输
如果您在 Linux 上运行 Play 服务器,现在可以通过使用 Netty 4.0 中引入的 原生套接字功能 来获得性能提升。
您可以在 Play 文档的 配置 Netty 部分了解如何使用原生套接字。
§性能改进
由于各种性能优化,Play 2.5 的性能测试框架显示每秒大约 60K 个请求,比 Play 2.4.x 提高了近 20%。
§WS 改进
Play WS 已升级到 AsyncHttpClient 2.0,现在包含一个请求管道过滤器(Scala,Java),可用于以 cURL 格式 记录请求。
下一步:迁移指南
发现此文档中的错误?此页面的源代码可以在 此处 找到。在阅读 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?前往 我们的社区论坛 与社区进行交流。