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的最简单的方式,但是我们不能


继续阅读»»»

用分层结构打造苗条MVC框架

原文请访问:Maintain Slim PHP MVC Frameworks with a Layered Structure

基于诸如Yii和Laravel这样MVC框架的一个必然问题就是:臃肿的controller(控制器)和臃肿的model(模型)。而使控制器和模型变得臃肿的主要东西就是这些框架中强大而又必要的组件 -- Active Record。

问题:违反了单一职责原则的Active Record

Active Record是一个架构模式,一种访问数据库中数据的方式。由Martin Fowler在他2003年的《企业应用框架模式》一书命名并广泛应用在PHP框架中。

尽管它一是个非常必要的方式,然而Active Record(AR)模式违反了单一职责原则(SRP),因为AR模型:

  • 处理了数据查询与数据存储。
  • (通过关系)知道了系统中太多其他的模型。
  • 经常在应用的业务逻辑中直接调用(因为数据存储的实现与业务逻辑的表达密切相关)。

当需要尽快创建一个应用原型时,违反SRP对于快速开发来说是一桩好的交易,但当应用成长为一个中等或者大型项目时,


继续阅读»»»

合成监控(SyntheticMonitoring)

/**
 * 献给我最尊敬的偶像Martin Fowler
 * 原文出处:https://martinfowler.com/bliki/SyntheticMonitoring.html
 * @author dogstar.huang <chanzonghuang@gmail.com> 2017-03-26
 */

本翻译已征得Martin Fowler同意,并链接在博客原文下方。

合成监控(也称为语义监控 [1])会定期对线上生产系统执行应用程序中自动化测试的一个子集。其结果会推送到监控服务,如果失败则触发警告。这项技术结合了自动化测试和监控以便能检测生产环境中失败的业务需求。

在小型独立服务和频繁部署的时代,很难用与后面会出现在生产环境上完全相同的版本组合来测试预生产环境。缓解这个问题的一个途径是将可测试性从预生产环境扩展到生产环境 -- 即生产环境上的QA背后的想法。这样做,可把思维模式从关注平均故障时长(MTBF)切换到关注平均修复时间(MTTR)。

对于大部分F的类型,平均修复时间 > 平均故障时长。 -- John Allspaw


继续阅读»»»