如果你剛開始考慮應用portal解決方案,或者想了解把一個新的或現有的JSF應用整合進一個portal環境有多容易,那麼本文絕對值得你仔細研讀.
在過去幾年中,portals無論是在企業還是在增強的portlet 2.0(JSR 286)規範中都得到了長足發展.新2.0版本的portlets在聚合不同的應用,並將其呈現在同一個頁面的不同窗口方面賦於開發人員很大的自由.此外,它還提供了認證功能,成熟的個性化特性和更好的處理AJAX的現成方法.
JSR 301 portlet橋接規範(portlet bridge specification)的出現,使我們具備了運行JSF應用的標準方式,不論portlets版本是1.0還是2.0.portlet橋(bridge)可以支配portal的Action/Render範式適當地處理JSF的生命周期.本教程將主要向你展示配置與開發JSF portlet是多麼容易的一件事情,同時還會介紹新的JBoss Portlet Container 2.0及其一些很酷的新特性.
本文是由三部分組成的系列文章的第一篇.該系列文章從基本的JSF portlet和portal知識一直講到portlet環境中的AJAX和Seam的高級用法.
現在準備開始吧!
項目安裝開發工具:
要想成功實踐文中的範例就要下載最新版本的Maven(我用的是2.0.9版本).
安裝 Maven 2.0.9 .
設置 Maven二進位版本的環境變數.
例子中用到的伺服器和二進位版本:
JBoss Portal』s Portlet Container 2.0
JBoss Portlet Bridge Beta3
目前,JBoss Portlet Bridge是JSR 301規範的唯一實現,它允許你運行JSF、RichFaces和Seam的任意組合.你項目的Maven配置可安排下載打包在一起的JBoss AS和JBoss Portlet Container 2.0,如果你想分別下載它們,可以在此處找到這些文件.否則,就給Maven幾分鐘讓它去自行下載適當的文件.
注意——在當前的2.6.5.SP1版本的JBoss Portal中同樣可以運行這個portlet ,我在本文中使用了JBoss Portlet Container 2.0,但是橋(bridge)在兩者中都能工作.你可通過此處了解令其可在任意版本的JBoss Portal中運行的配置方法.
下述Maven原型(Maven archetype)是創建項目的一種簡易方式,可以快速建立並運行一個啟始項目(或者模板項目).一旦你運行了這些命令,就可獲得實踐本文示例所需的一切文件.
打開一個終端窗口並運行如下指令:
mvn archetype:generate -DarchetypeGroupId=org.jboss.portletbridge.archetypes -DarchetypeArtifactId=1.2-basic -DarchetypeVersion=1.0.0.B3 -DgroupId=org.whatever.project -DartifactId=myprojectname -DarchetypeRepository=http://repository.jboss.org/maven2/ -Dversion=1.0.0.B3 |
現在,找到你的新建項目所在文件目錄(如果你使用的跟上面的例子一樣,那麼目錄名就應該是 「myprojectname」),瀏覽其中剛剛創建的所有文件,你將會看到一個基本Maven文件結構,其中帶有適用於本文範例的源碼.現在你就可以打開最喜歡的IDE環境,引入這個Maven項目了.
Portlet橋配置要求
從現在開始的開發過程更像是在Servlet世界中開發JSF應用,不同之處在於:處理類似單點登錄這樣的問題;諸如命名空間(namespacing)這樣的需要portletContext 和訪問變數的問題;以及portlet中像「Help」和「Edit」這樣的窗口模式問題.我不想在本文講述過多portlet的細節,但我會提供進行基本開發的必要信息.如果你想了解更多portlets的信息,請參考JSR 168或JSR 286規範說明.
JBoss Portlet Bridge比較酷的一點在於它不是一個portlet,它只是portlet和JSF之間的媒介.而你的JSF應用則是個portlet,不過除了 WEB-INF目錄下3到4個額外的xml文件和關於bridge的Jar包外,它的其餘部分與你的Servlet版本的應用毫無二致.下面幾個配置文件是主要區別:
portlet.xml
<portlet> ...v <portlet-class> javax.portlet.faces.GenericFacesPortlet </portlet-class> <init-param> <name>javax.portlet.faces.defaultViewId.view</name> <value>/home.xhtml</value> </init-param> <init-param> <name>javax.portlet.faces.defaultViewId.edit</name> <value>/jsf/edit.xhtml</value> </init-param> <init-param> <name>javax.portlet.faces.defaultViewId.help</name> <value>/jsf/help.xhtml</value> </init-param> ... </portlet> |
web.xml
<context-param> <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name> <param-value> org.jboss.portletbridge.application.FaceletPortletViewHandler </param-value> </context-param> <context-param> <param-name>javax.portlet.faces.renderPolicy</param-name> <param-value> ALWAYS_DELEGATE </param-value> </context-param> |
faces-config.xml
<application> <view-handler> org.jboss.portletbridge.application.PortletViewHandler </view-handler> <state-manager>org.jboss.portletbridge.application.PortletStateManager</state-manager> </application> |
由於上述設置已經應用在你剛剛設定的Maven原型中,因此現在我們就可以編譯項目,並在JBoss Portal上部署它了.
運行demo程序
編譯新項目,並通過如下兩個步驟完成部署:
步驟1: mvn install cargo:start -Premote-portal -Dpc20
這行命令將會花上幾分鐘去下載打在一起的server portal包,在進行下一步驟之前,請耐心等待直至看到如下內容:
這行命令將會花上幾分鐘去下載打在一起的server portal包,在進行下一步驟之前,請耐心等待直至看到如下內容:
*注意——在server啟動前你還會看到一個PortletException ,這很正常,它也是Portlet Container 2.0示例FailDuringInitPortlet的一部分.
接下來打開另外一個終端窗口,找到JSF portlet項目的根目錄,並運行:
步驟2: mvn cargo:deploy -Premote-portal -Dpc20
命令行參數通知cargo你正在運行的portal版本和JBoss Portal包所在位置.這個例子同樣可以運行於遵從JSR 168的最新版本JBoss Portal 2.6.5.SP1中.如果想了解更多Maven命令及相關信息,你可以參考JBoss Portlet Bridge文檔.要查看已部署的JSF portlet情況可訪問如下鏈接:http://localhost:8080/simple-portal/demo/jsr-301.jsp.
JSF Portlet開發
現在讓我們來了解將portlet和JSF聯繫在一起的技術.
把你的portlet視作一個普通的Web應用
當把你的應用視作servlet端的Web應用時,portlet橋是透明的.作為portlet開發人員,一種很好的做法是偶爾仔細檢查一下你的應用以確保正在進行的開發沒有擴大的趨勢,它將運行在一個portal環境中.要查看此demo應用,或者任何已部署的帶有橋的應用,可以訪問
http://localhost:8080/JSFRIPortlet/home.jsf.命名空間
在portal環境中橋可以處理JSF的命名空間組合.當你需要在JSF/xhtml標記中使用元素id時,正常情況下在顯示的標記中你所看到的是類似『form1:myBtn』的代碼,而如今在橋命名空間中你所看到的將是象:jbpns_2fdefault_2fNews_2fStories_2fStoryTemplateWindow12snpbj:_viewRoot:form1:myBtn
這樣的標記.
要克服這一點,你可以在你的Facelets頁中應用下面的表達式,來為你的javascript代碼預先設定命名空間:document.getElementById('#{facesContext.externalContext.response.namespace}the_rest_of_JSF_ID');
請注意,使用了portletResponse,一旦你試圖在servlet應用端查看這個頁面的時候就會得到一個異常.為避免這種情況的發生,你需要在你的後台Bean(backing bean)中檢查響應的類型,並為UI分配一個新的、「安全的」命名空間變數.
preserveActionParams
當你的web.xml文件中preserveActionParams值被設置為TRUE時,橋必須負責維護在portlet動作請求期間指派的任意參數,它們被保存在「橋請求域(bridge request scope)」中.當這個屬性沒有出現或者值為FALSE時,只在portlet請求作用域維護動作的請求參數.
<init-param> <param-name>javax.portlet.faces.preserveActionParams</param-name> <param-value>true</param-value> <init-param> |
在你的Facelets頁面中應用類似 #{request.yourParam}這樣的代碼可以利用這一設置.
排除橋請求域中的屬性
當你的應用在每一次請求上都要使用請求屬性而你又不想在擴展的橋請求作用域中管理特殊的屬性時,你就必須在你的faces-config.xml文件中使用如下的配置了.下面你會看到任何命名空間為foo.bar的屬性或者是以foo.baz(通配符)打頭的屬性都會被從橋請求作用域中排除,這些屬性只能用在每一次請求當中:
<application> <application-extension> <bridge:excluded-attributes> <bridge:excluded-attribute>foo.bar</bridge:excluded-attribute> <bridge:excluded-attribute>foo.baz.*</bridge:excluded-attribute> </bridge:excluded-attributes> </application-extension> </application> |
或者你可以使用javax.portlet.faces.annotation.ExcludeFromManagedRequestScope
j註解,對你不想包含在請求中的對象類進行註解,也可以達到同樣的效果.
正如你所看到的,JSR 301規範不僅是的把已存在的JSF web應用建立成portlet更加容易,還提供給開發人員一種管理和處理JSF和portlets差異的方式.不過,規範目前仍處於頻繁地評審和修訂階段.寫這篇文章時最新的公開版本是Early Draft Review 3,但是在JSR 301專家組內部,對此修訂版本又已經有很多改進了,對橋比較重大的改進是在下一個JBoss Portlet Bridge版本(Beta 4)中將會實現的portlet模式導航和狀態.
查看英文原文:Developing Portlets using JSF, Ajax, and Seam (Part 1 of 3) .
[火星人 ] 應用JSF、Ajax和Seam開發Portlets(1)已經有581次圍觀