WebSockets[翻译]

原文:WebSockets

WebSockets

WebSockets是一个可以被基于允许双向全双工通信协议的Web浏览器使用的套接字。只要在服务端和客户端之间有一个活跃的WebSocket 连接, 客户端可以发送信息,服务端可以在任何时候收到信息。

新的兼容HTML5的浏览器本身通过JavaScript WebSocket API 支持WebSockets 。然而WebSockets 不仅仅局限于被WebBrowsers使用,有很多的WebSocket客户端库可以用,例如允许服务端彼此通信,也允许本地的移动应用可以使用WebSockets。在这些环境中使用WebSockets 有可以复用Play服务端已使用的TCP端口的好处。

提示:查看caniuse.com了解更多关于浏览器支持WebSockets的已知问题和更多信息。

处理WebSockets

到目前为止,我们使用Action实例处理标准的HTTP 请求,并发送回标准的HTTP应答。而WebSockets 是完全不同的东西,并不能通过标准的Action处理。

Play提供了两个不同的内置机制来处理WebSo


继续阅读»»»

Comet[翻译]

原文:Comet

使用Comet的块应答

块应答的一个常见的用法是创建Comet套接字。

Comet套接字是仅包含<script>元素的 text/html应答块。对于每一个块,我们写一个<script> 标签,这个标签包含了通过Web浏览器立即执行的JavaScript 。这样我们就可以实时的把事件从服务器发送到Web浏览器:对每一个消息,把它封装进调用JavaScript 回调函数的<script>标签,并把它写进块应答。

由于 Ok.chunked 利用 Akka Streams获取Flow[ByteString],因此我们可以发送Flow元素并转换它,如此每一个元素会被转义并封装到JavaScript方法中。Comet助手自动完成Comet套接字,根据浏览器的兼容性推送初始的空白缓存,并支持字符串和JSON消息。

Comet Imports

为了使用Comet 助手,导入下面的类:

import akka.stream.Materializer  
import akka.stream.scaladsl.Source  
imp

继续阅读»»»

Handling asynchronous results【翻译】

原文:Handling asynchronous results

让控制器变成异步的

本质上,Play Framework从里到外都是异步的。Play以异步,非阻塞方式处理每一个请求。

默认配置已经为异步控制器做了优化。也就是说,在控制器中,应用代码应该避免阻塞,例如,让控制器代码等待一个操作。这种常见的阻塞操作的例子有JDBC调用,流式API,HTTP请求和长时间的计算。

尽管在默认的执上下文中可以增加线程的数量,让更多并发请求处在阻塞中的控制器执行,但是按照保持控制器异步的推荐方法,可以让线程数据更容易调整并在负载下保证系统的响应。

创建非阻塞Action

由于Play的工作方式,Action代码执行必须尽可能的快,例如,非阻塞。因此,如果我们还不能生产结果,那么我们应该返回什么作为结果呢?答案是一个future 结果!

Future[Result]最终将被用 Result类型的值回填。通过给定的 Future[Result] 代替正常的结果,我可以很快的生成结果而不阻塞。一旦执行完成,Play就会返回结果。

当等待应答时,网络客户端将被阻塞,但是在服务端没有什么会


继续阅读»»»

Session and Flash scopes【翻译】

在Play中的Session and Flash scopes有什么不同

如果你想跨多个HTTP请求存储数据,你需要把它们存储到Session或者Flash scopes中。在Session中的数据存储在整个用户Session周期可用,在Flash scope 存储的数据仅在下次请求时可用。

理解Session 和Flash数据不是存储在服务端而是使用Cookie机制添加到每一个随后的HTTP请求中这一点很重要。这意味着数据大小是非常有限的(最大4K),并且你只能存储String类型的值。Cookie的默认名是 PLAY_SESSION。这可以在应用的配置文件中修改Key

如果Cookie的名字被修改,可以使用在设置和清除Cookie中提到的方法清除之前的Cookie。

当然,由于Cookie值使用了秘钥签名因此客户端不能修改Cookie的数据(或者数据会无效)

Paly没有打算把 Session当缓存用。如果你需要缓存一些与特定Session相关的数据,你可以使用Play内置缓存机制,在用户Session存储一个唯一ID,让这些数据与特定的用户相关联。

默认


继续阅读»»»

Manipulating Results[翻译]

改变默认的Content-Type

结果的内容类型是自动地通过的指定的相应体的Scala值推断而来。

例如:

val textResult = Ok("Hello World!")  

将会自动的设置Content-Type头为text/plain,而:

将会设置 Content-Type 头为application/xml。

.提示:这是通过play.api.http.ContentTypeOf类型的类完成。

这是十分有用的,但是有时你想改变它,就只是在结果上使用as(newContentType)方法创建一个新的使用不同Content-Type头的类似的结果:

val htmlResult = Ok(<h1>Hello World!</h1>).as("text/html")  

或使用更好的方式:

val htmlResult2 = Ok(<h1>Hello World!</h1>).as(HTML)  

注意:使用HTML替代"text/html"的好处是字符集将会被自动的处理,并且实际的


继续阅读»»»

Handling errors【翻译】

原文:Handling errors

处理错误

HTTP应用可以返回两类主要的错误类型——客户端错误和服务端错误。客户端错误是指连接的客户端触发了什么错误,服务端错误是指有什么错误发生在服务端。

在许多情况下Play会自动的发现客户端错误——这些错误包括如错误的报头值,不支持的内容类型,请求找不到的资源。在多数情况下,Play也会自动的处理服务端错误——如果你的Action代码抛出异常。Play将会捕捉这个并生成一个服务端错误网页发送给客户端。

Play处理这些错误的接口是 HttpErrorHandler。它定义了两个方法,onClientError, 和 onServerError.

增加自定义的错误处理

自定义的错误处理可以通过在根包下创建一个叫做ErrorHandler的类实现,这个类实现了 HttpErrorHandler,例如:

import play.api.http.HttpErrorHandler  
import play.api.mvc._  
import play.api.mvc.Results._  
import scala.concurre

继续阅读»»»

Content negotiation

原文:Content negotiation

内容协商是一个让相同资源(URI)的不同表现成为可能的机制。它是有用的,如,为了写一个支持多种输出格式(XML, JSON, 等等)的Web Services。本质上,服务端驱动的协商是使用了 Accept* 请求的头执行。你可以在HTTP规范中找到更多关于内容协商的信息。

语言

Play在方法play.api.mvc.Controller#lang中使用它,这个方法提供一个隐式的 play.api.i18n.Lang 值给你的Action,因此他们自动的使用了最佳的语言(如果你的应用支持,否则你的应用的默认语言会被使用)。

内容

实际上,Accept 头没有真的包含MIME 类型而是媒体范围(例如,请求接受所有的文本结果会设置为 text/* 范围,而/ 范围意味着所有的结果类型都接受)。Controllers 提供一个较高水平的render 方法来帮助你处理媒体范围。例如考虑下面的Action定义:

val list = Action { implicit request =>  
val items = Item

继续阅读»»»

Action composition【翻译】

原文:Action composition

这章将介绍几种定义常用Action函数的方式。

自定义Action构建器

我们在前面看到过,有几种声明Action的方式——使用Request参数,不使用request参数,使用Body解析器等等。事实上,正如我们将在异步编程章节看到的. 还有更多的方式。

实际上,这些构建Action的方法都是通过一个叫 ActionBuilder 的特质定义的,并且我们用来声明我的Action的Action对象只是这个特质的实例。通过实现你自己的ActionBuilder, 你可以声明一个可被重复使用的Action栈,然后这可以被用来构建Action。

让我们从一个简单的日志装饰的例子开始,我想记录每次对这个Action的调用。第一种方式是在invokeBlock 方法中实现这个功能,这个方法通过ActionBuilder构建每个Action时调用:

import play.api.mvc._

object LoggingAction extends ActionBuilder[Request] {  
def invokeBlock[A](

继续阅读»»»

HTTP routing[翻译]

原文:HTTP routing

内置HTTP路由器

路由器的职责是负责转换每一个进入的HTTP请求给Action

一个HTTP请求可以被看做是由MVC框架的事件。这个事件包含两个主要的信息:

  • 请求路径(e.g. /clients/1542,/photos/list), 包含查询字符串
  • HTTP 方法 (e.g.GET,POST, …).

路由是在可被编译的conf/routes文件中被定义的。这意味着你可以在你的浏览器中直接看到路由的错误信息

依赖注入

Play支持生成两种路由器的类型,一个是依赖注入路由器,另一个是静态路由。默认的是依赖注入路由器,这也是在Play种子Activator模板中的样例,因此我们推荐你使用依赖注入Contrlller。如果你需要使用静态Contrller,你可以通过在你的build.sbt配置文件里添加下面这样的配置来转换到静态路由生成器:

routesGenerator:= StaticRoutesGenerator  

在Play的文档中的代码样例假定你使用了依赖注入路由生成器。如果你没有使用这个,你可以容易的改写代码样例到静态


继续阅读»»»

Actions, Controllers and Results

原文:Actions, Controllers and Results

什么是Action?

一个Play应用接收的大多数请求都是通过Action处理的。

一个play.api.mvc.Action就是一个(play.api.mvc.Request =>play.api.mvc.Result)函数,这个函数处理请求并生成发送给客户端的结果。

def echo = Action { request =>  
Ok("Got request [" + request + "]")  
}

一个Action返回一个play.api.mvc.Result值,这个值代表HTTP发送给网络客户端的响应。在这个例子中Ok构建了一个含有text/plain响应体的200 OK的响应。

构建一个Action

play.api.mvc.Action伴生对象提供了几个比较有用的方法来构建Action值。

第一个最简单的方式仅用一个表达式块作为参数,返回结果:

Action {  
Ok("Hello world")  
}

这是创建Action的最简单的方式,但是我们不能


继续阅读»»»