侯燕玫
摘要:為了方便用戶使用,多數(shù)網(wǎng)站都采用了頁(yè)面導(dǎo)航。而在JSF2.0中,為了方便進(jìn)行頁(yè)面導(dǎo)航,增加了RESTful導(dǎo)航的內(nèi)容,這很大程度的改善了JSF框架。該文著重介紹了JSF2.0中的RESTful導(dǎo)航方式,并對(duì)其導(dǎo)航處理進(jìn)行了分析。
關(guān)鍵詞:導(dǎo)航;重定向;表述性狀態(tài)轉(zhuǎn)移
中圖分類號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2012)07-1546-02
Exploring the RESTful Navigation Way in JSF2.0
HOU Yan-mei
(Dept. of Information,Capital University of Economic and Business, Beijing 100070, China)
Abstract: In order to facilitate the user use, many web sites are adopting page navigation. And in JSF2.0, in order to facilitate assessment page navigation, increased the RESTful navigation elements, which greatly improved the JSF framework. This paper introduces the RESTful navigation way in JSF2.0, and analyzed the navigation processing.
Key words: navigation; redirection; RESTful
2009年基于組件的框架的JSF2.0正式發(fā)布了,伴隨而來的是更簡(jiǎn)單的操作,更完美的整合,更規(guī)范的標(biāo)準(zhǔn),以及對(duì)更多技術(shù)的支持等等。而在這種種變化中,不難發(fā)現(xiàn)Web頁(yè)面導(dǎo)航也在發(fā)生著巨大的變化。導(dǎo)航最原始的定義是通過綁定到超媒體信息上的超鏈接在頁(yè)面間跳轉(zhuǎn)的動(dòng)作。而在今天網(wǎng)絡(luò)信息爆炸的情況下,導(dǎo)航的作用已不能局限于頁(yè)面間的跳轉(zhuǎn),還包括程序信息的傳遞和轉(zhuǎn)移。JSF提供了多種導(dǎo)航方式,尤其是新發(fā)布的JSF2.0,其更加豐富了頁(yè)面導(dǎo)航方式的種類。而在多種導(dǎo)航方式中最引起人們注意的還是RESTful的導(dǎo)航方式。
默認(rèn)情況下,JSF應(yīng)用程序像服務(wù)器產(chǎn)生一系列的POST請(qǐng)求。每一個(gè)POST請(qǐng)求包含格式化的數(shù)據(jù)。這對(duì)于需要用戶輸入信息的應(yīng)用程序是很有意義的。但是我們知道,在許多程序中,我們并不需要輸入任何信息,只是通過簡(jiǎn)單的單擊超級(jí)鏈接或是按鈕來實(shí)現(xiàn)頁(yè)面間的跳轉(zhuǎn)。還有另外重要的一點(diǎn),為了通過重訪URL能夠返回到同一頁(yè)面,相應(yīng)的鏈接都應(yīng)該是可標(biāo)示的,所有的頁(yè)面都是緩存的。但是,POST請(qǐng)求在標(biāo)示或者緩存上是無效的,這為創(chuàng)建高效的網(wǎng)頁(yè)造成了很大的阻礙。
1 RESTful簡(jiǎn)介
為了解決這個(gè)問題,JSF2.0提出了一種被稱為REST(Representational State Transfer)的風(fēng)格的設(shè)計(jì)理念,它倡導(dǎo)頁(yè)面應(yīng)該像HTTP事先預(yù)想的那樣工作。查找應(yīng)該使用GET請(qǐng)求。PUT,POST和DELETE請(qǐng)求應(yīng)該用來創(chuàng)建、修改和刪除。
GET請(qǐng)求用來查找信息,如http://myserver.com/animals?kind=fish,這即是一種RESTful。但是GET請(qǐng)求不能用來更新信息。如為動(dòng)物增加一個(gè)新的種類就是不恰當(dāng)?shù)?。GET請(qǐng)求應(yīng)該是等冪的。簡(jiǎn)單的說就是指第二次提出請(qǐng)求與第一次提出應(yīng)該是沒有什么不同的。但對(duì)于動(dòng)物來說提出兩次請(qǐng)求就是增加兩種動(dòng)物。這也說明在一個(gè)大的應(yīng)用程序中,POST請(qǐng)求在上下文是非常恰當(dāng)?shù)?。因此,RESTful網(wǎng)頁(yè)需要共享部分POST請(qǐng)求,僅僅依靠GET請(qǐng)求是不可能完成全部任務(wù)的。
一般的,JSF對(duì)于產(chǎn)生或是使用URL并沒有一個(gè)標(biāo)準(zhǔn)的機(jī)制,但是從JSF2.0開始,RESTful支持GET請(qǐng)求。我們將在下面的段落中詳細(xì)介紹。
2 RESTful中的GET請(qǐng)求
2.1視圖參數(shù)
http://myserver.com/ animals?kind=fish語句中,動(dòng)物的種類名稱kind被作為查詢參數(shù)。當(dāng)服務(wù)器端收到該請(qǐng)求時(shí),參數(shù)值被轉(zhuǎn)換為相應(yīng)的bean值,這就是使用視圖參數(shù)的目的。
在頁(yè)面的頂端加上如下標(biāo)簽:
處理請(qǐng)求時(shí),種類kind的值被傳遞給animals類的setCurrentKind()方法。
JSF頁(yè)面可以有很多視圖參數(shù)。和其他請(qǐng)求參數(shù)一樣,視圖參數(shù)可以被轉(zhuǎn)換和驗(yàn)證。
2.2 GET請(qǐng)求鏈接
使用h:commandButton和h:commandLink標(biāo)記會(huì)產(chǎn)生POST請(qǐng)求,為了使用戶能夠用GET請(qǐng)求進(jìn)行導(dǎo)航,需要通過使用h:button或是h:link標(biāo)記在頁(yè)面添加發(fā)送GET請(qǐng)求的按鈕或是鏈接。
對(duì)于這些請(qǐng)求,需要控制目的視圖ID和查詢參數(shù)。目的視圖ID由outcome屬性確定,而其屬性值可以是一個(gè)固定值,如:
或者也可以選擇提供一個(gè)值表達(dá)式:
此時(shí),getOutcome()方法被激活并一定會(huì)產(chǎn)生一個(gè)結(jié)果字符串。結(jié)果字符串以普通方式放入到導(dǎo)航處理中,產(chǎn)生目標(biāo)視圖ID。
GET請(qǐng)求鏈接中的outcome屬性在頁(yè)面呈現(xiàn)之前被計(jì)算,鏈接被嵌入到頁(yè)面中。
2.3指定請(qǐng)求參數(shù)
在大多數(shù)情況下,向服務(wù)器發(fā)送一個(gè)請(qǐng)求而沒有任何請(qǐng)求參數(shù)是沒有什么意義的。如果沒有請(qǐng)求參數(shù),服務(wù)器就得不到上下文數(shù)據(jù),也無法根據(jù)上下文數(shù)據(jù)為客戶創(chuàng)建“個(gè)性化”的響應(yīng)。
GET請(qǐng)求鏈接的參數(shù)來源于:
1)結(jié)果字符串
2)視圖參數(shù)
3)嵌入在f:param標(biāo)簽中
當(dāng)結(jié)果字符串作為請(qǐng)求參數(shù)時(shí),導(dǎo)航處理器從目標(biāo)視圖ID結(jié)果中取下原始參數(shù)并將其計(jì)算后的結(jié)果添加為新的參數(shù)。如:
示例中,導(dǎo)航處理首先會(huì)從取下outcome的參數(shù)index?q=1,將其計(jì)算。由于JSF中規(guī)定:
1)如果outcome屬性值沒有文件擴(kuò)展名,附加上當(dāng)前視圖的擴(kuò)展名。
2)如果outcome屬性值不是以/開頭,首先考慮當(dāng)前視圖的路徑。
這里,我們假設(shè)當(dāng)前視圖擴(kuò)展名為.xhtml,則計(jì)算的結(jié)果為/index.xhtml?q=1,將其添加為目標(biāo)視圖ID的新的outcome的值。
當(dāng)outcome屬性的值是復(fù)合參數(shù)時(shí),要使用分隔符&。如:
GET請(qǐng)求的參數(shù)也可以由視圖參數(shù)提供,對(duì)于查詢語句中包含的參數(shù),可以簡(jiǎn)單的添加一條語句:
這樣即可實(shí)現(xiàn)一個(gè)頁(yè)面的所有視圖參數(shù)成功傳遞到另一個(gè)頁(yè)面,這一點(diǎn)也是RESTful應(yīng)用中的普遍要求。
當(dāng)下一個(gè)頁(yè)面所需要的參數(shù)與當(dāng)前頁(yè)面參數(shù)并不完全一致時(shí),JSF提供了f:param標(biāo)簽,它可以覆蓋這些視圖參數(shù)。如:
這樣新設(shè)置的quizBean.currentProblem + 1的值便替代了上一個(gè)頁(yè)面中提供的q的取值。
2.4重定向鏈接
JSF可以實(shí)現(xiàn)重定向到新的視圖。JSF發(fā)送HTTP重定向到客戶端。重定向響應(yīng)告訴客戶端下一個(gè)頁(yè)面使用哪個(gè)URL。之后客戶端產(chǎn)生GET請(qǐng)求獲得相應(yīng)的URL。即:一個(gè)重定向鏈接,也是一個(gè)GET請(qǐng)求。有語句如:
該語句表示其實(shí)現(xiàn)重定向的同時(shí),還可以傳遞所有的視圖參數(shù)到下一個(gè)頁(yè)面。但是因?yàn)橹囟ㄏ蛘Z句中不能使用f:param標(biāo)簽,所以我們可以在相應(yīng)的XML配置文件中指定導(dǎo)航規(guī)則,使用include-view-params屬性和嵌入式的view-param標(biāo)簽:
因?yàn)橹囟ㄏ蛟试S瀏覽器更新地址,一般作為書簽的頁(yè)面可以使用redirect元素。
3結(jié)束語
對(duì)于簡(jiǎn)單的應(yīng)用程序,不需要使用導(dǎo)航規(guī)則。命令按鈕和鏈接可以返回簡(jiǎn)單的結(jié)果來指定下一次呈現(xiàn)的頁(yè)面,然而,如果有更復(fù)雜的需求,使用JSF框架是必需的工具,使用恰當(dāng)?shù)膶?dǎo)航規(guī)則是必要的。
而在多種導(dǎo)航方式中,RESTful導(dǎo)航將信息顯示在地址欄中,盡管對(duì)于有些信息內(nèi)容這樣是不安全的,但這樣使用get請(qǐng)求的頁(yè)面能夠一個(gè)單獨(dú)的可標(biāo)示的標(biāo)簽加到收藏夾中,而在JSF中POST請(qǐng)求的頁(yè)面是不可以這樣的。
同時(shí),注意到GET請(qǐng)求鏈接中的outcome屬性是在頁(yè)面呈現(xiàn)之前就已經(jīng)被計(jì)算,并且鏈接已被嵌入到頁(yè)面中。利用這個(gè)特點(diǎn),可以便捷高效的實(shí)現(xiàn)頁(yè)面間的跳轉(zhuǎn),尤其是當(dāng)一個(gè)頁(yè)面到另一個(gè)頁(yè)面的跳轉(zhuǎn)是必然結(jié)果時(shí)。如在很多類型的網(wǎng)站中,用戶想要更好的使用網(wǎng)站都要進(jìn)行登錄操作,用戶登錄后是要顯示網(wǎng)站首頁(yè)的,這時(shí)在登錄成功頁(yè)面嵌入自動(dòng)跳轉(zhuǎn)到首頁(yè)的鏈接,這樣登錄后的即可快速顯示首頁(yè)內(nèi)容。當(dāng)網(wǎng)頁(yè)內(nèi)容較多需要分頁(yè)顯示時(shí),可以在“下一頁(yè)”的鏈接中采用GET請(qǐng)求,這樣可以直接將下一頁(yè)的內(nèi)容嵌入到當(dāng)前頁(yè)中,將內(nèi)容整合在一起,可以保持用戶閱讀的流暢性。
參考文獻(xiàn):
[1]吳慶濤,王成良. ASP.NET2.0的Web頁(yè)面導(dǎo)航方式比較與選擇[J].電腦知識(shí)與技術(shù):學(xué)術(shù)交流, 2007,3(14).
[2] Geary D,Horstmann C.JavaSever Faces核心編程[M].北京:電子工業(yè)出版社,2005.
[3]楊俊生,唐琳.JSP開發(fā)技術(shù)[M].北京:清華大學(xué)出版社,2011.
[4]繆勇.JSP網(wǎng)絡(luò)開發(fā)逐步深入[M].北京:清華大學(xué)出版社,2010.