文件

§動作、控制器和結果

§什麼是動作?

Play 應用程式收到的請求大多數是由 Action 處理。

play.api.mvc.Action 基本上是一個 (play.api.mvc.Request => play.api.mvc.Result) 函式,用於處理請求並產生要傳送給客戶端的結果。

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

動作會傳回一個 play.api.mvc.Result 值,代表要傳送給網路用戶端的 HTTP 回應。在此範例中,Ok 會建構一個包含 text/plain 回應主體的 200 OK 回應。

§建立動作

在任何延伸 BaseController 的控制器中,Action 值是預設動作建構器。此動作建構器包含多個用於建立 Action 的輔助程式。

第一個最簡單的只將傳回 Result 的表示式區塊當作引數。

Action {
  Ok("Hello world")
}

這是建立動作最簡單的方式,但我們無法取得對應的要求參考。通常存取呼叫此動作的 HTTP 要求會很有用。

因此,還有另一個動作建構器,它將函式 Request => Result 當作引數。

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

通常將 request 參數標示為 implicit 會很有用,這樣其他需要它的 API 就能隱含地使用它。

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

如果已將程式碼區分成方法,就能從動作傳遞隱含的要求。

def action: Action[AnyContent] = Action { implicit request =>
  anotherMethod("Some para value")
  Ok("Got request [" + request + "]")
}

def anotherMethod(p: String)(implicit request: Request[_]) = {
  // do something that needs access to the request
}

建立動作值的最後一種方式是指定額外的 BodyParser 引數。

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

本文稍後將介紹主體剖析器。目前你只需要知道建立動作值的另一種方法會使用預設的 任何內容主體剖析器

§控制器是動作產生器

Play 中的控制器只不過是一個產生 Action 值的物件。控制器通常定義為類別,以利用 相依性注入

注意:請記住,在 Play 的未來版本中,將不支援將控制器定義為物件。建議使用類別。

定義動作產生器的最簡單使用案例是沒有參數並傳回 Action 值的方法。

package controllers

  import javax.inject.Inject

  import play.api.mvc._

  class Application @Inject() (cc: ControllerComponents) extends AbstractController(cc) {
    def index = Action {
      Ok("It works!")
    }
  }

當然,動作產生器方法可以有參數,而且這些參數可以由 Action 閉包擷取。

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

§簡單結果

目前我們只對簡單的結果感興趣:具有狀態碼、一組 HTTP 標頭和要傳送給網路客戶端主體的 HTTP 結果。

這些結果由 play.api.mvc.Result 定義

import play.api.http.HttpEntity

def index = Action {
  Result(
    header = ResponseHeader(200, Map.empty),
    body = HttpEntity.Strict(ByteString("Hello world!"), Some("text/plain"))
  )
}

當然,有幾個可用的輔助程式可以建立常見的結果,例如上面範例中的 Ok 結果

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

這會產生與之前完全相同的結果。

以下是建立各種結果的幾個範例

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 特質和伴隨物件中找到。

§重新導向也是簡單結果

將瀏覽器重新導向到新的 URL 只是另一種簡單的結果。但是,這些結果類型不採用回應主體。

有幾個可用的輔助程式可以建立重新導向結果

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

預設使用 303 SEE_OTHER 回應類型,但您也可以設定更具體的狀態碼(如果您需要的話)

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

§TODO 虛擬頁面

您可以使用定義為 TODO 的空 Action 實作:結果是標準的「尚未實作」結果頁面

def index(name: String) = TODO

下一步:HTTP 路由


在這個文件中發現錯誤?此頁面的原始程式碼可以在 這裡 找到。在閱讀 文件指南 後,請隨時提交拉取請求。有問題或建議要分享嗎?請前往 我們的社群論壇 與社群展開對話。