play framework2 的學習筆記
https://github.com/playframework/playframework
https://github.com/playframework/playframework.com
1.語言部分
1.1.文檔中說每個視圖視圖就是函數,個人以為,從聲明的方式來看視圖更像是類,因為其中可以定義重用的方法,也能插入別的視圖。從調用的方式來看的確很像函數。
2.play特性
2.1.使用SBT編譯系統
以前開發bs程序都是由javac給你把java文件編譯成classes文件,現在不同了,必須由SBT系統來編譯/發布和運行才行,eclipse之類的IDE環境只是個帶語法檢查功能的寫字板而已。
2.2.性能
play framework 2服務器是基於高性能的apache mina開發的,因此性能不俗(支持集群),據官網說自己的性能很好,比其他任何服務器都快,我沒有做過這方面測試,所以不好評價。
2.3.第三方jar包
必須放在工程目錄\lib目錄里,否則無法編譯,注意,加入新jar包后要重新在控制台執行
eclipsify with-source=true
否則eclipse不會自動加包,當然了你也可以不用指令手工設置。
2.4.ehcache緩存
play 2自帶ehcache,無需編寫ehcache.xml(play2已經包含了ehcache.xml),直接就能用。
2.5.模塊和插件
到目前為止,我還沒有辦法找出來模塊和插件的區別在哪里,給我的感覺兩者是一回事。
play2提供了很多插件,在https://github.com/playframework/Play20/wiki/Modules可以下載
2.6.約定優於配置
這是ROR的特點之一,也是優點,在play2中Global.java類就是這個特性的體現,Global.java是繼承自GlobalSettings的類,用於實現一些全局的功能,比如類似Listener和Filter的功能之類。Global.java必須是這個名字而且必須放在app目錄下,否則是不起作用的。類似的東西還有好多,如果有文檔還好點,沒有文檔只能自己在play framework2源碼里找了。
2.7.導出成war包
play2默認是無法到處成war包的,好在有一個叫play2-war-plugin的插件可以幫我們打包成war包,這個插件在 https://github.com/dlecan/play2-war-plugin 可以下載,畢竟Play是另起爐灶,和J2ee標准差別比較大,所以這個插件是有不少局限的,比如必須發布為ROOT.war,還有對servlet版本有要求等等。
2.8.升級play工程
升級了play版本后(只是2.x版本之間的升級,1.x到2.x升級並不適用),工程中執行play會出現提示信息
Update the Play sbt-plugin version to 2.0.3 (usually in project/plugins.sbt)
你需要
a.修改project/plugins.sbt,把其中的版本號改成最新的版本號
b.執行update命令
c.重新執行eclipse with-source=true
3.表現層部分
3.1.視圖是需要編譯的
視圖是需要編譯的,和java文件一樣,也是由SBT來編譯,然后通過控制器來調用和渲染。和JSP有點像。
3.2.視圖的使用需要注意
剛剛接觸scala template,在使用視圖的語法困惑了一陣子
@main(title="home"){ <h1>hello world</h1> }
明明main.scala.html里面定義了@title和@content兩個參數,怎么這里只使用了一個?而且@content參數是如何傳入的?
后來琢磨了一下,總算是弄清楚了,視圖的參數傳遞很靈活,可以和python一樣用指定名字傳參數title="hme",也可以按照參數順序來傳遞,其實上面的代碼參數傳遞應該是這樣的
@main(title="home")(content="<h1>hello world</h1>")
下面的幾種寫法都是正確的
@main(content="<h1>hello world</h1>")(title="home") @main{home}{<h1>hello world</h1>}
甚至可以寫成
@p1={home} @p2={<h1>hello world</h1>} @main(title=p1)(body=p2)
3.3.控制器中調用視圖的方法
例如視圖的名字叫做demo1.scal.html,其中有一個name參數
那么在Controller中,直接用views.html.demo1.render("jim")來打開views/demo1.scala.html視圖並渲染,其中的參數和視圖中聲明的一致。
如果在開發工具中使用自動完成功能找不到這個demo1或者提示的參數是錯誤的,那就可以說明視圖未編譯,需要在工程目錄中先執行compile命令編譯,然后再刷新工程就ok了。
3.4.scala視圖的困擾
視圖不像文檔描述的那么簡單,但也不是非常難。
困難的原因:
* Scala語法實在太靈活,也太晦澀,基本上你以前掌握的編程技能和語法在Scala里很多都是沒用的,最起碼我是從頭認認真真的學了Scala的,學完仍是雲里霧里的一知半解。
* 目前仍然沒有一款和JSP/HTML編輯器那樣的出色的,帶語法檢查,自動完成,語法着色的Scala視圖編輯器,尤其是缺少和主流開發環境集成的編輯器插件。這就意味着你只有在運行時才能知道剛才弄的視圖語法是否有錯。
* 沒法用網頁設計工具來直接設計視圖,你只能先設計,再改成視圖,如果需要進一步修改外觀,就只能把應用運行起來在線預覽和借助firebug之類的調試工具了。(估計這會讓美工和前端工程師手足無措的)。
幾個好消息:
* 對於開發Scala視圖來說,只要你弄清楚最簡單的scala語法和流程控制命令就夠用了,太高級的功能根本用不着。
* play服務器具備刷新即可顯示變化的特點,所以改變了代碼后直接刷新瀏覽器,然后看瀏覽器上的錯誤信息來修正代碼是唯一的除錯手段(不能不說,play給出的錯誤提示不但完整而且清晰准確)。這就比開發j2ee程序時葯省去了不少時間。
* Scala同時支持指令方編程和函數式編程,指令式就是說的java那樣的編程方式,個人認為這種編程風格更容易上手,也符合從java轉過來的開發人員的編程習慣。
3.5.Scala視圖里的泛型表示
在Scala視圖里用[]表示泛型,所以List[String]就相當與java里的List
3.6.play里對XML的處理
play使用的是w3c的DOM解析器,而不是我熟悉的dom4j,不過play自帶一個XPath庫 play.libs.XPath,倒是也不難
多個節點:List<Node> list = XPath.selectNodes("//name", doc);
單一節點:XPath.selectText("//name", doc);
也挺簡單的。
3.7.Scala視圖里對XML的處理
視圖里也可以直接處理XML,根本不用拼字符串,很方便。
3.8.自帶緩存功能
用法特簡單
緩存數據:
Cache.set("name", "jim"); String name = Cache.get("name"); Cache.remove("name");
緩存http響應:
@Cached("homepage") public static Result index(){ return ok("hello world"); }
緩存視圖
@cache.Cace.getOrElse("cache-content", 3600){
} 3.9.LESS Less是一種動態樣式表語言,擴展名是less,里面可以用變量,繼承,運算等編程語言中常見的內容編譯生成css。play framework2支持less作為樣式表 3.9.1.幾個要點
a.less必須放在app/assets/stylesheets目錄下 b.編譯后的樣式表會輸出到target/scala-x.x.x/resource_managed/main/public/stylesheets目錄下,如果你的less文件是demo1.less,那么會生成demo1.css和demo1.min.css。 c.執行play compile不會編譯less,只有運行時才會編譯(至少play 2.0.2是這樣的) d.在*.scala.html中像正常那么引入css就可以了,而不用管css有沒有生成 個人感覺less對於需要大量編寫css的開發者比較好使,但對於奉行拿來主義的開發者來說,除了能檢查css是否有錯和生成的css體積較小外,沒什么特別的優點。
3.10.twitterbootstrap twitterbootstrap是twitter團隊寫的一套css框架包,基本上你想做網頁外觀樣式,他們都提供了,你只要設置一下class就可以了,很省事,但是twitterbootstrap並不適合中國國情,因為國內仍然有着大量的ie6用戶,twitterbootstrap對ie系列支持的比較糟糕,個人認為,在現階段最好不要用twitterbootstrap,可以考慮別的一些框架,比如jquery ui,blueprint,960 grid system,yui css framework之類,這些框架對ie支持的不錯。 3.11.圖片的引用 在css中往往會引用一些圖片,比如設置個背景圖什么的,像這種情況一定要用相對路徑,例如路徑如下
public/ public/stylesheets/main.css public/ javascripts public/images
圖片統一放到images目錄下,css中聲明如下
background: url('../images/back_enabled.png')
這樣就可以正常訪問了。
3.12.樣式表/圖片/js提供緩存處理
play的服務器是采用Apache Mina網絡框架開發的,提供了很多友好的功能,比如自帶緩存功能,自動重新載入class。
不過,play服務器是否能用於生產環境還有待進一步觀察。
3.13.實現Servlet里Filter的功能
有兩種方法
方法1:繼承GlobalSettings類,重寫onRequest()方法,return super.onRequest(request, actionMethod)即可執行原方法,否則就不執行。
方法2:使用@With也可以實現Filter的功能
3.14.實現Servlet里Listener的功能
繼承GlobalSettings類,實現onStart()方法和onStop()方法
4.持久層部分
4.1.Play里的持久層
目前Play提供可用的持久層有三個
第一個是早期提供的Anorm,提供簡單的SQL數據訪問功能,這個框架功能類似spring的jdbctemplate。
第二個是從Play2.0開始提供的ORM框架EBean,用法和JPA差不多。
第三個是JPA。
說實話,個人認為,持久層框架的選擇依據應該是選你最熟悉和最了解的,別追求什么高科技。而且play並沒有限制你必須用什么持久框架。
比如我對mybatis情有獨鍾,個人感覺mybatis做sql優化非常容易,這對於復雜的查詢來說特別重要。只是mybatis和play2集成的文章挺少的,我做了一個demo,請參看我的另一篇文章play2+guice+mybatis+ehcache+mmysql范例(java版)j2ee
5.測試
5.1.單元測試很方便
只要把基於junit的單元測試類都放到test目錄下,在控制台運行play test就能自動執行所有測試了,很方便。
play2甚至已經集成了HttpMock功能,用法很簡單
public class FakeAppTests { @Test public void t1(){ running(fakeApplication(), new Runnable() { public void run() { Result result = callAction(controllers.routes.ref.Application.index()); Assert.assertEquals(OK, status(result)); System.out.println(Helpers.contentAsString(result)); } }); }
play2的單元測試功能簡直太棒了,對於測試驅動開發非常有幫助。
6.常見問題
6.1.偶爾出現的無法編譯問題解決辦法(代碼沒錯誤)
偶爾會發生代碼無法編譯的情況,尤其是在你執行了clean命令之后,出現這個問題后,一般可以先把project/scala-2.9.1/src_managed加入源碼路徑一般就可以了。也不總是靈驗的,總之我遇到這問題后就是在加路徑,重啟eclipse,clean,compile這幾個動作之間來回折騰,往往折騰幾次后,惱人的編譯失敗問題就搞定了。
6.2.play的資料太少了
只有一份官方出的手冊比較有針對性,但這文檔寫的太籠統了,只能湊合看,play 1.x的書倒是有幾本,但和Play2區別還是挺大的,剛剛入門最好別看play1.x的書,否則會給領溝里去。
6.3.play的開發模式和流程
對於用慣了j2ee開發環境的人來說,剛剛上手play2的開發還是挺不適應的,因為play2的開發全靠着play控制台,而對ide要求不好,甚至你用記事本就可以做play開發。
而且調試比較費勁,必須開啟調試模式,然后在eclipse遠程調試attach9999端口才能調試,而且eclipse控制台里還不顯示日志信息,總之就是一個不習慣。其實這是因為play更多的依重單元測試來完成開發工作的,一般的play開發流程是這樣的
開發流程主要分三大塊
一.編寫單元測試->修改routes文件->修改Controller->編寫*.scala.html 到了這里,其實程序都還沒有運行過一次,代碼里面也是有很多錯誤,eclipse紅色的錯誤一大片,視圖模板也沒法預覽,顯示成什么樣子都不知道。
二.開始運行 單元測試,調試業務功能,調試視圖輸出,不斷的迭代修改,直到測試通過為止。
三.然后再正式運行服務,在瀏覽器里查看頁面顯示格式,修改*.scala.html頁面模板,修改顯示直到符合要求。基本上就是這么個流程,和以前在tomcat下開發是有很大不同的,如果不按照測試驅動的開發思路做play項目的話,只能起到事倍功半的效果。
這樣做的最終結果是你得到了一大堆的單元測試程序,這些單元測試程序對於保證你項目的穩定性和強壯性有者至關重要的價值,尤其是大項目重構時,其價值尤其重要。
總結
play 2功能還是很強悍的,非常適合快速開發B/S應用,而且內置了常用的框架和組件,上手挺快,比J2EE簡單多了。