偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

使用Play框架快速進(jìn)行Java Web應(yīng)用開發(fā)

開發(fā) 后端
Play 框架是一個(gè)完整的 Web 應(yīng)用開發(fā)框架,覆蓋了 Web 應(yīng)用開發(fā)的各個(gè)方面。Play 框架在設(shè)計(jì)的時(shí)候借鑒了流行的 Ruby on Rails 和 Grails 等框架,又有自己獨(dú)有的優(yōu)勢(shì)。

雖然目前有很多種 Java Web 應(yīng)用開發(fā)框架,但Play 框架是一種新興的框架,可以幫助開發(fā)人員高效的構(gòu)建Web 應(yīng)用。51CTO在《Play!——另一個(gè)Java Web應(yīng)用框架》介紹過Play 框架是一個(gè)full-stack(全棧的)Java Web應(yīng)用框架,包括一個(gè)簡(jiǎn)單的無(wú)狀態(tài)MVC模型,具有Hibernate的對(duì)象持續(xù),一個(gè)基于Groovy的模板引擎,以及建立一個(gè)現(xiàn)代Web應(yīng)用所需的所有東西。

Play的關(guān)鍵特性:

1、一個(gè)非常簡(jiǎn)單的開發(fā)周期。此框架自動(dòng)編譯和重新裝載源文件的任何改變。

2、智能捆綁HTTP參數(shù)到Java方法參數(shù)。

3、基于Apache Mina的快速HTTP服務(wù)器。

4、一個(gè)基于Groovy的強(qiáng)大的模板引擎,具有多層繼承,定制用戶標(biāo)簽的能力,等。

5、優(yōu)秀的錯(cuò)誤報(bào)告功能:當(dāng)發(fā)生異常,此框架會(huì)直接顯示出錯(cuò)代碼,甚至是模板代碼。

本文詳細(xì)介紹了 Play 框架的使用,包括模型層、控制層、視圖層和 HTTP 路由等內(nèi)容。通過本文的介紹,開發(fā)人員可以了解到如何用 Play 框架來(lái)快速開發(fā) Web 應(yīng)用。

使用 Play 框架可以方便和高效的開發(fā)出 Java Web 應(yīng)用。通過 Play 框架提供的命令行工具,可以快速的創(chuàng)建出一個(gè) Web 應(yīng)用的基本骨架。它的 Java 代碼動(dòng)態(tài)編譯機(jī)制,使得修改代碼之后,不需要重啟服務(wù)器就可以直接看到修改之后的結(jié)果,調(diào)試起來(lái)非常方便。它使用 JPA 規(guī)范來(lái)完成領(lǐng)域?qū)ο蟮某志没梢院芊奖愕氖褂貌煌年P(guān)系數(shù)據(jù)庫(kù)作為后臺(tái)存儲(chǔ)。使用 Play 框架可以很容易的構(gòu)建使用 REST 架構(gòu)風(fēng)格的應(yīng)用。它使用 Groovy 作為視圖層模板使用的表達(dá)式語(yǔ)言。模板之間的繼承機(jī)制也可以避免代碼的重復(fù)??偟膩?lái)說(shuō),Play 框架非常適合快速 Web 應(yīng)用開發(fā)。

Play 框架采用經(jīng)典的 MVC 架構(gòu),把 Web 應(yīng)用分成模型層、控制層和視圖層三個(gè)層次。每個(gè)層次對(duì)應(yīng)的文件被存放在不同的目錄下面,方便組織和管理。使用 Play 框架的 Web 應(yīng)用具有相同的目錄結(jié)構(gòu),如 圖 1所示。

使用 Play 框架的 Web 應(yīng)用的目錄結(jié)構(gòu) 

圖 1. 使用 Play 框架的 Web 應(yīng)用的目錄結(jié)構(gòu)

如 圖 1所示,應(yīng)用自身的文件被放在 app目錄下面,三個(gè)子目錄分別存放的是 MVC 模式的三個(gè)層次的內(nèi)容。其中 models和 controllers目錄下面是 Java 源文件,而 views目錄下面則是視圖層使用的模板文件。conf目錄下面存放的是應(yīng)用的配置文件、HTTP 路由文件和國(guó)際化所需的消息文件。public目錄則是存放 Web 應(yīng)用的靜態(tài)文件,包括 JavaScript、CSS 和圖像文件等。lib目錄存放所需的額外的 Java 庫(kù)。test目錄存放的是測(cè)試結(jié)果。

開發(fā)環(huán)境

本文中使用的 Play 框架的版本是 1.0.3.1,使用的集成開發(fā)環(huán)境是 Eclipse 3.6, 使用 Dojo 作為 JavaScript 框架。在 Play 框架官方網(wǎng)站(見 參考資料)下載 Play 框架的壓縮包之后,解壓到某個(gè)目錄,并把該目錄下面的 bin目錄添加到環(huán)境變量中。接著啟動(dòng)一個(gè)命令窗口,運(yùn)行 play new developers_notebook就可以創(chuàng)建出一個(gè)新的名為 developers_notebook的 Web 項(xiàng)目。在項(xiàng)目目錄的父目錄下面,運(yùn)行 play eclipsify developers_notebook就可以創(chuàng)建出來(lái) Eclipse 工程。通過 Eclipse 導(dǎo)入此工程就可以在 Eclipse 里面進(jìn)行開發(fā)了。Play 框架的 support目錄下的 eclipse目錄下有個(gè)名為 org.playframework.playclipse的 Eclipse 插件,將此插件復(fù)制到 Eclipse 的 plugins目錄就可以安裝。運(yùn)行 play run就可以運(yùn)行此 Web 應(yīng)用,訪問 http://localhost:9000就可以看到。每次在 Eclipse 里面修改了代碼之后,不需要重新啟動(dòng)應(yīng)用,只需要刷新頁(yè)面就能看到更新之后的結(jié)果。這是 Play 框架的一個(gè)非常方便的特性。

本文中的示例應(yīng)用稱為“開發(fā)人員記事本”。開發(fā)人員可以用它來(lái)記錄開發(fā)過程中的一些注意事項(xiàng)。下面首先介紹 Play 框架中的模型層。

模型層

模型層包含的是 Web 應(yīng)用中的領(lǐng)域?qū)ο?。Play 框架推薦的實(shí)踐是模型層的對(duì)象不應(yīng)該是僅包含 getter/setter 方法的簡(jiǎn)單 Java Beans,而應(yīng)該有自己的業(yè)務(wù)邏輯。Play 框架中應(yīng)用的模型層類可以是任何的 Java 類。與一般的 Java Beans 不同的是,模型層類使用聲明為 public的域作為對(duì)象的屬性。Play 框架會(huì)自動(dòng)生成相應(yīng)的 getter/setter 方法。這樣可以使得代碼更加簡(jiǎn)潔。開發(fā)人員也可以提供自己的 getter/setter 方法實(shí)現(xiàn)。

領(lǐng)域?qū)ο蟪志没?/strong>

領(lǐng)域?qū)ο蟮膶?shí)例一般需要持久化下來(lái)。最常見的持久化方式就是使用關(guān)系數(shù)據(jù)庫(kù)。Play 框架使用 JPA 規(guī)范來(lái)進(jìn)行領(lǐng)域?qū)ο蟮某志没>唧w的后臺(tái)實(shí)現(xiàn)使用的是 Hibernate。開發(fā)人員只需要使用 JPA 規(guī)范定義的標(biāo)注,就可以聲明領(lǐng)域的持久化行為。比較好的做法是將領(lǐng)域?qū)ο箢惱^承自 Play 框架提供的 play.db.jpa.Model類。play.db.jpa.Model類提供了一個(gè)域 id作為對(duì)象的標(biāo)識(shí)符,也是對(duì)應(yīng)的數(shù)據(jù)庫(kù)表中的主鍵。play.db.jpa.JPASupport類是 play.db.jpa.Model的父類,提供了一些實(shí)用方法用來(lái)完成從領(lǐng)域?qū)ο蟮綌?shù)據(jù)庫(kù)之間的映射。表 1中列出了一些重要的方法,包括常用的增刪改查操作。

表 1. play.db.jpa.JPASupport API 說(shuō)明

play.db.jpa.JPASupport API 說(shuō)明

表 1中列出的方法中,find()和 all()方法的返回值是 play.db.jpa.JPASupport.JPAQuery類的實(shí)例,表示一個(gè)領(lǐng)域?qū)ο髮?shí)例的查詢結(jié)果。對(duì)于此查詢結(jié)果,可以進(jìn)行進(jìn)一步的操作。具體的操作,如 表 2所示。

表 2. play.db.jpa.JPASupport.JPAQuery API 說(shuō)明

play.db.jpa.JPASupport.JPAQuery API 說(shuō)明

使用 表 2中給出的方法,就可以在領(lǐng)域?qū)ο箢愔刑砑右恍┓浅?shí)用的方法,而不需要把這些方法添加到額外的服務(wù)層中。在示例應(yīng)用中,Note這個(gè)領(lǐng)域?qū)ο箢惐硎镜氖怯脩籼砑拥挠涗?。代碼清單 1中給出了 Note類中的一些實(shí)用方法。

清單 1. 領(lǐng)域?qū)ο箢愔械膶?shí)用方法

  1. // 創(chuàng)建新的領(lǐng)域?qū)ο?nbsp;Note 的實(shí)例,edit() 方法的使用與 create() 類似 
  2.  Map<String, String[]> params = new HashMap<String, String[]>();  
  3.  params.put("note.title", new String[] {"My note"});  
  4.  params.put("note.content", new String[] {"My note's content"});  
  5.  Note.create(Note.class, "note", params).save(); 
  6.  
  7.  // 使用 find() 來(lái)進(jìn)行查找 
  8.  List<Note> notes = Note.find("byTitle", "My note").fetch(); 
  9.  
  10.  // 使用 findById() 來(lái)查找單個(gè)實(shí)例 
  11.  Note note1 = Note.findById(1); 
  12.  
  13.  // 使用 delete() 來(lái)刪除對(duì)象實(shí)例 
  14.  Note.delete("byTitle", "My note"); 
  15.  
  16.  // 返回查詢結(jié)果中的第 2 到第 11 條記錄。 
  17.  Note.find("byTitle", "My note").from(1).fetch(10); 

在介紹完 Play 框架的模型層之后,下面介紹控制層。

控制層

Play 框架中的控制層是模型層和視圖層之間的橋梁。控制層負(fù)責(zé)接收 HTTP 請(qǐng)求并返回相應(yīng)的響應(yīng)。一般來(lái)說(shuō),控制層的典型實(shí)現(xiàn)是接收到 HTTP 請(qǐng)求之后,從請(qǐng)求中獲取一些參數(shù),再調(diào)用服務(wù)層對(duì)應(yīng)的處理方法。服務(wù)層的方法會(huì)對(duì)領(lǐng)域?qū)ο筮M(jìn)行操作,完成具體的業(yè)務(wù)邏輯。最后,某種格式的響應(yīng)被返回給請(qǐng)求者,如 HTML 頁(yè)面、JSON 數(shù)據(jù)和 XML 數(shù)據(jù)等。Play 框架的控制層實(shí)現(xiàn)使得完成這樣的典型場(chǎng)景變得非常簡(jiǎn)單。

Play 框架中的每個(gè)控制器都是一個(gè)普通的 Java 類,繼承自 play.mvc.Controller類,在包 controllers中??刂破黝愔械拿總€(gè)公開的靜態(tài)方法都表示一個(gè)動(dòng)作。每個(gè)動(dòng)作負(fù)責(zé)完整的請(qǐng)求 / 響應(yīng)的流程,也就是說(shuō),所有前面提到的所有請(qǐng)求 / 響應(yīng)的過程都需要在每個(gè)動(dòng)作中來(lái)完成。

參數(shù)綁定

在控制層實(shí)現(xiàn)中很繁瑣但是必不可少的操作就是解析 HTTP 請(qǐng)求中的參數(shù)。不同的 Web 開發(fā)框架會(huì)提供自己的參數(shù)解析方式。Play 框架也提供了相應(yīng)的支持。Play 框架可以解析 HTTP 請(qǐng)求中查詢字符串和 URI 路徑中包含的以及請(qǐng)求體中以 格式編碼的參數(shù)。所有這些參數(shù)都放在 params對(duì)象中,其中包含 get()、getAll()和 put()等方法用來(lái)獲取和設(shè)置參數(shù)的值。除了這種傳統(tǒng)的使用方式之外,Play 框架還支持直接把參數(shù)的值綁定到動(dòng)作方法的參數(shù)上面。比如一個(gè)動(dòng)作方法的聲明是 show(String username),那么請(qǐng)求中的參數(shù) username的值會(huì)在 show()方法被調(diào)用時(shí)作為實(shí)際參數(shù)傳遞進(jìn)去。Play 框架會(huì)負(fù)責(zé)完成相應(yīng)的類型轉(zhuǎn)換。值得一提的是對(duì)于日期類型(java.util.Date)的參數(shù),Play 框架支持多種類型的日期格式的轉(zhuǎn)換。比如動(dòng)作方法的聲明是 display(Date postedAt),而請(qǐng)求的格式可能是 /display?postedAt=2010-09-22,Play 框架會(huì)自動(dòng)完成相應(yīng)的類型轉(zhuǎn)換。

除了常見的基本數(shù)據(jù)類型之外,Play 框架還支持直接綁定領(lǐng)域?qū)ο蟮膶?shí)例。比如動(dòng)作方法的聲明是 create(Note note),可以在參數(shù)中直接指定對(duì)象實(shí)例的屬性的值。請(qǐng)求的格式可能是 /create?title=Note123&content=Good。Play 框架會(huì)負(fù)責(zé)創(chuàng)建一個(gè) Note類的實(shí)例,并根據(jù)參數(shù)的值設(shè)置該實(shí)例的屬性 title和 content的值。這種綁定方式不僅支持簡(jiǎn)單對(duì)象,還支持嵌套對(duì)象和列表。比如 /create?tags[0]=ajax&tags[1]=web可以設(shè)置列表類型屬性 tags的值。

Play 框架的這種綁定方式還支持文件對(duì)象,使得上傳文件變得非常簡(jiǎn)單。只需要在表單中添加文件上傳的控件(<input type="file">)并使用 multipart/form-data編碼來(lái)提交請(qǐng)求,在動(dòng)作方法的參數(shù)中就可以獲取到上傳文件對(duì)應(yīng)的 java.io.File對(duì)象。比如動(dòng)作方法的聲明可能是 upload(File picture)。上傳的文件被保存在臨時(shí)目錄中,在請(qǐng)求完成之后會(huì)被自動(dòng)刪除??梢栽趧?dòng)作方法中完成對(duì)上傳文件的操作。

返回響應(yīng)結(jié)果

在控制層的動(dòng)作方法完成了與業(yè)務(wù)邏輯相關(guān)的處理之后,需要把響應(yīng)返回給客戶端。響應(yīng)的結(jié)果可能是正確完成,也可能是出現(xiàn)錯(cuò)誤。Play 框架提供了方便的實(shí)現(xiàn)用來(lái)返回不同類型的響應(yīng)。使用 play.mvc.Controller類提供的不同方法就可以生成這些響應(yīng)內(nèi)容。

◆請(qǐng)求正確完成,HTTP 狀態(tài)代碼為 200。使用 ok()方法生成不帶內(nèi)容的響應(yīng)。使用 render()方法來(lái)生成使用模板的響應(yīng)。使用 renderText()方法生成 text/plain類型的純文本響應(yīng)。使用 renderXml()方法生成 text/xml類型的 XML 格式的響應(yīng)。使用 renderJSON()方法生成 application/json類型的 JSON 格式的響應(yīng)。使用 renderBinary()方法生成二進(jìn)制內(nèi)容的響應(yīng)。

◆跳轉(zhuǎn)到新的頁(yè)面,HTTP 狀態(tài)代碼為 3XX。使用 redirect()方法來(lái)跳轉(zhuǎn)到新的 URL。使用 notModified()方法來(lái)返回狀態(tài)代碼 304。

◆HTTP 狀態(tài)代碼 4XX。使用 unauthorized()方法返回狀態(tài)代碼 401。使用 forbidden()方法返回狀態(tài)代碼 403。使用 notFound()方法返回狀態(tài)代碼 404。

◆服務(wù)器內(nèi)部錯(cuò)誤,HTTP 狀態(tài)代碼 5XX。使用 error()方法返回狀態(tài)代碼 500。

從上面列出的方法可以看出,Play 框架使用一些有意義的方法名稱替換掉了難以記憶的 HTTP 狀態(tài)代碼,使用起來(lái)更加方便。同時(shí),對(duì)于常見的響應(yīng)格式,包括 HTML、XML、JSON 和二進(jìn)制內(nèi)容,都提供了相應(yīng)的方法,使得開發(fā)人員不會(huì)遺漏掉響應(yīng)中 Content-Type的聲明。

方法攔截

控制層的方法通常需要執(zhí)行一些橫切的邏輯,比如用戶認(rèn)證、加載通用信息和記錄日志等。在 Spring 框架中,這些橫切的邏輯是通過面向方面編程(AOP)的支持來(lái)實(shí)現(xiàn)的。Play 框架提供了更加簡(jiǎn)單易用的方法攔截支持,通過簡(jiǎn)單的標(biāo)注就可以定義一些執(zhí)行攔截操作的方法。這些方法必須非公開的靜態(tài)方法。Play 框架支持的方法攔截標(biāo)注有 @Before、@After、@Finally和 @With等四種。

用 @Before標(biāo)注的方法在動(dòng)作方法執(zhí)行之前被調(diào)用。@After標(biāo)注的方法在動(dòng)作方法執(zhí)行之后被調(diào)用。@Finally標(biāo)注的方法在動(dòng)作方法的響應(yīng)結(jié)果已經(jīng)成功生成之后被調(diào)用。這三個(gè)標(biāo)注都支持額外的兩個(gè)屬性:priority表示標(biāo)注的方法的優(yōu)先級(jí),0 為最高;unless是一個(gè)字符串?dāng)?shù)組,表示不適用此攔截方法的動(dòng)作方法的名稱。如 @Before(unless="index")表示此攔截方法不會(huì)應(yīng)用在動(dòng)作方法 index()上。

如果控制器類中存在繼承體系結(jié)構(gòu)的話,父類中聲明的攔截方法對(duì)于所有子類的動(dòng)作方法都是適用的。在有些情況下,開發(fā)人員可能希望把攔截方法定義在不同的類體系結(jié)構(gòu)中。由于 Java 不支持多繼承,無(wú)法通過繼承的方式來(lái)應(yīng)用來(lái)自不同類體系結(jié)構(gòu)上的攔截方法。針對(duì)這種情況,Play 框架提供了 @With標(biāo)注。在控制器類 ControllerA中定義的攔截方法可以通過 @With標(biāo)注來(lái)應(yīng)用到另外一個(gè)控制器類 ControllerB上,而且不通過繼承方式來(lái)實(shí)現(xiàn)。只需要在 ControllerB中聲明 @With(ControllerA.class)即可。

在介紹完 Play 框架的控制層之后,下面介紹視圖層。

視圖層

Web 開發(fā)框架的使用者都習(xí)慣于使用某種模板技術(shù)來(lái)生成 HTML 頁(yè)面,這些技術(shù)包括常見的 JSP、ASP 和 PHP 等。Play 框架也提供了自己的模板技術(shù),可以用來(lái)動(dòng)態(tài)的創(chuàng)建 HTML、XML、JSON 以及其它文本類型的內(nèi)容。Play 框架的模板技術(shù)使用的是 Groovy 語(yǔ)言。Groovy 語(yǔ)言的靈活性和簡(jiǎn)潔性使得 Play 框架的模板簡(jiǎn)單而且易用。在模板中可以混用靜態(tài)內(nèi)容和生成動(dòng)態(tài)內(nèi)容的各種元素。在模板中可以使用的動(dòng)態(tài)元素如 表 3所示。

表 3. 模板中可用的動(dòng)態(tài)元素

表 3. 模板中可用的動(dòng)態(tài)元素

Play 框架中的標(biāo)簽的作用相當(dāng)于 JSP 中的標(biāo)簽。Play 框架本身提供一些常用的標(biāo)簽,開發(fā)人員也可以根據(jù)需要開發(fā)自己的標(biāo)簽。Play 框架內(nèi)置提供的標(biāo)簽說(shuō)明如 表 4所示。

表 4. Play 框架提供的標(biāo)簽

Play 框架提供的標(biāo)簽

在模板中可以使用來(lái)自不同地方的變量。首先是在模板生成的時(shí)候,由控制器中的動(dòng)作方法通過 renderArgs對(duì)象來(lái)添加的。如 renderArgs.put("username", "Alex")就把一個(gè)變量 username添加到了模板中。其次是一些隱含的變量,如 request表示當(dāng)前的 HTTP 請(qǐng)求,session表示當(dāng)前的會(huì)話,params表示請(qǐng)求中的參數(shù)和 out表示用來(lái)輸出響應(yīng)的 java.io.Writer對(duì)象。最后就是可以通過 #{set}來(lái)設(shè)置變量。

模板的繼承

Play 框架中可以使用 #{extends}和 #{doLayout}來(lái)實(shí)現(xiàn)模板之間的繼承。模板的繼承機(jī)制對(duì)于實(shí)現(xiàn)靈活的頁(yè)面布局很有幫助。一個(gè)模板可以定義清楚頁(yè)面的基本布局結(jié)構(gòu),其它模板可以繼承此模板并添加具體的內(nèi)容。這樣就可以避免在不同模板中重復(fù)相同的頁(yè)面元素。
在父模板中可以包含任意的內(nèi)容。在需要由子模板填充的位置,使用 #{doLayout /} 進(jìn)行聲明即可。在子模板中通過 #{extends} 來(lái)聲明所繼承的模板。如 #{extends 'main.html'} 就聲明繼承自模板 main.html。當(dāng)子模板被生成之后,將包含父模板中的內(nèi)容。而子模板中只需要定義擴(kuò)展的內(nèi)容即可。

自定義標(biāo)簽

Play 框架自身提供的標(biāo)簽只能解決一些常見的需求,很多時(shí)候開發(fā)人員需要根據(jù)需要開發(fā)出自己的標(biāo)簽。一個(gè)標(biāo)簽的定義非常簡(jiǎn)單,就是一個(gè)模板文件。模板文件被存放在 app/views/tags目錄下,文件的名稱就是標(biāo)簽的名稱。在標(biāo)簽對(duì)應(yīng)的模板里面,開發(fā)人員可以添加任意的內(nèi)容。標(biāo)簽也是支持傳入?yún)?shù)的。在標(biāo)簽對(duì)應(yīng)的模板文件中可以用在參數(shù)名稱前面加上 _ 的方式來(lái)引用參數(shù)的值。比如一個(gè)標(biāo)簽在使用時(shí)的方式是 #{myTag name:'Alex' /},那么在該標(biāo)簽的模板文件中,就可以用 ${_name}來(lái)引用參數(shù) name 的值。有些標(biāo)簽是支持在使用的時(shí)候添加標(biāo)簽體的,如 #{anotherTag} 測(cè)試文字 #{/anotherTag}。對(duì)于這種情況,在標(biāo)簽的模板文件中可以用 #{doBody} 來(lái)引用標(biāo)簽體中的內(nèi)容。

在介紹完 Play 框架的視圖層之后,下面介紹 HTTP 路由。

HTTP 路由

在前面介紹過,Play 框架中的控制器用來(lái)接受 HTTP 請(qǐng)求并返回相應(yīng)的響應(yīng)。這個(gè)過程的重要一環(huán)就是 HTTP 請(qǐng)求的 URI 與控制器之間的映射關(guān)系。Play 框架提供了靈活的 HTTP 路由功能來(lái)完成這個(gè)映射。路由信息被保存在 config/routes 文件中,采用簡(jiǎn)單的方式進(jìn)行聲明。每條路由記錄包含 3 個(gè)元素,分別是 HTTP 方法的名稱、匹配的 URI 模式以及對(duì)應(yīng)的控制器動(dòng)作方法。路由記錄表示的含義是當(dāng)使用給定的 HTTP 方法來(lái)請(qǐng)求對(duì)應(yīng)模式的 URI 的時(shí)候,控制器動(dòng)作方法就會(huì)被調(diào)用。

Play 框架支持的 HTTP 方法有 GET、POST、PUT、DELETE 和 HEAD。使用通配符 *可以匹配任何方法。在 URI 模式的聲明中可以使用正則表達(dá)式來(lái)表示復(fù)雜的映射規(guī)則。URI 模式中還可以使用 {...}來(lái)聲明動(dòng)態(tài)的部分。每個(gè)動(dòng)態(tài)部分都是有名稱的,可以在控制器動(dòng)作方法中通過 params對(duì)象來(lái)獲取。比如,/notes/home 這樣的 URI 模式會(huì)匹配 /notes/home,但是 /notes/{id} 可以匹配 /notes/123 和 /notes/abc,而且 URI 模式中 /notes/ 后面的部分可以作為參數(shù) id 的值被獲取到。URI 模式 /notes/{<[0-9]+>id} 使用了正則表達(dá)式,只會(huì)匹配 /notes/后面緊跟的全是數(shù)字的情況。在聲明控制器的動(dòng)作方法的時(shí)候,需要使用帶名稱空間的全名,如 myapp.Notes.show。有些動(dòng)作方法是帶參數(shù)的,可以在聲明的時(shí)候預(yù)先綁定一些參數(shù)值,這樣可以方便的添加一些 URI 別名。比如動(dòng)作方法 Notes.show() 有一個(gè)參數(shù) id 用來(lái)指明要顯示的內(nèi)容的 ID。如果參數(shù) id 的值為 0,則會(huì)顯示所有內(nèi)容的一個(gè)列表。這樣的話,就可以定義一個(gè)類似 GET /notes/all Notes.show(id:0) 的路由聲明。這樣暴露出來(lái)的 URI 更加簡(jiǎn)潔和易于記憶。

在路由文件中的路由聲明是按照從上到下的優(yōu)先級(jí)來(lái)進(jìn)行匹配的。比較具體的 URI 模式應(yīng)該放在比較通用的模式之前。對(duì)于靜態(tài)文件,可以通過一個(gè)特殊的動(dòng)作方法 staticDir 進(jìn)行聲明。比如 GET /files staticDir:files 就聲明了 files目錄中包含的是靜態(tài)文件。

在介紹完 HTTP 路由之后,下面介紹 Play 框架獨(dú)特的無(wú)狀態(tài)的體系結(jié)構(gòu)。

無(wú)狀態(tài)的體系結(jié)構(gòu)

HTTP 協(xié)議本身就被設(shè)計(jì)成無(wú)狀態(tài)的,采用請(qǐng)求 / 響應(yīng)的模式。不同的請(qǐng)求之間并不存在相互關(guān)系。但是這種架構(gòu)模式在開發(fā)某些 Web 應(yīng)用的時(shí)候不是很方便。有些應(yīng)用要求用戶進(jìn)行認(rèn)證登錄之后才能進(jìn)行某些操作。同樣的 URL,認(rèn)證和未認(rèn)證用戶看到的內(nèi)容是不同的。而且用戶認(rèn)證成功之后,他應(yīng)該在一段時(shí)間內(nèi)保持這種認(rèn)證狀態(tài)。否則的話,用戶每次都需要輸入用戶名和密碼才能訪問受限的內(nèi)容。對(duì)于這種情況,很多 Web 開發(fā)框架提供了會(huì)話的支持,允許應(yīng)用保存一些與會(huì)話相關(guān)的數(shù)據(jù)。Java Servlet 規(guī)范中的 javax.servlet.http. HttpSession就是一種會(huì)話的接口。應(yīng)用的服務(wù)器會(huì)負(fù)責(zé)維護(hù)每個(gè)會(huì)話相關(guān)的數(shù)據(jù)。這些數(shù)據(jù)可以通過一個(gè)會(huì)話 ID 來(lái)進(jìn)行標(biāo)識(shí)。這個(gè)標(biāo)識(shí)會(huì)利用瀏覽器的 cookie 機(jī)制保存在瀏覽器端,也可以作為請(qǐng)求 URL 的參數(shù)來(lái)傳遞。服務(wù)器端通過此標(biāo)識(shí)來(lái)識(shí)別每個(gè)會(huì)話。在處理相應(yīng)的請(qǐng)求的時(shí)候,就可以根據(jù)會(huì)話 ID 來(lái)獲取保存在服務(wù)器端上的會(huì)話數(shù)據(jù)。會(huì)話機(jī)制的問題是會(huì)影響應(yīng)用的可伸縮性。如果一個(gè)應(yīng)用使用多臺(tái)服務(wù)器的話,就需要額外的機(jī)制來(lái)保證同一用戶在不同機(jī)器上面的會(huì)話是同步的。而無(wú)狀態(tài)的實(shí)現(xiàn)則不存在這個(gè)問題,對(duì)于某一個(gè)請(qǐng)求,由不同機(jī)器來(lái)處理的結(jié)果都是相同的。

Play 框架的設(shè)計(jì)架構(gòu)就是無(wú)狀態(tài)的。它沒有提供服務(wù)器端的機(jī)制用來(lái)維護(hù)跨多個(gè)請(qǐng)求的數(shù)據(jù)。如果確實(shí)需要保存這樣的數(shù)據(jù)的話,可以考慮下面幾種方案:

◆保存在 Session 或 Flash 作用域中。Play 框架中仍然有會(huì)話的機(jī)制,但是并沒有提供在服務(wù)器端保存會(huì)話數(shù)據(jù)的能力。會(huì)話數(shù)據(jù)是保存在瀏覽器的 cookie 中的,由瀏覽器在每次請(qǐng)求的時(shí)候自動(dòng)發(fā)送。通過這種方式來(lái)達(dá)到維護(hù)會(huì)話數(shù)據(jù)的目的。由于會(huì)話數(shù)據(jù)是保存在 cookie 中,其大小是有限制的,一般不能超過 4K 字節(jié),而且只能保存字符串類型的數(shù)據(jù)。Flash 作用域和會(huì)話一樣,也是通過 cookie 來(lái)保存的。所不同的是,F(xiàn)lash 作用域中的數(shù)據(jù)只在下次請(qǐng)求中是有效的。

◆保存在持久化的數(shù)據(jù)存儲(chǔ)中,如數(shù)據(jù)庫(kù)中。如果需要在多個(gè)請(qǐng)求中使用同一個(gè)領(lǐng)域?qū)ο蟮脑挘梢园堰@個(gè)對(duì)象的 ID 保存在 Session 或 Flash 作用域中,而在控制器動(dòng)作方法中使用此 ID 來(lái)從數(shù)據(jù)庫(kù)中查詢相應(yīng)的對(duì)象。

◆保存在暫時(shí)性數(shù)據(jù)存儲(chǔ)中,如緩存中。Play 框架內(nèi)置了緩存的支持,通過調(diào)用類 play.cache.Cache 就可以對(duì)緩存進(jìn)行操作。與使用持久化存儲(chǔ)類似,緩存中的鍵的值可以保存在 Session 或 Flash 作用域中。

對(duì)于熟悉了 Java Servlet 規(guī)范的開發(fā)人員來(lái)說(shuō),需要一些時(shí)間來(lái)適應(yīng) Play 框架的這種無(wú)狀態(tài)的體系結(jié)構(gòu)。不過這種結(jié)構(gòu)對(duì)于應(yīng)用的可伸縮性來(lái)說(shuō),確實(shí)是非常有好處的。

介紹完無(wú)狀態(tài)的體系結(jié)構(gòu)之后,下面介紹一些其它話題。

其它話題

測(cè)試

Play 框架對(duì)應(yīng)用的測(cè)試也提供了良好的支持。Play 框架一共支持三種類型的測(cè)試,分別是單元測(cè)試、功能測(cè)試和界面測(cè)試。單元測(cè)試主要用來(lái)測(cè)試應(yīng)用的模型層代碼。單元測(cè)試用例的 Java 類繼承自 play.test.UnitTest ,可以使用 JUnit 4 提供的標(biāo)注和斷言。功能測(cè)試主要用來(lái)測(cè)試應(yīng)用的控制層代碼。功能測(cè)試用例的 Java 類繼承自 play.test.FunctionalTest。在測(cè)試用例中,可以通過 GET()、POST()、PUT()、DELETE() 和 makeRequest()等方法來(lái)發(fā)出 HTTP 請(qǐng)求,也可以直接調(diào)用控制器中的動(dòng)作方法。除此之外,還可以使用一些與 HTTP 響應(yīng)相關(guān)的斷言。如 assertStatus()、assertContentType() 和 assertHeaderEquals()分別用來(lái)驗(yàn)證 HTTP 狀態(tài)代碼、內(nèi)容類型和 HTTP 頭。界面測(cè)試使用 Selenium 工具來(lái)進(jìn)行。開發(fā)人員可以使用 Selenium 的語(yǔ)法來(lái)編寫測(cè)試用例,也可以使用 Play 框架提供的 #{selenium}標(biāo)簽。

在進(jìn)行測(cè)試的時(shí)候,需要準(zhǔn)備一些測(cè)試數(shù)據(jù)。測(cè)試數(shù)據(jù)可以用 YAML 的格式保存在文本文件中,并通過 play.test.Fixtures.laod()方法來(lái)加載這些數(shù)據(jù)到數(shù)據(jù)庫(kù)中。當(dāng)測(cè)試結(jié)束之后,可以通過 deleteAll()方法來(lái)刪除這些數(shù)據(jù)。

在測(cè)試的時(shí)候,需要用 play test命令以測(cè)試模式啟動(dòng)應(yīng)用,再用瀏覽器訪問 http://localhost:9000/@tests進(jìn)行測(cè)試。

任務(wù)調(diào)度

在 Web 應(yīng)用開發(fā)中,有時(shí)候會(huì)需要定期執(zhí)行一些調(diào)度任務(wù),比如數(shù)據(jù)庫(kù)備份和數(shù)據(jù)同步等。這些任務(wù)不是通過 HTTP 請(qǐng)求來(lái)觸發(fā)的,而是定時(shí)執(zhí)行的。Play 框架提供了內(nèi)置的任務(wù)調(diào)度支持的能力。創(chuàng)建新任務(wù)的時(shí)候,只需要繼承自 play.jobs.Job類,并覆寫 doJob()方法即可。如果要?jiǎng)?chuàng)建的任務(wù)有返回結(jié)果的話,覆寫 doJobWithResult()方法即可。任務(wù)創(chuàng)建完成之后,可以選擇不同的調(diào)度方式。一種方式是在應(yīng)用啟動(dòng)的時(shí)候執(zhí)行一次。只需要在任務(wù)的 Java 類上添加標(biāo)注 @OnApplicationStart即可。對(duì)于定期執(zhí)行的任務(wù),Play 框架提供了兩個(gè)標(biāo)注:一個(gè)是 @Every,用來(lái)按照固定的時(shí)間間隔調(diào)度任務(wù),如 @Every("1h")聲明任務(wù)每個(gè)小時(shí)執(zhí)行一次;另外一個(gè)是 @On,用來(lái)聲明描述調(diào)度策略的 CRON 表達(dá)式。

安全

Play 框架提供了對(duì) Web 應(yīng)用安全性方面的支持,可以防范一些常見的攻擊方式。前面提到過,Play 框架中的會(huì)話數(shù)據(jù)是保存在瀏覽器的 cookie 中的。這些數(shù)據(jù)是經(jīng)過簽名的,可以防止被惡意攻擊者所篡改。應(yīng)用中的重要數(shù)據(jù)也不應(yīng)該保存在會(huì)話中。Play 框架中的模板在輸出 HTML 內(nèi)容的時(shí)候,會(huì)自動(dòng)對(duì)內(nèi)容進(jìn)行轉(zhuǎn)義,可以防范跨站點(diǎn)腳本攻擊。對(duì)于 SQL 注入攻擊,開發(fā)人員應(yīng)該盡量使用提供的 find()方法來(lái)查詢領(lǐng)域?qū)ο?。?duì)于自己創(chuàng)建的查詢語(yǔ)句,應(yīng)該在語(yǔ)句中使用占位符并進(jìn)行參數(shù)綁定,而不是通過字符串相加的方式來(lái)創(chuàng)建。為了防范跨站點(diǎn)請(qǐng)求偽造,Play 框架中的控制器的動(dòng)作方法都可以使用 checkAuthenticity()方法來(lái)聲明調(diào)用此方法時(shí)的請(qǐng)求中必須包含合法的令牌。這個(gè)令牌用來(lái)確保當(dāng)前請(qǐng)求是由應(yīng)用自身發(fā)出的,而不是被偽造的。通過 session.getAuthenticityToken()方法可以生成一個(gè)只對(duì)當(dāng)前會(huì)話有效的令牌,需要在請(qǐng)求的時(shí)候附帶此令牌。如果是通過頁(yè)面上的表單來(lái)提交請(qǐng)求的話,Play 框架也提供了一個(gè)標(biāo)簽 #{authenticityToken /}用來(lái)生成一個(gè)包含了令牌的隱藏域,可以直接在模板中使用。

總結(jié)

Play 框架作為一個(gè)優(yōu)秀的 Java Web 應(yīng)用開發(fā)框架,可以幫助開發(fā)人員快速高效的構(gòu)建 Web 應(yīng)用。它為開發(fā)人員提供了一個(gè)良好的基礎(chǔ)架構(gòu),并屏蔽了很多底層的實(shí)現(xiàn)細(xì)節(jié)。開發(fā)人員可以用一個(gè)簡(jiǎn)單的視角來(lái)看待 Web 應(yīng)用開發(fā),而不需要關(guān)心過多的細(xì)節(jié)。Web 開發(fā)人員可以熟悉 Play 框架,并在開發(fā)中選用這個(gè)框架。

【編輯推薦】

  1. Java Web應(yīng)用開發(fā)中的一些概念
  2. 理想的Java Web開發(fā)框架
  3. Java Web Servlet學(xué)習(xí)淺談
  4. 新一代Java Web開發(fā)框架JSF框架
  5. 現(xiàn)代Java Web開發(fā)框架分析

 

責(zé)任編輯:佚名 來(lái)源: developerworks
相關(guān)推薦

2011-11-08 10:36:42

Java

2009-05-12 09:54:09

JavaRestCoC

2018-05-04 15:27:22

Spring Boo Web開發(fā)

2024-10-14 10:12:37

Python Web框架Python

2012-01-13 11:02:27

JavaWebOpenXava

2011-12-16 09:49:38

Java

2011-09-09 17:01:42

框架

2024-09-29 16:36:16

2020-03-30 09:00:00

WebJava框架

2012-02-22 15:51:22

JavaPlay Framew

2009-09-03 16:52:44

Java Web開發(fā)框

2009-06-18 12:06:30

Java Web開發(fā)框

2012-02-23 13:13:00

JavaPlay Framew

2020-07-24 07:00:00

Laravel框架Web應(yīng)用開發(fā)

2019-11-25 11:20:08

FlutterWeb應(yīng)用軟件開發(fā)

2009-05-08 09:32:27

JavaWeb編程框架

2010-04-20 09:14:33

Struts

2023-06-27 08:34:32

2009-06-22 11:50:00

J2EE Web應(yīng)用快速開發(fā)

2016-01-27 09:39:13

JoobyJava Web流程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)