§Play 2.4 遷移指南
這是從 Play 2.3 遷移至 Play 2.4 的指南。如果您需要從 Play 的早期版本進行遷移,則必須先遵循 Play 2.3 遷移指南。
除了此頁面上的資訊外,還有一些主題有更詳細的遷移資訊
§Java 8 支援
不再支援 Java 6 和 Java 7,Play 2.4 現在需要 Java 8。這項決定是基於下列事實:Java 7 已於 2015 年 4 月結束生命週期。此外,Java 8 支援簡潔的 API,且更支援函式程式設計風格。如果您嘗試使用 Java 6/7 來使用 Play 2.4,您將會收到以下錯誤
java.lang.UnsupportedClassVersionError: play/runsupport/classloader/ApplicationClassLoaderProvider : Unsupported major.minor version 52.0
一個 java.lang.UnsupportedClassVersionError 表示使用比類別檔案編譯時更舊版本的 Java 來讀取 Java 類別檔案不受支援。
注意:Scala 2.10 並未完全支援所有 Java 8 語言功能,例如介面的靜態方法。如果您的專案有使用 Java 8 中這些新功能的 Java 程式碼,請升級以使用 Scala 2.11.6+。請參閱 sbt 文件 以了解如何將
scalaVersion
設定到您的專案。
§建置變更
在 sbt 中載入/執行 Play 專案之前,需要執行下列步驟來更新您的 sbt 建置。
§Play 升級
更新 project/plugins.sbt
中的 Play 版本號碼以升級 Play
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.0") // Set to latest version of Play 2.4
§sbt 升級
Play 2.4 現在至少需要 sbt 0.13.8。更新您的 project/build.properties
,使其讀取
sbt.version=0.13.8
§在獨立模組中支援 Specs2
如果您之前使用 Play 的 specs2 支援,您現在需要明確地將其相依性新增到您的專案
libraryDependencies += specs2 % Test
如果您使用 .scala 建置檔案,您將需要新增下列匯入 import play.sbt.PlayImport._
§資料庫演進支援在一個獨立模組中
支援 資料庫演進 曾經包含在 Play JDBC 和 JPA 支援中。現在不再是這樣。因此,如果你正在使用演進,現在你需要在專案的建構中加入一個明確的相依性到 evolutions
libraryDependencies += evolutions
同時,如果你沒有使用演進,現在可以安全地從你的 application.conf
中移除 evolutionplugin=disabled
。
組態金鑰已經改變,所以現在你需要使用 play.evolutions.enabled=false
而不是 evolutionplugin=disabled
(請參閱 演進組態)
如果你正在使用 Play Slick 模組(有或沒有演進),事情已經改變很多,所以請務必閱讀 Play Slick 遷移指南。
§IDE:Eclipse 和 IntelliJ IDEA
Play 不再包含 sbteclipse 或 sbt-idea 外掛程式,這讓使用者可以獨立於 Play 升級 IDE 支援。
Eclipse 支援可以設定,只額外增加一行來匯入外掛程式。有關詳細資訊,請參閱 文件。
IntelliJ 現在可以原生匯入 sbt 專案,因此我們建議使用它。或者,可以手動安裝和使用 sbt-idea 外掛程式,說明可以 在此 找到。
§Play sbt 外掛程式 API
sbt 外掛程式中的所有類別現在都在套件 play.sbt
中,如果你使用 .scala
檔案來組態你的建構,這特別相關。你需要從 play.sbt.PlayImport
匯入識別碼,才能使用 play 提供的組態元素。
§playWatchService
重新命名
sbt 設定金鑰 playWatchService
已重新命名為 fileWatchService
。
對應的類別也已變更。若要設定 FileWatchService 每兩秒輪詢一次,請使用下列方式
PlayKeys.fileWatchService := play.runsupport.FileWatchService.sbt(2000)
§Play Slick 相依性
Play Slick 模組已進行大幅度重新設計,以支援 Slick 3.0。如要順利升級,請閱讀 Play Slick 遷移指南。
§Ebean 相依性
Ebean 已移出至外部專案,以使其生命週期不受 Play 自身生命週期影響。Ebean 位元組碼增強功能也已從 Play sbt 外掛程式中抽取至其自己的外掛程式。
若要將現有的使用 Ebean 的 Play 專案遷移至新的外部 Ebean 外掛程式,請從 build.sbt
中的 libraryDependencies
中移除 javaEbean
,並將下列內容新增至 project/plugins.sbt
addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "1.0.0")
接著,為專案啟用 Ebean 外掛程式
lazy val myProject = (project in file("."))
.enablePlugins(PlayJava, PlayEbean)
最後,將 Ebean 對應類別設定為清單,而非逗號分隔字串(仍支援,但已標示為不建議使用)
ebean.default = ["models.*"]
ebean.orders = ["models.Order", "models.OrderItem"]
此外,Ebean 已升級至 4.5.x,其中包含 Play 先前自行新增的幾個功能,包括 Model
類別。因此,Play Model
類別已標示為不建議使用,建議改用 com.avaje.ebean.Model
。
§位元組碼增強
Play 的位元組碼增強(為 Java 屬性產生 getter 和 setter)已從 Play 核心移出至單獨管理的專案,該專案可擁有自己的生命週期。若要啟用,請將下列內容新增至 project/plugins.sbt
檔案
addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0")
§相依性注入
立即播放,開箱即用,使用 Guice 提供的依賴注入。這是 Play 長期策略的一部分,目的是移除 Play 中的全局狀態,我們希望在 Play 3.0 版本中完成此項工作。將任何應用程式從依賴全局狀態轉移到完全無全局狀態是一個大任務,如果一次完成,可能會造成很大的破壞。因此,我們在 Play 中採取的方法是將變更分散在多個版本中,讓最終使用者可以逐漸遷移其程式碼,使其不依賴全局狀態,而非一次強制執行。
在實際可行的範圍內,我們已確保 Play 2.4 中提供的 API 與 Play 2.3 相容。這表示在許多情況下,有兩種方法可以執行工作,一種依賴全局狀態,另一種則不依賴。我們已更新文件,以反映執行工作的全新依賴注入方法 - 如果您仍想使用舊 API 並查看相關文件,通常 Play 2.3 文件仍然相關。
在繼續將程式遷移到 Play 2.4 之前,請務必閱讀 Play 中關於依賴注入的文件。有一些決定必須先做出。開箱即用,我們提供並鼓勵使用 Guice 進行依賴注入,但許多其他依賴注入工具和技術,包括 Scala 中的編譯時間依賴注入技術,都是可行的。您可以在 Java 或 Scala 中閱讀關於依賴注入的資訊。
§路由
關於依賴注入,其中一個最具破壞性的變更在於我們現在支援產生兩種樣式的路由器。第一種是現有的靜態樣式,這與 Play 2.3 路由器大致相同。它是一個 Scala 單例物件,並假設它呼叫的所有動作都是 Scala 單例物件或 Java 靜態方法。第二種是依賴注入路由器,它是一個在建構函式中宣告其依賴項目的類別。為了說明這兩個路由器之間的差異,請考慮下列路由檔案
GET / controllers.Application.index
POST /save controllers.Application.save
GET /assets/*file controllers.Assets.versioned(path = "/public", file: Asset)
靜態路由產生器將會產生一個路由器,其大致上(偽程式碼)如下所示
object Routes extends GeneratedRouter {
def routes = {
case ("GET", "/") => controllers.Application.index
case ("POST", "/save") => controllers.Application.save
case ("GET", "/assets/:file") => controllers.Assets.versioned("/public", file)
}
}
同時,注入路由產生器將會產生一個路由器,其大致上如下所示
class Routes(application: controllers.Application, assets: controllers.Assets) extends GeneratedRouter {
def routes = {
case ("GET", "/") => application.index
case ("POST", "/save") => application.save
case ("GET", "/assets/:file") => assets.versioned("/public", file)
}
}
預設會使用靜態路由產生器。如果您尚未準備好將所有 Java 動作移轉為非靜態方法,或將 Scala 動作移轉為類別,則必須使用此選項。在大部分情況下,這相當容易執行,在 Java 中,需要刪除 static
關鍵字,在 Scala 中,需要將 object
字詞變更為 class
。靜態路由器仍支援 @
算子,它會指示路由器從執行時期的 Injector
查詢動作,如果您處於過渡時期,其中一些動作為靜態而另一些則已注入,您可能會覺得這很有用。
如果您想要切換到注入產生器,請在 build.sbt
中將下列內容新增到您的建置設定
routesGenerator := InjectedRoutesGenerator
預設情況下,Play 會自動使用 Guice 為您處理此路由器的配線,但根據您採用的 DI 方法,您可能會自訂它。
注入的路由產生器也支援路由上的 @
算子,但其意義略有不同(因為所有內容都已注入),如果你在控制器之前加上 @
,則會注入該控制器的 JSR 330 Provider
,而不是直接注入該控制器。例如,這可用於消除循環相依問題,或者如果你想要每個請求都實例化一個新的動作。
此外,Play 現在預設會在 router
套件中產生路由器,而不是在根套件中。這是為了協助相依注入,因此如果需要,可以手動建立或繫結,因為通常無法參照根套件中的類別。
§相依注入元件
雖然 Play 2.4 不會強迫你使用相依注入版本的元件,但我們鼓勵你開始轉換到這些版本。下表顯示了使用全域狀態的舊靜態 API 和你應該轉換到的新注入 API
§Scala
舊 API | 新 API | 註解 |
---|---|---|
Lang |
Langs |
|
Messages |
MessagesApi |
使用其中一個 preferred 方法,你可以取得 Messages 實例。 |
DB |
DBApi 或更佳,Database |
你可以使用 @NamedDatabase 註解取得特定資料庫。 |
Cache |
CacheApi 或更佳 |
你可以使用 @NamedCache 註解取得特定快取。 |
Cached 物件 |
Cached 實例 |
使用注入的實例,而不是伴隨物件。您可以使用 @NamedCache 註解。 |
Akka |
不適用 | 不再需要,只要宣告對 ActorSystem 的依賴即可 |
WS |
WSClient |
|
Crypto |
Crypto |
|
GlobalSettings |
HttpErrorHandler 、HttpRequestHandler 和 HttpFilters |
請閱讀下方 GlobalSettings 區段的詳細資訊。 |
§Java
舊 API | 新 API | 註解 |
---|---|---|
Lang |
Langs |
Lang 物件的實例仍然可以使用 |
Messages |
MessagesApi |
使用其中一個 preferred 方法,您可以取得 Messages 實例,然後您可以使用 at 來取得該語言的訊息。 |
DB |
DBApi ,或更好的是,Database |
您可以使用 @NamedDatabase 註解來取得特定資料庫。 |
JPA |
JPAApi |
|
Cache |
CacheApi |
您可以使用 @NamedCache 註解來取得特定快取。 |
Akka |
不適用 | 不再需要,只要宣告對 ActorSystem 的依賴即可 |
WS |
WSClient |
|
Crypto |
Crypto |
舊的靜態方法已移除,可以使用 play.Play.application().injector().instanceOf(Crypto.class) 靜態存取實例 |
GlobalSettings |
HttpErrorHandler 、HttpRequestHandler 和 HttpFilters |
請閱讀下方 GlobalSettings 區段的詳細資訊。 |
§GlobalSettings
如果您熱衷於使用依賴注入,我們建議您盡可能將程式碼移出 GlobalSettings
實作類別。請閱讀 `GlobalSettings` 遷移文件 以取得詳細資訊。
§Plugin
已棄用
Java play.Plugin
和 Scala play.api.Plugin
類型皆已棄用。請閱讀 將外掛移轉至模組 以更新您的程式碼,使用 play.api.inject.Module
。
§組態變更
Play 2.4 現在使用 reference.conf
來記錄和指定所有屬性的預設值。您可以輕鬆地前往 此處 並搜尋名為 reference.conf
的檔案,即可找到這些屬性。
此外,Play 現在已為大量的組態屬性命名更好的命名空間。舊的組態路徑通常仍可使用,但如果您使用它們,執行時期會輸出棄用警告。以下是已變更金鑰的摘要
舊金鑰 | 新金鑰 |
---|---|
application.secret |
play.crypto.secret |
application.context |
play.http.context |
session.* |
play.http.session.* |
flash.* |
play.http.flash.* |
application.router |
play.http.router |
application.langs |
play.i18n.langs |
application.lang.cookie |
play.i18n.langCookieName |
parsers.text.maxLength |
play.http.parser.maxMemoryBuffer |
csrf |
play.filters.csrf |
evolutions.* |
play.evolutions.* |
applyEvolutions.<db> |
play.evolutions.db.<db>.autoApply |
ws |
play.ws |
§Akka 組態
Play 2.4 現在只有一個 actor 系統。之前,內部 actor 系統是在 play.akka
下組態,而 Akka 外掛是在 akka
下組態。新的合併 actor 系統是在 akka
下組態。play.akka
下不再有 actor 系統組態。不過,仍有數個 Play 特定的設定在 play.akka
前綴下提供。
如果您想要變更 actor 系統的組態方式,您可以設定 play.akka.config = "my-akka"
,其中 my-akka
是您選擇的組態前綴。
請參閱 Java 或 Scala Akka 頁面以取得更多資訊。
§執行緒池組態
先前兩個 actor 系統的執行緒池組態略有不同。現在由於只有一個 actor 系統,因此組態已合併。我們也新增了 LIFO(基於堆疊)排程規則,這應可提升大部分 Play 應用程式的效能。
下列設定為 Play 2.4 的新預設值。我們的測試顯示這些設定具有良好的效能,但每個應用程式都不同,因此您可能需要調整這些設定或將其還原為 Play 2.3 設定。您可以在 application.conf
中覆寫任何這些值來執行此動作。以下是新設定
akka {
actor {
default-dispatcher {
fork-join-executor {
parallelism-factor = 1.0
parallelism-max = 24
task-peeking-mode = LIFO
}
}
}
}
特別是,您可能想嘗試 預設 Akka 設定
akka {
actor {
default-dispatcher {
fork-join-executor {
parallelism-factor = 3.0
parallelism-max = 64
task-peeking-mode = FIFO
}
}
}
}
請參閱 執行緒池組態區段 以取得更多資訊。
§HttpRequestHandler
Play 預設使用的 HttpRequestHandler 委派至舊版 GlobalSettings
方法。如果您未在應用程式中使用 GlobalSettings
,則可以透過變更處理常式來稍微提升效能。您可以在設定中新增下列內容來執行此動作
play.http.requestHandler = "play.http.DefaultHttpRequestHandler"
§記錄
現在僅透過 logback 組態檔案 來組態記錄。
§JDBC 連線池
現在預設的 JDBC 連線池由 HikariCP 提供,而非 BoneCP。
可以在 Play JDBC reference.conf
中找到 Play 連線池可用的完整組態選項範圍。
您可能會遇到下列例外
Caused by: java.sql.SQLException: JDBC4 Connection.isValid() method not supported, connection test query must be configured
如果您的 JDBC-Drivers 不支援 Connection.isValid(),就會發生這種情況。最快速且建議的修正方式是確定您使用最新版本的 JDBC-Driver。如果升級到最新版本沒有幫助,您可以在 application.conf 中指定 connectionTestQuery
,如下所示
#specify a connectionTestQuery. Only do this if upgrading the JDBC-Driver does not help
db.default.hikaricp.connectionTestQuery="SELECT TRUE"
可以在 HikariCP Github 頁面 上找到更多相關資訊
§主體解析器
預設主體解析器現在為 play.api.mvc.BodyParsers.parse.default
。它類似於 anyContent
解析器,只不過它只解析 PATCH、POST 和 PUT 要求的主體。若要解析其他方法的要求主體,請明確傳遞 anyContent
解析器至 Action
。
def foo = Action(play.api.mvc.BodyParsers.parse.anyContent) { request =>
Ok(request.body.asText)
}
§最大主體長度
對於 Scala 和 Java,已對處理和套用已設定的最大主體長度的方式進行一些小但重要的變更。
新的屬性 play.http.parser.maxDiskBuffer
指定可能會緩衝到磁碟的解析器所解析的任何主體的最大長度。這包括原始主體解析器和 multipart/form-data
解析器。預設為 10MB。
對於 multipart/form-data
解析器,所有文字資料部分的總長度受到已設定的 play.http.parser.maxMemoryBuffer
值限制,預設為 100KB。
在所有情況下,當超過其中一個最大長度解析屬性時,會傳回 413 回應。這包括明確覆寫 BodyParser.Of
註解上的 maxLength
屬性的 Java 動作 - 以前,如果已設定自訂最大長度,Java 動作會檢查 RequestBody.isMaxSizeExceeded
旗標,此旗標現已不建議使用。
此外,Java 動作現在可以宣告大於已設定最大長度的 BodyParser.Of.maxLength
值。
§JSON API 變更
JSON 查詢的語意已略微變更。JsUndefined
已從 JsValue
類型階層中移除,且所有 jsv \ foo
或 jsv(bar)
形式的查詢已移至 JsLookup
。它們現在會傳回 JsLookupResult
,而非 JsValue
。
如果您有以下形式的程式碼
val v: JsValue = json \ "foo" \ "bar"
如果您知道屬性存在,以下程式碼是等效的
val v: JsValue = (json \ "foo" \ "bar").get
如果您不知道屬性是否存在,我們建議使用模式比對或 JsLookupResult
上的方法來安全地處理 JsUndefined
案例,例如
val vOpt: Option[JsValue] = (json \ "foo" \ "bar").toOption
§JsLookup
所有 JSON 橫越方法已移至 JsLookup
類別,該類別會隱含套用至所有 JsValue
或 JsLookupResult
類型的值。除了 apply
、\
和 \\
方法之外,已新增 head
、tail
和 last
方法供 JSON 陣列使用。除了 \\
之外的所有方法都會傳回 JsLookupResult
,這是 JsValue
的包裝器,有助於處理未定義的值。
方法 as[A]
、asOpt[A]
、validate[A]
也存在於 JsLookup
中,因此類似以下的程式碼不應需要任何原始程式碼變更
val foo: Option[FooBar] = (json \ "foo" \ "bar").asOpt[FooBar]
val bar: JsResult[Baz] = (json \ "baz").validate[Baz]
由於這些變更,您的程式碼現在可以假設 JsValue
類型的所有值都能序列化為 JSON。
§讀取選項
OptionReads
在 2.4 中不再預設可用。如果您有 jsv.validate[Option[A]]
形式的程式碼,您需要用下列其中一種方式改寫
- 若要將
JsNull
和未定義的查詢結果都對應到None
,請使用jsv.validateOpt[A]
。這通常是您想要的。 - 若要將所有驗證錯誤都對應到
None
,請使用JsSuccess(jsv.asOpt[A])
。這是 2.3 中讀取Option
的方式。 - 若要將
JsNull
對應到None
,並驗證值(如果存在),請使用jsv.validate(Reads.optionWithNull[A])
。如果值不存在,結果將會是JsError
。
當使用函式組合器來建構 Reads
時,您很可能會想要取代
(JsPath \ "property").read[Option[String]]
為
(JsPath \ "property").readNullable[String]
這與上述 (1) 的做法相同。Writes
搭配 JsPath.writeNullable
和 Format
搭配 JsPath.formatNullable
也是如此。請注意,如果在最後一個節點之前找不到節點,readNullable
會傳回 JsError
,而不是 JsSuccess(None)
。
最後,您可能會遇到為需要 Option
的 Reads
的類型建立序列化器的問題,例如 Seq[Option[String]]
。在這種情況下,您只需要為 Option[String]
建立 reads
,並確保它在範圍內
implicit val optionStringReads: Reads[Option[String]] = Reads.optionWithNull[String]
§測試變更
FakeRequest
已被 RequestBuilder
取代。
Java 測試中使用的反向參考路由器已移除。傳遞參考路由器的任何 Helpers.call
呼叫都可以用 Helpers.route
呼叫取代,後者採用標準反向路由器參考或 RequestBuilder
。
§Java TimeoutExceptions
如果您使用 Java API,F.Promise
類別現在會擲回未檢查的 F.PromiseTimeoutException
,而不是 Java 的已檢查 TimeoutException
。先前使用的 TimeoutExceptions
沒有使用 throws
關鍵字正確宣告。我們沒有變更 API 以使用 throws
關鍵字,因為這表示使用者必須在方法中宣告 throws
,因此我們改為將例外情況變更為新的未檢查類型。請參閱 #1227 以取得更多資訊。
舊 API | 新 API | 註解 |
---|---|---|
TimeoutException |
F.PromiseTimeoutException |
§WS 伺服器
WSRequestHolder
已在 Scala 和 Java 中重新命名為 WSRequest
。先前 WSRequest
類別已移除,因為它只在 WS 中內部用於 OAuth 功能。
WS 已從 AsyncHttpClient 1.8.x 升級到 1.9.x,其中包含許多重大變更(如果您直接使用或設定該函式庫)。請參閱 AsyncHttpClient 遷移指南 以取得更多詳細資料。升級到 AsyncHttpClient 1.9.x 可在 HTTPS 中啟用伺服器名稱指示 (SNI) - 這解決了許多基於 HTTPS 的 CDN(例如高度依賴 SNI 的 Cloudflare)的問題。
WS 的組態設定已變更
ws.acceptAnyCertificate
已移至寬鬆設定中,稱為play.ws.ssl.loose.acceptAnyCertificate
,以更清楚指出盲目接受任何 X.509 憑證而不進行驗證的非安全本質。ws.ssl.debug
設定已重新定義為布林值,例如play.ws.ssl.debug.all=true
。請參閱 除錯 SSL 以取得詳細資料。ws.ssl.disabledSignatureAlgorithms
和ws.ssl.disabledKeyAlgorithms
已重新定義為字串陣列,例如play.ws.ssl.disabledSignatureAlgorithms = ["MD2", "MD4", "MD5"]
。
由於 AsyncHttpClient 1.9.x 升級,幾個設定不再使用 AsyncHttpClientConfig.Builder 中 1.8.x 版本中的名稱。為了減少混淆,以下是從 WS 設定到 1.9.x AsyncHttpClientConfig.Builder 的對應表
play.ws.ning.connectionTimeout
-> setConnectTimeoutplay.ws.ning.idleTimeout
-> setReadTimeoutplay.ws.ning.followRedirects
-> setFollowRedirectplay.ws.ning.compressionEnabled
-> setCompressionEnforcedplay.ws.ning.allowPoolingConnection
-> setAllowPoolingConnectionsplay.ws.ning.allowSslConnectionPool
-> setAllowPoolingSslConnectionsplay.ws.ning.maxConnectionsTotal
-> setMaxConnectionsplay.ws.ning.maxConnectionLifetime
-> setConnectionTTLplay.ws.ning.idleConnectionInPoolTimeout
-> setPooledConnectionIdleTimeoutplay.ws.ning.webSocketIdleTimeout
-> setWebSocketTimeoutplay.ws.ning.maxNumberOfRedirects
-> setMaxRedirectsplay.ws.ning.disableUrlEncoding
-> setDisableUrlEncodingForBoundedRequests
WS 已將 OAuth 簽章計算器從 Signpost 變更為 AsyncHttpClient 的 OAuthCalculator。Signpost 仍用於擷取要求權杖和存取權杖。這不應需要任何應用程式層級變更,但若發生意外的 OAuth 失敗,則值得注意。
由於最近一系列的 TLS 漏洞,因此有更多活動會捨棄不安全的 HTTPS 組態。根據 RFC 7465,RC4 加密組已新增至已捨棄加密組清單中,且預設不可用。它們可以使用 play.ws.ssl.enabledCiphers
和 play.ws.ssl.loose.allowWeakCiphers
設定值,明確啟用為加密組。請同時考慮檢閱 RFC 7525,以取得 IETF 建議的 TLS 組態。
§加密 API
Play 2.4 的 AES 加密現使用 初始化向量 隨機化每個加密。Play 加密格式已變更,以新增對初始化向量的支援。
Play 2.4 使用的新 AES 轉換完整名稱為 AES/CTR/NoPadding
。舊轉換為 AES/ECB/PKCS5Padding
。CTR
模式比 ECB
模式安全許多。與之前相同,您可以透過設定 play.crypto.aes.transformation
組態選項,覆寫 Play 的加密轉換。在 Play 2.4 中,任何 JRE 支援的轉換 都可以使用,包括使用初始化向量的轉換。
Play 2.4 使用新的加密格式,但它可以讀取由 Play 早期版本加密的資料。然而,Play 早期版本無法讀取由 Play 2.4 加密的資料。如果您的 Play 2.4 應用程式需要產生舊格式的資料,您可能想要從 Play 2.3 Crypto 程式碼 複製演算法。
下表顯示不同 Play 版本所支援的加密格式。舊格式由 Play 早期版本使用。新格式 I由 Play 2.4 使用,如果設定的密碼沒有使用初始化向量。新格式 II在需要初始化向量時使用。
格式 | 編碼 | Play 2.3 | Play 2.4 | ||
---|---|---|---|---|---|
舊格式 | hex(cipher(plaintext)) | 寫入 | 讀取 | 讀取 | |
新格式 I | “1-” + base64(cipher(plaintext)) | 寫入 | 讀取 | ||
新格式 II | “2-” + base64(iv + cipher(plaintext, iv)) | 寫入 | 讀取 |
儘管輸出不同,但 Java Crypto API 的使用方式仍然相同
import play.libs.Crypto;
String enc = Crypto.encryptAES(orig);
String dec = Crypto.decryptAES(enc);
Scala Crypto API 的使用方式也相同
import play.api.libs.Crypto
val enc = Crypto.encryptAES(orig)
val dec = Crypto.decryptAES(enc)
§Anorm
新的 Anorm 版本包含各種修正和改進。請閱讀 此處 以瞭解更多資訊。
§HTTP 伺服器設定
進階 Netty 設定選項,也就是以 http.netty.option
為字首的選項,現在必須改用 play.server.netty.option
為字首。
§I18n
用於指定應用程式支援語言的設定金鑰已從 application.langs
變更為 play.i18n.langs
。此外,它現在是一個清單,而不是逗號分隔的字串。例如
play.i18n.langs = [ "en", "en-US", "fr" ]
§Scala
現在您需要一個隱含的 Messages
值,而不是只有 Lang
,才能使用 i18n API。Messages
類型會彙總一個 Lang
和一個 MessagesApi
。
這表示您應該變更範本,以接受隱含的 Messages
參數,而不是 Lang
@(form: Form[Login])(implicit messages: Messages)
...
從控制器中,您可以透過在控制器中混合 play.api.i18n.I18nSupport
特質來取得此類隱含的 Messages
值,只要隱含範圍內有 RequestHeader
值,它就會提供隱含的 Messages
值。I18nSupport
特質有一個抽象成員 def messagesApi: MessagesApi
,因此您的程式碼通常會如下所示
import javax.inject.Inject
import play.api.i18n.{MessagesApi, I18nSupport}
import play.api.mvc.Controller
class MyController @Inject() (val messagesApi: MessagesApi)
extends Controller with I18nSupport {
}
如果您希望控制器仍然使用靜態控制器物件,而不是使用具有 I18nSupport
特質的注入類別,則也支援較簡單的遷移路徑。在修改範本以採用隱含的 Messages
參數後,如上所述,請將下列匯入新增至您的控制器
import play.api.i18n.Messages.Implicits._
只要隱含範圍內有 Lang
和 Application
,此匯入就會提供隱含的 Messages
值(很幸運的是,控制器已經提供 Lang
,您可以透過匯入 play.api.Play.current
來取得目前執行的應用程式)。
§Java
此 API 應該與使用 Play 2.3 的程式碼向下相容,因此沒有遷移步驟。不過,請注意您必須在使用 Java i18n API 之前啟動 Play 應用程式。當您執行專案時,通常會是這種情況,但您的測試程式碼可能不會總是啟動應用程式。請參閱對應的 文件頁面,以了解如何在執行測試之前啟動應用程式。
§發行
以前,Play 會將所有資源新增至發行中的 conf
目錄,但不會將 conf
目錄新增至類別路徑。現在,Play 預設會將 conf
目錄新增至類別路徑。
這可以透過設定 PlayKeys.externalizeResources := false
來關閉,這將不會在發行版中建立 conf
目錄,而且它也不會在 classpath 中。應用程式 conf
目錄的內容仍會在 classpath 中,因為它包含在應用程式 jar 檔案中。
請注意,如果您使用 Java Persistence API (JPA),您需要將此選項設定為 false 才能部署您的應用程式。否則,您會收到錯誤訊息:Entity X is not mapped
。這對於本機開發並非必要。
§Debian 套件建立的變更
sbt-native-packager 已升級。因此,可能需要進行以下調整
* /etc/default/$appname
檔案的語法已從單純的命令列參數清單變更為由啟動/停止指令碼來源的 shell 指令碼,讓您可以設定環境變數。
* 舊預設檔案語法的等效項是您封存檔 conf
資料夾中的 application.ini
檔案。
* 預設檔案僅由 SystemV
Init 指令碼來源 - Upstart 目前忽略此檔案。若要變更您的建置以建立與 SystemV
相容的套件,請將此加入您的 build.sbt
import com.typesafe.sbt.packager.archetypes.ServerLoader.{SystemV, Upstart}
serverLoading in Debian := SystemV
- 可能需要的其他變更可以在 sbt-native-packager 發行說明 中找到。
§其他
§不再有 OrderedExecutionContext
神秘的 OrderedExecutionContext
已在 Play 中保留了多個版本,以支援舊版應用程式。它很少使用,現在已移除。如果您仍然需要 OrderedExecutionContext
,您可以根據 Play 2.3 原始碼 建立自己的實作。如果您沒有聽過這個類別,則您不需要執行任何動作。
§子專案資產
子專案中的任何資產現在都預設放置在 /lib/[子專案] 中,以允許根專案 / 不同子專案中具有相同名稱的檔案,而不會造成它們彼此干擾。
若要讓資產路由在您的應用程式中正確運作,您需要變更
GET /assets/*file controllers.myModule.Assets.at(path="/public", file)
為這
GET /assets/*file controllers.myModule.Assets.at(path="/public/lib/myModule", file)
在此文件檔中發現錯誤?此頁面的原始碼可以在 這裡 找到。在閱讀 文件檔指南 後,請隨時提交拉取要求。有問題或建議要分享嗎?請前往 我們的社群論壇 與社群展開對話。