JSON with HTTP

原文

Play通过HTTP API与JSON库共同支持内容类型为JSON的HTTP请求和应答。

关于 Controllers, Actions, 和routing的详细资料看HTTP Programming

我们将通过设计一个简单的RESTful Web服务来解释必要的概念,这个服务可以GET 到实体集合,并接收POSTs 创建新的实体。并且这个服务将对所有的数据使用JSON类型。

这是我们在我们的服务中将使用的模型:

case class Location(lat: Double, long: Double)

case class Place(name: String, location: Location)

object Place {  
var list: List[Place] = {  
List(  
Place(  
"Sandleford",
Location(51.377797, -1.318965)  
),
Place(  
"Watership Down",
Location(51.235685, -1.309197)  
)
)
}

继续阅读»»»

JSON basics[翻译]

现代的Web应用经常需要解析并生成JSON格式的数据 (JavaScript 对象符号)。Play通过它的JSON library支持这个功能。

JOSN是一个轻量级的数据交换格式,像下面这样:

{
"name" : "Watership Down",
"location" : {
"lat" : 51.235685,
"long" : -1.309197
},
"residents" : [ {
"name" : "Fiver",
"age" : 4,
"role" : null
}, {
"name" : "Bigwig",
"age" : 6,
"role" : "Owsla"
} ]
}

想学习更多关于JSON的知识,详见json.org.

Play的JSON库

play.api.libs.json 包包含了为展示JSON数据的数据结构及这些数据结构和其他数据展现实现之间的实用工具。这个包的一些功能是:

  • 使用最小样板自动转换为Case类和从Case类转换为JSON。如果你想用最小的代码快速的起步和运行,这可能是个开始的地方
  • 解析时自定义验证。
  • 在请求Bo

继续阅读»»»

Body parsers[翻译]

什么是Body解析器?

一个HTTP请求是一个HTTP头后面跟着Body,这个头通常比较小——它可以安全的缓存在内存中,因此在Play中使用RequestHeader 类模仿头。而Body有可能很长,因此不能在内存中缓存,而是使用一个流来模仿。

但是,许多请求Body的有效负载比较小,可以缓存到内存中,因此在缓存中映射Body流到一个对象,Play提供了一个 BodyParser 抽象。

由于Paly是一个异步框架,因此传统的 InputStream不能被用来读Body请求——当你调用read时,输入流会被阻塞掉,线程要调用它就必须等到数据可用时。作为替代,Play使用了一个叫做 Akka Streams的异步流库。

Akka Streams是 Reactive Streams的实现,Reactive Streams是一个允许许多异步流API无缝地一起工作的SPI,因此尽管一般的基于基础技术的 InputStream不合适在Play中使用,但是Akka Streams和Reactive Streams相关的整个异步库生态系统将提供给你任何你想要的。

更多关于Actions


继续阅读»»»

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,让这些数据与特定的用户相关联。

默认


继续阅读»»»

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

继续阅读»»»