文件

§Play 2.8 遷移指南

本指南適用於從 Play 2.7 遷移至 Play 2.8。請參閱 Play 2.7 遷移指南 以從 Play 2.6 升級。建議一併閱讀 Akka 2.5 至 2.6 遷移指南,因為其中的多項變更會影響 Play 2.8。

§如何遷移

在啟動 sbt 之前,請務必進行以下升級。

§Play 更新

project/plugins.sbt 中更新 Play 版本號碼

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.x")

其中 2.8.x 中的「x」是你想要使用的 Play 次要版本,例如 2.8.0

§sbt 升級

雖然 Play 2.8 仍支援 sbt 0.13,但我們建議你使用 sbt 1。這個新版本獲得支援且積極維護。若要更新,請變更你的 project/build.properties,使其讀取

sbt.version=1.3.10

撰寫本文時,1.3.10 是 sbt 1.x 系列中的最新版本,你可能也能使用較新的版本。查看 Play 次要版本的 發行說明 和 sbt 的 發行說明 以取得詳細資訊。

§API 變更

Play 2.8 包含多項 API 變更。和往常一樣,我們遵循在移除現有 API 之前將其標示為不建議使用的政策。本節說明這些變更。

§SSLEngineProvider 使 SSLContext 可見

設定 HTTPS 時,如果你需要完整設定 SSL 憑證,可以覆寫 play.server.SSLEngineProvider。在 Play 2.8.0 之前,提供者只會使 SSLEngine 可見。現在,為了與第三方程式庫更好地整合,SSLContext 也必須可見。請參閱 ConfiguringHttps 頁面以取得更多詳細資訊。

§Scala 2.11 支援已終止

Play 2.8 支援 Scala 2.12 和 2.13,但不支援已達使用期限的 Scala 2.11。

§在專案中設定 scalaVersion

Scala 和 Java 使用者都必須設定 sbt 以使用 Scala 2.12 或 2.13。即使專案中沒有 Scala 程式碼,Play 本身也會使用 Scala,且必須設定為使用正確的 Scala 函式庫。

若要在 sbt 中設定 Scala 版本,只需設定 scalaVersion 鍵,例如

scalaVersion := "2.13.13"

如果您有一個單一專案建置,則此設定可以單獨放置在 build.sbt 中。但是,如果您有多專案建置,則必須在每個專案中設定 Scala 版本設定。通常,在多專案建置中,您會有一些每個專案共用的設定,這是放置設定的最佳位置,例如

def commonSettings = Seq(
  scalaVersion := "2.13.13"
)

val projectA = (project in file("projectA"))
  .enablePlugins(PlayJava)
  .settings(commonSettings)

val projectB = (project in file("projectB"))
  .enablePlugins(PlayJava)
  .settings(commonSettings)

§檔案提供方法已變更其 filename 參數的類型

提供檔案的方法,例如 Java API 中的 ok(File content, ...)(和類似方法)或 Java 的 StatusHeader 和 Scala 的 Status 類別中的 sendFilesendPathsendResource 已變更其 filename 參數的類型:Scala API 現在使用 Option[String] 作為其 filename 參數函式的回傳類型,而非使用純文字 String。Java API 已將參數類型變更為 Optional<String>
此 API 變更更能反映以下事實:如果您不希望 Content-Disposition 標頭包含檔案名稱,則可以傳遞 None / Optional.empty()

§Java API 的 Headers 類別是不可變的

類別 play.mvc.Http.Headers 現在是不可變的。某些方法已棄用,並已替換為新的方法

已棄用的方法 新方法
toMap() asMap()
addHeader(String name, String value) adding(String name, String value)
addHeader(String name, List<String> values) adding(String name, List<String> values)
remove(String name) removing(String name)

請注意,舊的已棄用方法會傳回原始已修改的 Headers 物件,而新方法總是會傳回新的物件,讓原始物件保持不變。

§已棄用的 API 已移除

許多在早期版本中已棄用的 API 已在 Play 2.8 中移除。如果您仍在使用它們,我們建議在升級到 Play 2.8 之前,先移轉到新的 API。請查看 Javadoc 和 Scaladoc 以取得移轉注意事項。另請參閱 Play 2.7 移轉指南 以取得更多資訊。

§Java API

在 Play 2.7 中,我們棄用 play.mvc.Http.Context,並建議直接使用 play.mvc.Http.RequestHeaderplay.mvc.Http.Request。我們現已移除 Http.Context,如果您的應用程式依賴於它,您應該閱讀 Play 2.7 移轉指南說明

§快取 API 變更

§組態變更

此區段列出組態中的變更和棄用事項。

§ObjectMapper 序列化變更

Play 2.8 採用 Akka Jackson 序列化支援,並使用 Akka 提供的預設值。其中一項變更為 Java Time 類型的呈現方式。在 Play 2.7 之前,它們會以時間戳記呈現,效能較佳,但現在改用 ISO-8601 (rfc3339) 格式 (yyyy-MM-dd'T'HH:mm:ss.SSSZ) 呈現。

如果您需要使用舊的時間戳記預設格式,請在 application.conf 中加入下列組態

akka.serialization.jackson.play.serialization-features {
  WRITE_DATES_AS_TIMESTAMPS = on
  WRITE_DURATIONS_AS_TIMESTAMPS = on
}

Play 提供的 ObjectMapper 執行個體(使用 Json#newDefaultMapper 或 Guice 管理的 play.core.ObjectMapperProvider)包含 Jackson 解序列化器對 JsonNode 的堆疊效率實作。如果您已使用自訂解序列化器將 json 酬載讀入 JsonNode,您有兩個選項

  1. 您可以使用設定從 ObjectMapper 中停用 Play 的 play.utils.JacksonJsonNodeModule
akka.serialization.jackson.play {
  jackson-modules = ${akka.serialization.jackson.jackson-modules}
  ##   Play's default settings concatenate "akka.serialization.jackson.jackson-modules" 
  ##      with "play.utils.JacksonJsonNodeModule" 
  ## jackson-modules = ${akka.serialization.jackson.jackson-modules} ["play.utils.JacksonJsonNodeModule"]
}
  1. 您可以進一步完全停用將 ObjectMapper 繫結至 Provider<ObjectMapper>play.core.ObjectMapperModule Guice 模組。接著,您必須建立自己的 com.example.ObjectMapperModule 並提供該繫結。
    the ObjectMapper to a Provider<ObjectMapper>. Then, you will have to create your
    own com.example.ObjectMapperModule and provide that binding.
play.modules.disabled += "play.core.ObjectMapperModule"
play.modules.enabled += "com.example.ObjectMapperModule"

§已移除 akka.actor.default-dispatcher.fork-join-executor 的覆寫

Play 在 akka.actor.default-dispatcher.fork-join-executor 中的覆寫已移除,改用 Akka 新且進步的預設值。

請參閱 Akka 遷移指南中與 預設派送變更 相關的區段,以取得更多詳細資料。

§IOSourceFileIO 在 Akka Streams 中的變更

與 Akka Streams 如何處理 FileIO.toPathStreamConverters.fromInputStreamStreamConverters.fromOutputStream 的錯誤相關的變更。請參閱 Akka 移轉指南中與 這些變更 相關的部分,以取得更多詳細資料。

§組態載入變更

在 Play 2.7 之前,當載入組態時,如果使用者提供一些屬性,Play 就不會考慮預設的 Java 系統屬性。現在,系統屬性總是會被考慮,這表示即使您也在定義自訂屬性,您也可以在 application.conf 檔案中參照它們。例如,當 嵌入 Play 時,就像底下的程式碼一樣,userProperties 和系統屬性都會被使用

import java.util.Properties

import play.api.mvc.Results
import play.core.server.AkkaHttpServer
import play.core.server.ServerConfig
import play.api.routing.sird._

class MyApp {
  def main(args: Array[String]): Unit = {
    // Define some user properties here
    val userProperties = new Properties()
    userProperties.setProperty("my.property", "some value")

    val serverConfig = ServerConfig(properties = userProperties)

    val server = AkkaHttpServer.fromRouterWithComponents(serverConfig) { components => {
      case GET(p"/hello") => components.defaultActionBuilder {
        Results.Ok
      }
    }}
  }
}

請記住,系統屬性會覆寫使用者定義的屬性。

§除錯 SSL 連線

在 Play 2.7 之前,Play 和 Play-WS 都使用 ssl-config 的版本,而該版本具有依賴於未記錄的內部 JSSE 除錯設定修改的除錯系統。這些通常會在啟動時使用 javax.net.debugjava.security.debug 系統屬性設定。

除錯系統已移除,而沒有在新系統中直接相關性的除錯旗標已棄用,而新的組態已記錄在 ssl-config 文件 中。

§I18n 行為變更

語言行為的比對現在符合 RFC 4647

§範例

conf/application.conf 檔案

play.i18n.langs = [ "fr", "fr-FR", "en", "en-US" ]

使用者的接受語言

en-GB
§之前

使用者的接受語言en-GB與任何設定檔不符。Play 應用程式回應法文頁面,與使用者的意願相違。

§之後

使用者的接受語言en-GBen相符。Play 應用程式回應英文頁面。

§概括的伺服器後端設定檔

Play 附帶兩個伺服器後端

到目前為止,我們將這些設定檔分開,即使有些設定套用於兩個後端,因此是完全的重複。
在 Play 2.8 中,我們開始概括此類重複的伺服器後端設定檔,並將它們直接移至play.server.*下方

§重新導向 HTTPS 篩選器的excludePaths設定檔已變更

現在,重新導向 HTTPS 篩選器play.filters.https.excludePaths設定檔包含路徑清單,而非 URI。這表示查詢參數不再重要。如果清單包含/foo,則要求/foo?abc=xyz現在也會被排除。在 Play 2.8 之前,由於會根據清單檢查要求的 URI(路徑 + 查詢參數),因此您需要新增完全一個要求的 URI 才能將其從重新導向中排除。

§預設值變更

Play 使用的一些預設值已變更,這可能會對您的應用程式造成影響。本節說明預設變更的詳細資訊。

§提供檔案時不再傳送Content-Disposition: inline 標頭

透過 Scala APIJava API 提供檔案時,Play 預設會自動產生 Content-Disposition 標頭並將其傳送給客戶端。

不過,從 Play 2.8 開始,如果計算出的標頭最終完全Content-Disposition: inline(傳遞 inline = true,這是預設值,以及 null 作為檔案名稱),Play 將不再自動傳送該標頭。這是因為根據 RFC 6266 第 4.2 節,預設會內嵌呈現內容。

因此,此變更不應對您造成任何影響,因為所有瀏覽器都遵守規格,不會對此標頭做任何特殊處理,而是會像未傳送標頭一樣內嵌呈現內容。

不過,如果您仍想傳送此確切標頭,您可以使用 ScalaJava Result 類別的 withHeader(s) 方法。

§相依性圖表變更

在 Play 2.7.0 之前,"com.typesafe.play" %% "play-test" artifact 包含 Akka HTTP 和 Netty 伺服器後端。這會為您的測試建立不穩定的行為,也可能會讓它們使用與製作程式碼不同的伺服器,具體取決於類別路徑的排序方式。在 Play 2.8 中,play-test 改為依賴於 play-server,然後測試將使用應用程式使用的相同伺服器提供者。如果您出於某種原因需要將提供者新增到我們的測試,您可以透過將 Akka HTTP 或 Netty 伺服器相依性新增為 "test" 相依性來執行此操作。例如

libraryDependencies += akkaHttpServer % "test" // Use nettyServer if you want the Netty Server backend

§更新的函式庫

除了更新我們自己的函式庫(play-json、play-ws、twirl、cachecontrol 等)的新版本之外,許多其他重要的相依性也更新到最新版本

下一頁:Play 2.7


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