PlayFramework入门教程
Scala語言與Play框架入門教程 (初稿)
http://cn.tanshuai.com/a/getting-started-scala-play#4
關于教程
更新日期:2012-11-28, 作者:tanshuai,電郵:?i@tanshuai.com
為了更好的服務于開發者,本教程將會持續更新,勘誤并完善內容。若發現本文的錯誤,建議或意見均可聯系本文作者。
Scala語言簡介
Scala語言編譯后的代碼直接運行在Java虛擬機之上,可調用所有的Java代碼庫,Scala設計目標是成為比Java更好的語言。Scala同時具備和整合了面向對象及函數式的編程特性。
Play框架簡介
Play Framework是一個開源的Web應用框架,使用Scala和Java語言混合編寫。Play遵循傳統的MVC(Model-View-Controller: 模型、視圖和控制器)模式,這一點Lift與其有所不同。
本文主要對Play Framework最新第二版(Play 2.0)進行講解。
目前本文所刊載網站?cn.tanshuai.com?就是基于Scala和Play Framework。
安裝和配置Scala和Play Framework開發環境
安裝 JDK
Scala作為Java虛擬機語言(JVM Language),與Java一樣需要Java虛擬機才能編譯和運行,因此開發者須首先安裝Java開發工具包(JDK),無論為個人學習還是商業開發,目前均推薦使用JDK 6 (Java SE 6)而非7,亦可使用同版本的OpenJDK。
安裝完JDK后,一定要檢查環境變量是否設置正確,檢驗方法:
在命令行程序中任意路徑位置,分別輸入java -version和javac -version 若輸出正確的java和javac版本信息,即表示安裝和環境變量設置正確; 若輸出的是"command not found"或"不是內部或外部命令,也不是可運行的程序"等錯誤提示,即表示沒有安裝成功或環境變量設置有誤。
下載地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk6u37-downloads-1859587.html
$ sudo apt-get install openjdk-6-jre下載Scala、Play工程項目
下載地址: http://../go/scala-play-prj.zip
Play 2.0開始使用Scala開發生態中的SBT(Simple Build Tool)作為編譯、運行、測試、部署和配置管理系統,類似Java的Maven。
SBT通常以一個sbt-launch.jar文件通過Java指令啟動,根據項目的SBT配置文件,自動下載該項目所需的全部工具和類庫。SBT可由開發者自行安裝在計算機中,作為各種項目的統一工具,也可放入工程項目中以便快速部署。
本文所提供的用于快速入門的工程項目內置了SBT,開發者下載解包后,根據不同的操作系統運行下列命令即可初始化和啟動開發環境:
- Window:
-
Unix (Linux / Mac OS X ...)
$ cd web_app $ ./sbt
Windows XP 的開發者請注意,由于Play Framework 發布版本的問題(Bug),目前無法在該操作系統上正常開發和運行,Windows 7不受影響。
使用Scala和Play開發環境
初始化Scala、Play開發環境
首次使用SBT,啟動和執行run命令時,SBT會自動下載所需的工具和類庫,如:Scala編譯器、Scala基礎庫、Play框架等相應開發和運行所必需的類庫,這個過程根據網速快慢可能需要數十分鐘至數個小時,開發者此時可以繼續閱讀本文下面的內容。
運行Scala Play Web應用
Scala和Play的開發和測試均在SBT命令行狀態下進行。進入項目所在路徑啟動SBT。
當出現[web_app] $?時,表示開發環境準備就緒,可以進行開發和測試工作。
輸入指令 run :
[web_app] $ run即可運行本文提供的工程項目Web應用,指令執行后輸出以下信息時證明啟動成功:
--- (Running the application from SBT, auto-reloading is enabled) ---[info] play - Listening for HTTP on port 9000...(Server started, use Ctrl+D to stop and go back to the console...)"Server started" 表示Web應用已經運行成功,"HTTP on port 9000" 指的是Web應用使用了本機9000端口作為Web服務器監聽端口。
此時在瀏覽器中輸入:http://localhost:9000,即可瀏覽該Web應用的效果。
首次運行需要等待數秒,用于SBT編譯項目中的Scala/Java代碼,此時會看到以下信息:
[info] Compiling 6 Scala sources and 1 Java source to /../web_app/target/scala-2.9.1/classes...Play是由Scala和Java混合編寫的框架,因此在用Scala開發Play應用的過程中雖并不需z編寫Java代碼,但Play會自動生成一個Java代碼文件,因此在編譯的時候會提示一個Java source,稍后會講解為何生成該Java代碼。
此時SBT命令行處于鎖定狀態,若想輸入新的SBT命令,必須按下Ctrl+D,重新回到命令行待命狀態:?[web_app] $
文件保存、瀏覽器刷新與自動編譯
在輸入run指令后,修改任何文件只需要進行保存,然后通過瀏覽器刷新(F5)網頁,SBT將會自動編譯修改后的文件,并將結果(或錯誤信息)輸出至瀏覽器。
清理編譯后的文件
有時需要清空所有編譯后的文件如各種.class文件以恢復全新的狀態,在待命狀態下輸入:
[web_app] $ clean可以嘗試執行該清理命令再重新編譯來解決開發過程中遇到一些難以理解的問題。
只編譯(不運行)
有時在進行程序編碼為了校驗語法等目的,不需要運行程序,以提高開發效率只需要執行編譯指令?compile?:
[web_app] $ compile退出 SBT
在待命狀態下輸入:
[web_app] $ exitPlay Framework下的Web開發
Play 工程目錄結構
web_app 根目錄 | sbt SBT Unix 批處理腳本用于啟動sbt-launch.jar | sbt.bat SBT Windows 批處理腳本用于啟動sbt-launch.jar | sbt-launch.jar SBT 啟動的Java可執行類庫 | +---app Play Web 應用全部代碼所在目錄 | | | +---models 模型代碼所在目錄 | | Message.scala 留言板例程模型代碼 | | | +---controllers 控制器代碼所在目錄 | | Application.scala 默認控制器代碼 | | | \---views 視圖(Play Scala HTML模板) 代碼所在目錄 | main.scala.html 主模板文件 | index.scala.html 首頁模板文件 | msgboard.scala.html 留言板例程模板文件 | +---conf Play 配置文件所在目錄 | application.conf 應用配置文件 | routes 應用入口路由文件,所有的HTTP請求將通過該文件轉發到指定的Scala對象處理 | +---logs 日志目錄 | application.log 應用運行日志 | +---project SBT工程文件 | build.properties 保存所需的SBT版本信息,通常無需更改 | Build.scala 主要的工程配置文件 | plugins.sbt 告知SBT本工程所需要的插件以及下載位置 | +---public 存儲一切直接發送給瀏覽器的資源文件 | | | +---images 圖像文件,如JPEG、PNG、GIF等 | | | +---javascripts JavaScript腳本文件 | | | \---stylesheets CSS樣式表文件 | \---target 存放編譯后的可執行代碼和編譯時的中間代碼一切從 routes 開始
Play 的應用入口為?conf/routes?文件,該文件定義了全部Play應用中URL對應的動作(Action),如當瀏覽器請求訪問 http://localhost:9000/ ,Play 應用將會返回一個頁面,此時routes文件應定義成如下形式:
GET / controllers.Application.index該定義告知Play收到HTTP GET類型請求且路徑為/時調用controllers包中Application類的index方法,對應的代碼即為:web_app/app/controllers/Application.scala
此時若嘗試訪問 http://localhost:9000/index.html,會出現“Action not found”錯誤提示,因為此時沒有在routes文件中定義針對GET /index.html的對應動作,開發者可嘗試修改routes文件,添加下列行:
GET /index.html controllers.Application.index當再次訪問 http://localhost:9000/index.html 會就發現瀏覽器可以正常顯示與http://localhost:9000/一樣的內容。
理解Play Framework控制代碼 (Controller)
上文的routes定義/和/index.html對應了Application.scala代碼中的index方法來顯示網頁內容:
//所有的控制代碼按Play規范均歸入controllers包 package controllers//導入Play應用開發所需的類庫 import play.api._ import play.api.mvc._ import play.api.templates._//Application全局對象實例化,因此使用Object來聲明Application并繼承Play的Controller類 object Application extends Controller {//定義index方法,任何routes文件中指定調用的方法,必須返回Action對象來處理HTTP請求def index = Action {//任何Action對象必須獲得反返回的Result對象//Ok繼承于Result對象,所以返回Ok表示其包含的內容為HTTP 200 OK狀態//在Scala最后一行代碼可以無需使用return來返回結果//因此下面最后一行代碼等同于 return Ok(views.html.index("首頁","首個Play Web應用!"))Ok(views.html.index("首頁","第一個Play Web應用!"))}}Ok表示所包括的內容的狀態為HTTP 200 OK,現在嘗試修改該段代碼為:
Ok("<p>修改后的<strong>代碼!</strong></p>")保存并刷新瀏覽器,會發現瀏覽器會將上面的字符串連同HTML標簽一起顯示出來,因為此時傳入Ok中對象類型為String,Ok將其Content-type作為text/plain輸出,所以連同HTML標簽一起顯示。
因此需要返回并告知Ok這是段Html格式內容而非純文本,因此套用Html類,再次修改代碼為:
Ok(Html("<p>修改后的<strong>代碼!</strong></p>"))保存并刷新瀏覽器,HTML標簽已不存在,文字也按照規定的格式正常顯示。
由此可知Play Web應用的調用順序和關系為:
瀏覽器 ( http://localhost:9000/ )-> Play 框架 (conf/routes) -> 對應的Controller代碼 (app/controllers/Application.scala) -> 對應的返回Action (def index = Action {...}) 的方法 -> 對應的可返回Result的代碼 (OK(...)) -> 要返回的正文內容 ( "..." 純文本 或 Html("...) HTML格式) 。
Play Framework模板 (View)
Play的模板在HTML基礎上直接基于Scala語言,模板文件通常存放在/app/views目錄下,文件須以“.scala.html”雙擴展名命名。Play的每個模板文件其實都是一個Scala代碼,均需要通過Scala編譯器檢查其類型與語法,并編譯成.class可執行的JVM二進制文件。
編譯時Play首相會將.scala.html的Play模板文件自動生成為.scala的源代碼文件,如 /app/views/index.scala.html的模板文件將會生成/target/scala-2.9.1/src_managed/main/views/html/index.template.scala文件,該文件將會繼而被Scala編譯器編譯成index.class。
首先看一下index.scala.html文件:
@(title: String, message: String) @* 模板入參,兩個參數均為String類型,分別命名為title和message *@@* 調用main.scala.html模板,傳入參數title *@ @main(title) {@* 輸出參數message *@<p>@message</p><a href="#">Scala語言與Play框架入門教程</a> }在Play的模板中@符號代表跟隨其后的代碼為Scala語言代碼,由于最終任何.scala.html文件都將轉換成Scala語言代碼,在編寫Play模板時也可以理解為編寫Scala語言代碼,一個模板文件可以理解為一個對象,因此需要傳入參數時就必須在模板文件的第一行定義都需要哪些入參以及這些入參的名字和類型。服務器端的代碼注釋寫法為: @* 注釋內容 *@
比如index.scala.html定義需要兩個入參,兩個參數均為String類型,分別命名為title和message,就對應了Application.scala代碼:
Ok(views.html.index("首頁","第一個Play Web應用!"))Play將會生成一個包名為views.html,名為index的實例化對象,并接受兩個String類型的入參,此時index.scala.html文件中的title = "首頁"、message = "第一個Play Web應用!",大括號中此時的內容應為:
<p>第一個Play Web應用!</p> <a href="#">Scala語言與Play框架入門教程</a>接下來@main(title)調用了main.scala.html模板,在Scala代碼層面可以理解為views.html.main(title)。
再看main.scala.html文件:
@(title: String)(body: Html)<!DOCTYPE html><html><head><title>@title</title></head><body>@body</body> </html>main.scala.html聲明需要兩個分別名為title的String類型和名為body的Html類型入參,index.scala.html將title直接傳給了main,因此此時main的title的值同樣也是"首頁",其后index將大括號中的全部的內容傳遞給了main的body。
根據上述代碼當我們訪問http://localhost:9000/時,輸出的全部內容為:
<!DOCTYPE html><html><head><title>首頁</title></head><body><p>第一個Play Web應用!</p><a href="#">Scala語言與Play框架入門教程</a></body> </html>Play 業務和數據模型 (Model)
當Web應用需要對數據模型進行處理時,則需要在app/models目錄下編寫相應的scala代碼,這些模型可以與內存、文件、關系型數據庫或NoSQL非關系型數據庫等數據存儲方式進行綁定,也可以是對業務邏輯或表單的定義。
下文將會對Play模型進行講解。
例程學習:留言板
設計一個留言板,通過表單提交留言,存儲在內存中,并顯示出全部留言。
定義留言板表單和數據模型
在app/models目錄下創建Message.scala文件,并寫入如下Scala代碼:
package models import play.api._ import play.api.data._ import play.api.data.Forms._//每條留言的數據模型:包括兩個字符串,分別存儲名字和內容 case class Message(name: String, content: String)//全部留言的數據操作 object Message {//用于存儲全部留言的列表var list: List[Message] = Nil//將留言追加在用于存儲全部留言的列表前面def post(name: String, content: String) {list :::= List(Message(name, content)) }//定義表單及其校驗要求,nonEmptyText表示該項內容不得為空val form = Form(tuple("name" -> nonEmptyText, "content" -> nonEmptyText))}設計視圖模板 (View)
在app/views目錄下創建msgboard.scala.html文件,并寫入如下Play模板代碼:
@(msgs: List[Message], msgForm: Form[(String, String)]) @* 模板入參: 第一個名為msgs的List[Message]類型參數; 第二個名為msgForm的Form[(String, String)]類型參數 *@@* 導入 helper 包下的類和對象,因為需要其中的form來生成表單 *@ @import helper._@* 調用main.scala.html模板,并將標題改為"留言板" *@ @main("留言板") {<h2>留言<h2><ul>@* 提取 msgs 入參中的全部數據 *@@msgs.map { message =><li>@* 提取名字 *@<p><strong>@message.name</strong></p>@* 提取內容 *@<p>@message.content</p></li>}</ul><h2>發言</h2>@* 創建表單,告知表單提交時發送POST給routes.Application.postMsg來處理 *@@form(routes.Application.postMsg) {@* 生成名字的輸入框*@@inputText(msgForm("name"), '_label -> "名字") @* 生成內容的輸入框 *@@inputText(msgForm("content"), '_label -> "內容") @* 生成用于提交的按鈕 *@<input type="submit" value="發送">} }編寫控制器 (Controller)
在app/controllers/Application.scala文件中加入如下代碼:
//顯示留言列表和發言表單def m = Action {Ok(views.html.msgboard(Message.list, Message.form))}//處理發言def postMsg = Action { implicit request =>Message.form.bindFromRequest.fold(//處理錯誤errors => BadRequest(views.html.msgboard(Message.list, errors)),{case (name, content) =>//發言Message.post(name, content)//重新定向到顯示留言列表和發言表單頁面Redirect(routes.Application.m)})定義routes
在conf/routes文件中寫入如下行:
# 顯示留言列表和發言表單 GET /m controllers.Application.m# 使用POST方式提交留言 POST /postMsg controllers.Application.postMsg運行和測試留言板
此時在瀏覽器中輸入:http://localhost:9000/m,即可測試留言板。
目前全部留言以List[Message]類型存于內存之中,一旦停止Play應用全部留言數據將會消失,下次再"sbt run"該留言板Play Web應用時留言內容為空。
建議學習本文的開發者嘗試將留言內容存于本地文件或數據庫中。
(完)
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的PlayFramework入门教程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vim显示行号、语法高亮、自动缩进的设置
- 下一篇: 使用python 提取html文件中的特