Introduction to Play Framework for Scala developers 這個影片,由建立 Play Framework 專案開始,解釋初始專案的內容,在 trace 的過程中,連帶將如何使用 Play Framework 的概念一併提供給讀者。
啟動 play framework web server
在「命令提示字元」裡,切換到 scala-play 的目錄,然後鍵入指令 activator run ,就能啟動 play framework web server。瀏覽器瀏覽網頁 http://localhost:9000/ 就可以看到 play framework 的測試網頁。
網站首頁
首先我們先看 conf/routes 這個設定檔,這裡面針對 / 這個 URI,設定是由 controllers.Application 這個類別的 index 這個 method 負責處理。
設定檔 /conf/routes
## Home page
GET / controllers.Application.index
在 app/controllers/Application.scala 這個 controller 中,會看到處理 index 的 Action
package controllers
import play.api._
import play.api.mvc._
class Application extends Controller {
def index = Action {
Ok(views.html.index("Your new application is ready."))
}
}
瀏覽器首頁最上面的 "Your new application is ready." 文字,就是從這裡列印到網頁中的,但實際上,Ok 裡面還是呼叫了 view template 的程式,後面的部份是傳送給 view template 的文字參數。
在 play framework web server 啟動的狀態下,如果我們修改了 app/controllers/Application.scala 的內容,網頁會自動重新編譯,並輸出到瀏覽器上。同樣地,當原始程式編譯產生錯誤時,網頁也會自動顯示錯誤點,而且未來在實際上線時,可以將顯示錯誤點網頁的功能關閉。
view template
app/views/index.scala.html 最前面的 message 是收到的參數內容,也就是上一個步驟傳送進來的 "Your new application is ready.",接下來的 template 引用了兩個參數,並傳送至 app/views/main.scala.html。
play20.welcome 是一個內建在 play framework 的 template ,裡面是 play framework 的 document 網頁。
@(message: String)
@main("Welcome to Play") {
@play20.welcome(message)
}
app/views/main.scala.html 的一開始,定義了兩個參數,分別是 title 以及content html。
@(title: String)(content: Html)
<!DOCTYPE html>
<html lang="en">
<head>
<title>@title</title>
<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
<script src="@routes.Assets.versioned("javascripts/hello.js")" type="text/javascript"></script>
</head>
<body>
@content
</body>
</html>
將 app/views/index.scala.html 裡面的 @play20.welcome(message) 改為 @message,瀏覽器上就只會剩下 "Your new application is ready." 的文字列印在畫面上。
@(message: String)
@main("Welcome to Play") {
<!-- @play20.welcome(message) -->
@message
}
如何測試 play framework
test/ApplicationSpec.scala 是直接發送 http request,然後以 http response code 確認是否正常。
import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._
import play.api.test._
import play.api.test.Helpers._
/**
* Add your spec here.
* You can mock out a whole application including requests, plugins etc.
* For more information, consult the wiki.
*/
@RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification {
"Application" should {
"send 404 on a bad request" in new WithApplication{
route(FakeRequest(GET, "/boum")) must beSome.which (status(_) == NOT_FOUND)
}
"render the index page" in new WithApplication{
val home = route(FakeRequest(GET, "/")).get
status(home) must equalTo(OK)
contentType(home) must beSome.which(_ == "text/html")
contentAsString(home) must contain ("Your new application is ready.")
}
}
}
利用 browser 測試網站
import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._
import play.api.test._
import play.api.test.Helpers._
/**
* add your integration spec here.
* An integration test will fire up a whole play application in a real (or headless) browser
*/
@RunWith(classOf[JUnitRunner])
class IntegrationSpec extends Specification {
"Application" should {
"work from within a browser" in new WithBrowser {
browser.goTo("http://localhost:" + port)
browser.pageSource must contain("Your new application is ready.")
}
}
}
打開一個新的 「命令提示字元」,切換到 project 目錄,輸入 activator test
> activator test
[info] Loading global plugins from C:\Users\yaocl\.sbt\0.13\plugins
[info] Loading project definition from D:\projectcase\trunk3\play-scala-intro\project
[info] Set current project to play-scala-intro (in build file:/D:/projectcase/trunk3/play-scala-intro/)
[info] Compiling 2 Scala sources to D:\projectcase\trunk3\play-scala-intro\targe
t\scala-2.11\test-classes...
[info]
[info] IntegrationSpec
[info]
[info] Application should
[info] - play.api.libs.concurrent.ActorSystemProvider - Starting application default Akka system: application
[info] - play.api.libs.concurrent.ActorSystemProvider - Shutdown application default Akka system: application
[info] + work from within a browser
[info]
[info] Total for specification IntegrationSpec
[info] Finished in 14 seconds, 734 ms
[info] 1 example, 0 failure, 0 error
[info]
[info] ApplicationSpec
[info]
[info] Application should
[info] - play.api.libs.concurrent.ActorSystemProvider - Starting application default Akka system: application
[info] - play.api.libs.concurrent.ActorSystemProvider - Shutdown application default Akka system: application
[info] + send 404 on a bad request
[info] - play.api.libs.concurrent.ActorSystemProvider - Starting application default Akka system: application
[info] - play.api.libs.concurrent.ActorSystemProvider - Shutdown application default Akka system: application
[info] + render the index page
[info]
[info] Total for specification ApplicationSpec
[info] Finished in 447 ms
[info] 2 examples, 0 failure, 0 error
[info]
[error] Failed: Total 3, Failed 0, Errors 0, Passed 3
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 90 s, completed 2015/6/11 下午 01:53:07
如果測試時發生錯誤,修正程式後,可直接執行 "activator test-quick" 快速重新測試 failed tests
Data Persistence
在測試影片中說明的 sorm : scala 使用的 ORM framework,一直發生一些問題,在 play framework issue #4342中提到,sorm 原本是以 scala 2.10 編譯的,可能因此沒能正常地支援 2.11,最後建議嘗試使用 Anorm 或是 Slick。
根據上述文章的建議,我們就測試了 Anorm 的方案。
activator computer-database-scala 的 project template 設定過程如下:
activate new play-scala-db computer-database-scala
以 computer-database-scala 這個 template 建立一個新專案 play-scala-db
cd play-scala-db
切換到 play-scala-db 目錄
activator eclipse
建立 eclipse project settings
activator run
啟動 play-scala-db project
瀏覽器連結到 http://localhost:9000/ 可看到以下的畫面
這個 project template 是個傳統的 CRUD 頁面,Model 利用 Anorm 存取 DB,有使用 twitter bootsctrap 產出頁面以及分頁功能。project 設定檔 conf/application.conf 裡面預設是使用 h2 memory database。