Actions, Controllers 和 Results

什么是Action?

Play应用程序收到的大多数请求都是由Action来处理。

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

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

Action 返回一个play.api.mvc.Result 类型的值, 表示要发送到客户端的HTTP响应。在这个示例 Ok 构造一个 200 OK 响应,并包含一个 text/plain 类型的响应体。

构建一个Action

play.api.mvc.Action 的伴生对象提供一些助手方法来构造一个 Action 值。

首先最简单的一种是只带一个表达式块做为参数,并返回一个Result:

Action {
  Ok("Hello world")
}

这是创建Action最简单的方法, 但是我们不能获得对传入请求的引用。它对访问正在调用这个Action的HTTP请求常常是很有用的。

因此还有另外一种Action构建方法,是带有一个Request => Result 函数做为参数:

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

标记 request 参数为implicit 通常是有用的,这样其它API在需要时可以隐式使用它:

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

最后一种创建Action值的方式是指定一个额外的BodyParser 参数:

Action(parse.json) { implicit request =>
  Ok("Got request [" + request + "]")
}

这份手册到后面会讲到Body解析器。现在只需要知道这个创建Action值的方法使用了一个默认的 任意内容body解析器.

Controllers 是 action 生成器

一个Controller 只不过是一个生成Action值的单例对象。

定义一个action生成器的最简单用法,是定义一个无参方法,让其返回一个Action 值:

package controllers

import play.api.mvc._

class Application extends Controller {

  def index = Action {
    Ok("It works!")
  }

}

当然, action 生成器方法可以有参数, 而且这些参数可以在Action 闭包中捕获:

def hello(name: String) = Action {
  Ok("Hello " + name)
}

简单 results

目前为止我们只是对简单的results感兴趣: 一个HTTP result与一个状态码, 一组HTTP标头和一个发送到web客户端的body。

results由play.api.mvc.Result 定义:

def index = Action {
  Result(
    header = ResponseHeader(200, Map(CONTENT_TYPE -> "text/plain")),
    body = Enumerator("Hello world!".getBytes())
  )
}

当然这里有几个助手方法可用于创建常见的results,如Ok result,和上面的例子一样:

def index = Action {
  Ok("Hello world!")
}

这将产生与刚才上面那段代码完全相同的结果。

这里有几个示例,用来创建各种results:

val ok = Ok("Hello world!")
val notFound = NotFound
val pageNotFound = NotFound(<h1>Page not found</h1>)
val badRequest = BadRequest(views.html.form(formWithErrors))
val oops = InternalServerError("Oops")
val anyStatus = Status(488)("Strange response type")

所有这些助手方法都可以在play.api.mvc.Results 特质和它的伴生对象中找到。

重定向也是一种简单results

重定向浏览器到一个新的URL只是另外一种类型的简单result。可是, 这些result类型不带响应体。

有几个助手方法可用于创建重定向results:

def index = Action {
  Redirect("/user/home")
}

默认是使用一个303 SEE_OTHER 响应类型, 但如果你需要,也可以设定更多特定的状态码:

def index = Action {
  Redirect("/user/home", MOVED_PERMANENTLY)
}

TODO dummy页面

你可以使用一个空Action 实现定义为TODO: 它的result是一个标准的‘Not implemented yet’ 结果页面:

def index(name:String) = TODO