文件

§介紹 Play 2

此頁面也適用於 2023 年 10 月發布的 Play 3

自 2007 年以來,我們一直致力於簡化 Java 網路應用程式開發。Play 最初是 Zenexity(後來成為 Zengularity,最後被 Fabernovel 收購)的內部專案,深受我們執行網路專案方式的影響:專注於開發人員生產力、尊重網路架構,並從一開始就採用創新的封裝慣例,在有意義的地方打破所謂的 JEE 最佳實務。

2009 年,我們決定以開源專案的形式與社群分享這些想法。立即獲得極為正面的回饋,而且專案獲得極大的關注。如今,經過多年積極的公開開發,Play 已有數個版本,擁有超過 10,000 人的活躍社群,而且全球各地都有愈來愈多的應用程式在執行。

對全世界開放專案當然意味著有更多回饋,但也意味著發現和瞭解新的使用案例、所需功能,以及找出最初設計及其假設中未特別考慮的錯誤。在這些年來將 Play 作為開源專案開發期間,我們致力於修正這類問題,並整合新功能以支援更廣泛的場景。隨著專案的成長,我們從社群和自己的經驗中學到了很多,在愈來愈複雜且多樣化的專案中使用 Play。

同時,技術和網路持續演進。網路已成為所有應用程式的中心點。HTML、CSS 和 JavaScript 技術快速演進,這讓伺服器端架構幾乎不可能跟上腳步。整個網路架構正快速朝向即時處理邁進,而現今專案輪廓的新興需求表示 SQL 不再能作為獨占資料儲存技術。在程式語言層級,我們見證了幾種 JVM 語言的重大變革,包括 Scala,其受歡迎程度日益提升。

這就是我們建立 Play 2 的原因,這是一個適用於新時代的新網路架構。

§專為非同步程式設計而建

現今的網路應用程式整合了更多並行的即時資料,因此網路架構需要支援完整的非同步 HTTP 程式設計模型。我們最初設計 Play 以處理具有許多短暫請求的傳統網路應用程式。但現在,事件模型是透過 Comet、長輪詢和 WebSocket 建立持續連線的方法。

Play 2 從一開始就根據每個請求都可能是長期的假設進行建構。但這還不夠:我們還需要一種強大的方式來排程和執行長時間執行的任務。基於 Actor 的模型無疑是目前處理高度並行系統的最佳模型,而 Java 和 Scala 都可使用的最佳模型實作是 Akka,因此我們將其納入。Play 2 提供原生 Akka 支援,適用於 Play 應用程式,讓撰寫高度分散式系統成為可能。

Play 3 以 Pekko 取代 Akka,更多詳細資訊可在此處找到 連結

§專注於類型安全性

使用靜態類型程式語言撰寫 Play 應用程式的一項好處是,編譯器可以檢查您的程式碼部分。這不僅有助於在開發過程中及早偵測錯誤,還讓許多開發人員參與大型專案時更輕鬆。

將 Scala 加入 Play 2 的組合中,我們顯然受益於更強大的編譯器保證,但這還不夠。在 Play 1.x 中,範本系統是動態的,基於 Groovy 語言,而編譯器無法為您做太多事。因此,範本中的錯誤只能在執行時偵測。控制器中膠水程式碼的驗證也是如此。

在 2.0 版中,我們真的希望進一步推動這個想法,讓 Play 在編譯時檢查大部分程式碼。這就是我們決定將基於 Scala 的範本引擎用作 Play 應用程式的預設值的原因,即使是使用 Java 作為主要程式語言的開發人員也是如此。這並不表示您必須成為 Scala 專家才能在 Play 2 中撰寫範本,就像您在 Play 1.x 中撰寫範本時不需要真的了解 Groovy 一樣。

在範本中,Scala 主要用於導覽您的物件圖形,以便顯示相關資訊,其語法非常接近 Java。但是,如果您想發揮 Scala 的強大功能來撰寫進階範本抽象,您很快就會發現 Scala 作為以表達式為導向且具有功能性的語言,非常適合範本引擎。

這不僅適用於範本引擎:路由系統也經過完全類型檢查。Play 2 會檢查您的路由說明,並驗證所有內容的一致性,包括反向路由部分。

完全編譯的一個好處是,範本和路由檔案會更容易封裝和重複使用。您在執行時也會在這些部分獲得顯著的效能提升。

§原生支援 Java 和 Scala

在 Play 專案的早期,我們開始探索使用 Scala 程式語言撰寫 Play 應用程式的可能性。我們最初將這項工作作為一個外部模組推出,以便能夠自由地進行實驗,而不會影響架構本身。

將 Scala 正確地整合到基於 Java 的架構中並不容易。考量到 Scala 與 Java 的相容性,可以快速地達成一個簡單的初步整合,僅使用 Scala 的語法取代 Java 的語法。然而,這肯定不是使用該語言的最佳方式。Scala 結合了真正的物件導向與函式式程式設計。要充分利用 Scala 的強大功能,需要重新思考架構中大部分的 API。

我們很快地達到了作為一個獨立模組的 Scala 支援所能做到的極限。我們在 Play 1.x 中做出的最初設計選擇,過度依賴 Java 反射 API 和位元組碼操作,使得在不完全重新思考 Play 內部的一些基本部分的情況下,更難以進展。同時,我們為 Scala 模組建立了幾個很棒的元件,例如新的類型安全範本引擎和全新的 SQL 存取元件 Anorm。這就是我們決定,為了完全發揮 Scala 與 Play 的強大功能,我們將 Scala 支援從一個獨立模組移到 Play 2 的核心,而 Play 2 從一開始就設計為原生支援 Scala 作為一種程式語言。

另一方面,Java 肯定不會從 Play 2 獲得較少的支援;恰恰相反。Play 2 建置為我們提供了一個機會,可以提升 Java 開發人員的開發體驗。Java 開發人員會取得一個真正的 Java API,考量到所有 Java 特殊性而撰寫。

§強大的建置系統

從 Play 專案開始,我們選擇了一個執行、編譯和部署 Play 應用程式的全新方式。它可能一開始看起來像是一個深奧的設計,但提供非同步 HTTP API(而不是標準 Servlet API)、透過開發期間的即時編譯和重新載入原始碼的短回饋週期,以及推廣一個新的封裝方法,這些都是至關重要的。因此,很難讓 Play 遵循標準 JEE 慣例。

如今,這種無容器部署的想法在 Java 世界中越來越受到接受。這是一個設計選擇,讓 Play Framework 能夠原生執行於像 Heroku 這樣的平台上,它引進了一個我們認為是彈性 PaaS 平台上 Java 應用程式部署未來的模型。

然而,現有的 Java 建置系統並不足以支援這個新方法。由於我們想要提供直接的工具來執行和部署 Play 應用程式,在 Play 1.x 中,我們建立了一個 Python 腳本集合來處理建置和部署任務。

同時,使用 Play 進行更多企業規模專案的開發人員(需要建置流程自訂和與現有公司建置系統整合)會有點不知所措。我們在 Play 1.x 中提供的 Python 腳本絕不是一個功能齊全的建置系統,而且不易自訂。這就是為什麼我們決定為 Play 2 採用一個更強大的建置系統。

由於我們需要一個現代建置工具,它必須足夠靈活以支援 Play 原創慣例,並能夠建置 Java 和 Scala 專案,因此我們選擇在 Play 2 中整合 sbt。sbt 是 Scala 的事實上建置工具,而且在 Java 社群中也越來越受到接受。

這也表示與 Maven 專案的整合會更好,可以將專案打包並發佈為任何儲存庫的一組 JAR 檔案,特別是在開發期間,即使是標準的 Java 或 Scala 函式庫專案,也可以進行即時編譯和重新載入。

§資料儲存和模型整合

「資料儲存」不再與「SQL 資料庫」同義,而且可能從來就不是。許多有趣的資料儲存模型正變得流行,為不同的情境提供不同的特性。基於此原因,像 Play 這樣的網路架構很難對開發人員將使用的資料儲存類型做出大膽的假設。Play 中的通用模型概念不再有意義,因為幾乎不可能使用單一 API 抽象出所有這些技術類型。

在 Play 2 中,我們希望讓使用任何資料儲存驅動程式、ORM 或任何其他資料庫存取函式庫變得非常容易,而無需與網路架構進行任何特殊整合。我們只想提供一組最小的輔助程式來處理常見技術問題,例如管理連線範圍。然而,我們也希望透過為沒有特殊需求的使用者組合預設工具來存取傳統資料庫,以維護 Play Framework 的全堆疊面向,這就是為什麼 Play 2 具有 JPA、Slick 和 Anorm 等關聯式資料庫存取函式庫。

下一頁:Play 使用者群組


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