隨著CDI的portlet集成庫的放出,我們可以在JSF portlet中通過Portlet橋,利用CDI帶來的巨大優點。
怎麼使用?
除了通常的Portlet橋依賴以外,在portlet中使用CDI還需要:
在項目中添加以下依賴包:
<dependency> <groupId>org.gatein</groupId> <artifactId>cdi-portlet-integration</artifactId> <version>1.0.2.Final</version> </dependency> <dependency> <groupId>org.gatein</groupId> <artifactId>cdi-portlet-integration</artifactId> <version>1.0.2.Final</version> </dependency>
在WAR包的WEB-INF目錄下,新增一個空的beans.xml文件。
在portlet.xml中,添加以下過濾器的定義:
filter> <filter-name>PortletCDIFilter</filter-name> <filter-class>org.gatein.cdi.PortletCDIFilter</filter-class> <lifecycle>ACTION_PHASE</lifecycle> <lifecycle>EVENT_PHASE</lifecycle> <lifecycle>RENDER_PHASE</lifecycle> <lifecycle>RESOURCE_PHASE</lifecycle> </filter> <filter-mapping> <filter-name>PortletCDIFilter</filter-name> <portlet-name>yourPortletName</portlet-name> </filter-mapping> <filter> <filter-name>PortletCDIFilter</filter-name> <filter-class>org.gatein.cdi.PortletCDIFilter</filter-class> <lifecycle>ACTION_PHASE</lifecycle> <lifecycle>EVENT_PHASE</lifecycle> <lifecycle>RENDER_PHASE</lifecycle> <lifecycle>RESOURCE_PHASE</lifecycle> </filter> <filter-mapping> <filter-name>PortletCDIFilter</filter-name> <portlet-name>yourPortletName</portlet-name> </filter-mapping>PortletCIDFilter
只包括接收到的portlet請求可以使用CDI。如果你的程序代碼框架需要處理portlet響應,則需要使用即可以處理請求又能夠處理響應的PortletCDIResponseFilter來代替。
@RequestScoped
使用此作用域的bean在portlet中的行為與常規的JSF不同。在portelt中,設定為ActionRequest的bean類,其中任何修改的內容都無法到達portlet生命周期的其他階段,包括RenderRequest。所以,建議不要一個JSF的portlet中的CDI bean類中,使用此作用域。推薦使用GateIn 3.6.0 Final中新增的@PortletLifecycleScoped。這個新的作用域允許為了渲染portlet,在一個action裡面,設置你想要的數據;並且可以從ActionRequest到RenderRequest階段保持Bean的實體。
@ConversationScoped
臨時會話跟一個標記為@RequestScoped的Bean類具有相同的行為。因此,不推薦為渲染JSF portlet而讓數據可用。
預計JSF portlet會提供對長會話的支持,但是,仍然有一些問題需要注意:
在RenderRequest階段,結束一個長會話時,將導致接下來的portlet渲染出現一個ConversationNotFoundException。這是因為portlet渲染所觸發的url,包含有cid參數;CDI據此參數確定是創建一個長會話還是一個臨時會話。如果會話終結時參數仍存在,那麼在下次portlet渲染時,將會試圖重新啟動結束該會話。
使用AJAX來開始或者結束一個長會話是不錯的選擇。我們需要重新渲染包括URL在內的所有portlet組件,從而讓CDI知道我們點擊一個鏈接或者按鈕所使用的會話。如果不更新URL,鏈接有可能被賦予一個舊的cid值,從而導致ConversationNotFoundException,或者直接就沒有cid,導致所有的調用都是臨時會話。
GateIn Scopes
最近,在GateIn 3.6.0 Final版本中提供了兩個新的作用域:@PortletLifecycleScoped與@PortletRedisplayScoped。這兩個作用域在JSF portlet中非常實用,並且可以跟其他的CDI作用域的bean類進行無縫交互。這些作用域將在GateIn的博客文章中展開討論。
希望這篇文章能夠指出在JSF portlet開發中,使用CDI時的一些常見陷阱。