portlet session共享

一,問題描述
用戶會話session是servet規範中標準的對象,它代表了用戶活動的生命週期,因此在我們以往的web開發中,經常將用戶信息放置到session對象中。然而隨着真正意義上的portal時代的到來,portlet的開發讓身在其中的人們感到了稍許的不自在,其中很重要的一個因素就是對於session的管理。

在portal中,一個war是一系列portlet的組合,它的意義等價於以前servlet開發中的webapp,因此一個portlets的war就代表了部署在portal server上的一個應用程序,我們又知道在servlet規範中,session的範圍是和用戶會話相關的,而此會話是相對於具體的某個應用的,即同一個用戶登錄到不同的web應用後,他的session也是不同的,例如某個用戶登錄了部署在同一個服務器上的兩個web應用:辦公自動化系統和財務系統,那麼在辦公自動化系統中會有該用戶的一個sesion,而在財務系統中會有用戶的另外一個不同的session。

在portal server中也是這樣的,既然不同的portlets war代表不同的應用,那麼不同的portlets war之間session也是不同的,即是不能共享的。我想這是我們所能接受的,但是在同一個portlets war中的portlet之間共享session,這應該是個可以達到的基本要求吧,但是對於這一點,不同的portlet規範給出的答案也是不一樣的。

下面我們看一下JSR168和IBM Portlet對session問題的回答。

二,不同portlet規範對session問題的回答

1,JSR168方面

JSR168是JCP關於portlet的一個標準,它在自己框架中加入了對session問題的解決方法,在JSR168中,portlet session是可以設置作用範圍的,目前有兩個作用範圍:應用範圍(application_scope)和portlet範圍(portlet_scope),對於應用範圍的session屬性,是在同一個portlets war中共享的,而對於portlet範圍的session屬性,只能是在該portlet具體實例內共享的。如下是JSR168規範中的API:

PortletSession session = request.getPortletSession();

session.setAttribute("attributeName1", "attributeValue1", PortletSession.APPLICATION_SCOPE);
session.setAttribute("attributeName2", "attributeValue2", PortletSession.PORTLET_SCOPE);
session.setAttribute("attributeName3", "attributeValue3");

如上,設置了session屬性的範圍後,attributeName1是可以在整個portlets war內取到的,而attributeName2只能在該portlet 實例內取到,attributeName3沒有設置作用範圍,則默認位portlet_scope,因爲也只能在該portlet實例內取到。

2,IBM Portlet方面

可以說IBM portlet在同一個portlets war內session的共享做的很不夠,在wps4.1中可以通過如下方面解決:在web.xml的servlet定義中,加入下面的參數:

< init-param>
    < param-name> com.ibm.wps.portlet.session< /param-name>
    < param-value> shared< /param-value>
< /init-param>

但是這種共享並不是想象中的在portlets war內共享,而是隻有部署在同一個頁面中的該war中的portlet實例之間才能共享session,也就是說,即使是同一個portlets war的portlets,如果被部署在不同的頁面,那麼他們之間的session也是不能共享的,這顯然限制很大,沒有太大的實際上的意義。

三,實際的portlet項目開發中,該如何解決session的問題

通過前面已經知道,如果使用JSR168開發,則問題基本上可以解決,具體請參看上面的敘述,但是如果使用IBM portlet開發,則需要使用其它方式了。下面介紹的是針對IBM portlet在session方面所做的一種方式,效果還是可以的。

通過查閱相關資料以及進行相關實驗,我們最終發現,IBM portlet session基本上只能在具體的 concrete portlet實例(即已經部署到頁面中的某個portlet實例)範圍內有效,因此我們每個portlet都需要重新組建session,即通過用戶標識以及其它一些輔助類,獲取用戶相關信息並將信息設置到portlet session之中,爲了能讓每個portlet在做就體邏輯之前就將session信息初始化好,我採用如下的一個方案:

通過IBM portlet規範知道,每個concrete portlet可以定義他的視圖默認頁面,我們一般定義爲某個路徑下的index.jsp,因爲到index.jsp的時候,portlet的其它邏輯還沒有執行,因此此時是獲取用戶相關數據並存放到portlet session中的好時機,如下:


<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<portletAPI:init/>
<%
//獲取相關數據放置到session屬性中。
com.ibm.portal.puma.User portalUser= (com.ibm.portal.puma.User) portletRequest.getUser();
String userId=portalUser.getUserID();
session.setAttribute("userId",userId);
String department=new UserManager().getUserDepartmentBySn(userId);
session.setAttribute("department",department);
//準備完session信息後,導向到具體的應用邏輯頁面。
portletConfig.getContext().include("next.jsp",portletRequest,portletResponse);
%>
按照上面的方式,原來需要在HttpSession存儲的信息,現在每個需要這些信息的portlet都自己去後臺取一次,然後設置到自己的PortletSession之中。這種方式雖然感覺笨了一些,但至少是一種解決方式,可以嘗試一下,還是不錯的。

四,從portlet session問題看portal

portlet session的問題可能是不少人所不能理解的,爲什麼用戶登錄portal後,他所看到的東西可能不是在同一個session範圍內,爲什麼同一個用戶看到的不同的portlet可能會屬於不同的session。其實這涉及到對portal的理解問題。

portal我們知道是門戶的意思,也知道上面是一個個的portlet應用,每個portlet可能代表着一個不同的應用,這裏的應用和上面說的應用可能概念還不太一樣,這裏的應用主要是指業務。

另外我們知道portlet有自己的規範,只要按照規範開發出的portlet,則就可以部署到portal server之中,那麼在portal server中,很有可能包含了各種各樣的portlet,有些portlet是同一個業務的,而另外一些portlet是爲另一個業務的,請注意一點,portal server中的這些業務,並不一定只包含你自己做的,或你們公司自己做的,也有可能包含各個廠商自己已經做好的,還有可能客戶後來又新添加的。

這樣一來,如果不同業務或風馬牛不相及的業務之間可以共享session的話,那麼很可能會引起session的混亂,例如廠家A的portlet在session中設置了company屬性爲company_A,而廠家B的portlet在session中設置了company屬性爲company_B,如果session是在用戶登錄後的所有portlet之間共享的話,那麼就會引起數據混亂,而導致嚴重的業務問題。

基於此,portal server中提出了portlets應用的概念(portlet war),一個portlets 應用就是一組portlets,這些portlets被打成一個符合portal要求的war包,然後可以部署到portal server之中。在portal server中,portal會將每個portlet應用看作是一個獨立的應用,就好像是Tomcat下的webapps中的應用一樣,也許你覺得將portlets 應用看作是web應用很難,但你想一想,一個portlets應用中,包含了一個web應用所有的東西,有獨立的web.xml,有獨立的lib和classes以及tld等等,只能說portlet應用不僅是一個web應用,而且是一個實現了portlet功能的更爲強大的web應用。

我們知道一個portal server中可以部署多個這樣的portlet 應用,這實際上就相當於在一個portal server中部署了多個web應用,再想下去你可能會覺得非常驚歎:既然不同的portlet war是不同的web應用(就像tomcat webapps下的應用一樣),那麼我們登錄portal後,實際上看到的是多個web應用的聚合,不知你是否理解我現在說的,你想想以前訪問tomcat時,我們一般都是通過某個context path然後訪問到webapps下的具體應用,但是你是否想過如果將webapps下的所有應用在一個系統在內聚合訪問,那將是怎樣的一番景象呢!portal做的就是這個!

因此portets 應用(portlets war)之間不能共享session是理所當然的,就好像tomcat webapps下的不同應用不能共享session是一個道理,當然同一個portlets應用內(即同一個web應用內)共享session這應該是被支持的,JSR168做的就很好,IBM的portlet在這方面真是有些問題。

基於此我們再理解一下Websphere中的server1和WebSphere_Portal兩個服務器,我們以前可能會奇怪,爲什麼我們可以直接在server1部署web應用程序,然後通過url進行訪問,而WebSphere_Portal中卻不可以部署web應用程序然後通過url訪問呢,現在可以告訴你,server1部署的web應用是符合servlet標準的web應用,或者說是普通的web應用,而再WebSphere_Portal中實際上也可以部署web應用,只是只能部署較爲特殊的一種web應用,即portlets應用。另外我們在Websphere控制檯中只能部署企業級應用程序(包括普通的web應用),我們在裏面找不到可以部署portlet這種特殊web應用的地方,實際上我們都清楚,portlet應用的部署是在portal的管理短實現的,而不是在websphere的控制檯中.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章