文件

§為範本引擎新增對自訂格式的支援

內建範本引擎支援常見的範本格式 (HTML、XML 等),但您可以在需要時輕鬆新增對自訂格式的支援。此頁面摘要了支援自訂格式的步驟。

§範本處理程序概觀

範本引擎透過附加範本的靜態和動態內容部分來建構其結果。例如,考量下列範本

foo @bar baz

它包含兩個靜態部分(foo  baz)和一個動態部分(bar)。範本引擎將這些部分串接在一起以建構其結果。實際上,為了防止跨網站指令碼攻擊,bar 的值可以在串接到結果的其餘部分之前進行跳脫。此跳脫程序特定於每種格式:例如,在 HTML 的情況下,您希望將 “<” 轉換為 “&lt;”。

範本引擎如何知道哪種格式對應於範本檔案?它會查看其副檔名:例如,如果其副檔名為 .scala.html,它會將 HTML 格式與該檔案關聯。

最後,您通常希望您的範本檔案用作 HTTP 回應的主體,因此您必須定義如何從範本呈現結果建立 Play 結果。

總之,若要支援您自己的範本格式,您需要執行下列步驟

§實作格式

實作 play.twirl.api.Format[A] 特質,它具有方法 raw(text: String): Aescape(text: String): A,分別用於整合靜態和動態範本部分。

格式的類型參數 A 定義範本呈現的結果類型,例如 HTML 範本的 Html。此類型必須是 play.twirl.api.Appendable[A] 特質的子類型,該特質定義如何將部分串接在一起。

為方便起見,Play 提供一個 play.twirl.api.BufferedContent[A] 抽象類別,它使用 StringBuilder 來建構其結果,並實作 play.twirl.api.Appendable[A],且實作 play.twirl.api.Content 特質,因此 Play 知道如何將其序列化為 HTTP 回應主體(有關詳細資訊,請參閱此頁面的最後一節)。

簡而言之,您需要寫入類別:一個定義結果(實作 play.twirl.api.Appendable[A])和一個定義文字整合程序(實作 play.twirl.api.Format[A])。例如,以下是 HTML 格式的定義方式

// The `Html` result type. We extend `BufferedContent[Html]` rather than just `Appendable[Html]` so
// Play knows how to make an HTTP result from a `Html` value
class Html(buffer: StringBuilder) extends BufferedContent[Html](buffer) {
  val contentType = MimeTypes.HTML
}

object HtmlFormat extends Format[Html] {
  def raw(text: String): Html = …
  def escape(text: String): Html = …
}

§將檔案副檔名與格式關聯

範本會在編譯整個應用程式來源之前由建置程序編譯成 .scala 檔案。TwirlKeys.templateFormats 鍵是 Map[String, String] 類型的 sbt 設定,定義檔案副檔名與範本格式之間的對應。例如,如果 HTML 沒有由 Play 內建支援,您必須在建置檔案中撰寫以下內容,將 .scala.html 檔案與 play.twirl.api.HtmlFormat 格式關聯

TwirlKeys.templateFormats += ("html" -> "my.HtmlFormat.instance")

請注意,箭頭右邊包含 play.twirl.api.Format[_] 類型值的完整限定名稱。

§告訴 Play 如何從範本結果類型產生 HTTP 結果

對於任何存在隱式 play.api.http.Writeable[A] 值的 A 類型值,Play 都可以撰寫 HTTP 回應主體。因此,您只需要為範本結果類型定義此類值即可。例如,以下是為 HTTP 定義此類值的方式

implicit def writableHttp(implicit codec: Codec): Writeable[Http] =
  Writeable[Http](result => codec.encode(result.body), Some(ContentTypes.HTTP))

注意:如果您的範本結果類型延伸 play.twirl.api.BufferedContent,您只需要定義
隱式 play.api.http.ContentTypeOf

implicit def contentTypeHttp(implicit codec: Codec): ContentTypeOf[Http] =
  ContentTypeOf[Http](Some(ContentTypes.HTTP))

下一步:表單提交和驗證


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