
Portlet间的通信
介绍
在Portlet规范的第一个版本( JSR-168/Portlet 1.0)是不包含任何内部Portlet通信支持的。在第二个版本(JSR-286/Portlet 2.0)提供了IPC 通信的支持.
而JSR-286让两个portlet之间分享数据变得简单。通过使用IPC机制,我们可以在 Action层到View层 或View 层到View 层 中分享数据。
有3中方式可以在2个portlet之间分享数据:
- Portlet session
- IPC Mechanisms
- Public Render Parameters
- Event
- Client-Side IPC
- Cookies
1. Portlet Session #
默认的情况下,每个不同的War都有他们各自的seesion,但是是不能被分享给其他War的。
而Liferay 提供了一个允许夸War包访问的分享Session属性的机制。
每个Portlet应用程序都会创建一个PortletSession供每个用户使用。
在相同的Portal应用程序中,PortletSession是非常有用的,可以用在联系不同Porlet间相关联的用户信息。
步骤1:设置下面的属性 在 Portlet1 中 #
liferay-portlet.xml
<portlet> <private-session-attributes>false</private-session-attributes> </portlet>
#
步骤2:设置Seesion #
PortletSession session = renderRequest.getPortletSession(); session.setAttribute("sessionValue", some-value ,PortletSession.APPLICATION_SCOPE);
#
步骤3:在Portlet2中获取 Seesion中的值 #
PortletSession ps = renderRequest.getPortletSession(); String tabNames = (String)ps.getAttribute("sessionValue ",PortletSession.APPLICATION_SCOPE);
#
2,内部Porlet连接(IPC)机制 #
2.1 Public-Render-Parameter Inter-portlet Communication #
在JSR 168,processAction里设置的Render Parameter 只能供同一Portlet的Render来使用。
通过使用 Public Render Parameter ,在一个Porlet中的processAction里设置的 Public Render Parameter 也可以能供其他的Portlet的Render使用了。
在portal-ext.properties里添加下面的属性,我们可以使不同页面中的Portlet互相分享其 Render的状态:
portlet.public.render.parameter.distribution=ALL_PORTLETS
#
步骤1:在“Sender-Portlet”中添加下面的属性 #
<portlet-app> <portlet> <supported-public-render-parameter>id1</supported-public-render-parameter> </portlet> <public-render-parameter> <identifier>id1</identifier> <qname xmlns:x="http://abc.com/userId">x:param1</qname> </public-render-parameter> </portlet-app>
Note:We can declare a list of public paramters for a portlet application.
注意:我们可以为Portlet声明一个 Public Render Parameter 列表。
#
步骤2 #
我们可以在processAction方法中设置 Public Render Parameter 。作为key,我们使用的是定义好了的 Public Render Parameter 标识符:
response.setRenderParameter("id1", "someIdValue");
E.g.
public void processAction(ActionRequest request, ActionResponse response) throws IOException, PortletException { ........ response.setRenderParameter("id1", “someIdValue”); ........ }
#
步骤3:“Receiver Portlet”的“portlet.xml”文件 #
在porltet定义中指定哪个 Public Render Parameter 允许被分享
<portlet-app> <portlet> <portlet-name >PortletB< /portlet-name> <supported-public-render-parameter>id1</supported-public-render-parameter> </portlet > <public-render-parameter> <identifier>id1</identifier> <qname xmlns:x="http://abc.com/userId">x:param1</qname> </public-render-parameter> </portlet-app>
#
步骤4 #
Portlet可以通过使用 request.getPublicParameterMap() 方法读取 Public Render Parameter 。
注意:因为 Public Render Parameter 被合并到全局 parameter中了,所以我们也可以用下面的方法去读取:
request.getParameter(“id1”);
#
步骤5 #
我们也可以使用下面的方法去移除一个 Public Render Parameter :
response.removePublicRenderParameter("id1")
2.2 Event Inter-portlet Communication # #
Portlet Event 可以被接收和传递。
在JSR-168中,实现 Eventing(事件)的唯一方法是通过Portlet Session.这种方法的限制是,要求Portlet都隶属于相同的Web 应用。
在JSR-286里,则为 Event定义里生命周期。所以使属于不同Web应用的portlets间的事件成为了可能。
在portal-ext.properties文件中添加下面的属性,这样我们就可以在不同页面间传递或接收来自其他Portlet的Event了。
portlet.event.distribution=ALL_PORTLETS
#
步骤1:Sender Portlet #
portlet.xml
Porltet协议定义了一种方法去告知一个portlet容器如何去负责发送一个Event。
添加如下的字段到<portlet>标签里:
<portlet-app> <portlet> <supported-publishing-event xmlns:x='http://liferay.com'> <qname>x:empinfo</qname> </supported-publishing-event>> </portlet> <event-definition xmlns:x='http://liferay.com'> <qname>x:empinfo</qname> <value-type>java.lang.String</value-type> </event-definition> </portlet-app>
#
步骤2:在Process Action中设置一个Event #
javax.xml.namespace.QName qName = new QName("http://liferay.com", "empinfo", "x"); response.setEvent(qName, "Hi! You have received Event Data sent from Sender Portlet");
#
步骤3:Listener Portlet #
portlet.xml
<portlet-app> <portlet> <supported-processing-event xmlns:x='http://liferay.com'> <qname>x:empinfo</qname> </supported-processing-event> </portlet> <event-definition xmlns:x='http://liferay.com'> <qname>x:empinfo</qname> <value-type>java.lang.String</value-type> </event-definition> </portlet-app>
#
步骤4:获取Event #
如下图所示,Event将在processAction之后被执行。
Lifecycle for IPC Event
IPC Event 的生命周期
@javax.portlet.ProcessEvent(qname = "{http://liferay.com}empinfo")
public void handleProcessempinfoEvent(javax.portlet.EventRequest request, javax.portlet.EventResponse response) throws javax.portlet.PortletException, java.io.IOException { javax.portlet.Event event = request.getEvent(); String value = (String) event.getValue(); System.out.print("value in process event>>>>>>>>>" + value); response.setRenderParameter("empInfo", value); }
2.3 Client-Side IPC #
目前,有两个关于客户端IPC 的 API
Event生成
Liferay.fire( '<eventName>', { name: value } );
E.g.
Liferay.fire( 'planTravel', { origin: 'pune', destination : 'mumbai' } );
Event监听
Liferay.on( '<eventName>', function(event) { // your code } );
E.g.
Liferay.on( '<eventName>', function(event) { showNews('', event.origin); showNews('', event.destination); } );
#
3. Cookies #
除了IPC机制外,还有一种最简单的方法:通过Cookies。获取不同页面间不同的Porltet的数据。
但是这种方法还有一些局限性:
1. 不允许超过4KB的数据
2.每个服务器限制了最多只能有20个Cookies。
所以说,很不推荐去把每个变量分别存成不同的Cookie。
#
Portlet 1 #
通过JQuery设置Cookies
<script src="/html/js/jquery/cookie.js" type="text/javascript" > </script> function setCookie(docURL) { jQuery.cookie("cookieParam",docURL); }
设置Java/JSP 设置Cookies
HttpServletResponse response = PortalUtil.getHttpServletResponse(actionResponse); Cookie cookieParam = new Cookie("cookieParam ", password); response.addCookie(cookieParam);
#
Portlet 2 #
通过JQuery获取Cookies
jQuery.cookie("cookieParam ");
通过Java/JSP获取Cookies
String sessionid = ""; Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { if (cookies[i].getName().equals("cookieParam ")) { sessionid = cookies[i].getValue(); break; } } }