Portlet 应用开发, Part 6 - Portlet 的 Preference对象

本部分将阐述了Portlet的Preference对象, Preference 对象是Portlet所特有的对象,用来实现用户的个性化设置,可以替代部分数据库的功能.
• 为什么使用Preference 对象?
Preference 主要用来帮助用户对Portlet进行符合用户需要的显示定制或者行为定制.
举一个简单的例子: 用户有一个用来显示商品列表的Portlet, 可能有些用户需要在Portlet窗口中每页显示10个商品, 但是也有用户需要在Portlet的窗口中显示20个或者是30个商品. 这样的话, 对于同一个Portlet应用, 用户可以定制自己满意的用户界面.
以上的Preference 使用有一个前提, Preference对象只用来存取简单的配置信息,并不能替代数据库的应用.
• 如何使用Preference 对象?
Preference对象对于Portlet的配置信息存取使用KEY=VALUE , 或者是 KEY=VALUES 形式. 如果你的Portlet有需要使用用户定制的元素,可以将其加入到Preference对象中. 如下:
PortletPreference p= req.getPortletPreferences();
p.setValue(“PageSize”,”10”);
p.store();
• Preference的属性的作用范围
因为Preference的属性是用来存取用户的个性化信息的, 因此两个用户之间不可以share属性.
注: Pluto因为是单用户的Portal/PortletContainer的实现,因此如果两个用户使用同一个preference属性名称,互相会有冲突.
• 如何配置Preference 属性?
在Portlet.xml中设置Preference的初始或者是默认属性. 如下:
<portlet-preferences>
<preference>
<name>PageSize</name>
<value>20</value>
<read-only>true</read-only>
</preference>
</portlet-preferences>
在以上配置中配置了一个preference 属性PageSize, 注意read-only标签中设置了true, 那么这样一来这个preference 属性便不可以通过编程更改.
• 为什么使用PreferencesValidator对象?
PreferencesValidator对象允许Portlet的preference在被储存之前进行验证.用以保证portlet的Preference存取的正确性.
• 如何配置PreferencesValidator对象 ?
Servlet开发中有一种叫filter Servlet, 它的配置和PreferencesValidator的配置方式非常相似, 只不过一个在web.xml中配置, 而另一个在portlet.xml中配置. 如下XML:
<portlet-preferences>
<preferences-validator>
com.sss.PortletValidator
</preferences-validator>
</portlet-preferences>

• Case Study
以下我们将使用Preference和PreferencesValidator对象来开发一个简单的Portlet实现一个简单的用户登陆auditing. 以下是代码片段:
1. Portlet (PortletPreferenceExample.java)
… …
PortletPreferences prefs = request.getPreferences();
prefs.setValue("audit_enabled",audit_enabled);
prefs.store();
… …

以上代码片段将一个Portlet的配置参数audit_enabled赋予相应的值.
… …
PortletPreferences prefs = request.getPreferences();
prefs.reset("audit_enabled");
prefs.store();
… …
以上代码片段将一个Portlet的配置参数audit_enabled重新reset到初始时Portlet.xml配置文件中audit_enabled所对应的值.
2. JSP (edit_preference.jsp)

<%
PortletPreferences prefs = renderRequest.getPreferences();
String flag=prefs.getValue("audit_enabled","").toString();
%>
Edit 模式下Fragment 用来取得 Preference 的KEY值的代码 .

3. JSP (view_portletpreference.jsp)
<%
PortletPreferences prefs = renderRequest.getPreferences();
String flag=prefs.getValue("audit_enabled","").toString();
%>
View 模式下Fragment 用来取得 Preference 的KEY值的代码.

4. PreferencesValidator (PortletPreferencesValidator.java)
public class PortletPreferencesValidator implements
PreferencesValidator{
… …
… …
public void validate(PortletPreferences preferences)
throws ValidatorException
{
… …
… …
}
}
PortletPreferencesValidator执行了PreferencesValidator接口, 其具体的功能实现由validate方法执行. 我们这里将应用逻辑在validate方法中执行. 其功能主要是验证KEY所对应的值是否符合要求.(本例中Validator将验证audit_enabled所对应的值是否为”0”或者”1”, 否则将抛出错误).
• Preference Portlet的运行结果
将Tomcat启动, 在IE 或者 NetScape 中敲入以下地址:
http://localhost:8080/pluto/portal



单击Preference Example Page后可以看到如下页面(图6-1)
图6-1

输入”SpiritSeekerS” , 单击 Enter Button, 进入如下页面 (图6-2)
图6-2
进入edit mode , 将enable audit 选项选中 , 如下(图6-3):
图6-3
单击 SAVE button , 将回到view mode , 再次登陆后, 如下图(图6-4)
图6-4
• 源代码及Portlet相关配置文件
1. Portlet (PortletPreferenceExample.java)
package portlets.portletpreference;
/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import javax.portlet.*;
import java.io.IOException;
public class PortletPreferenceExample extends GenericPortlet{
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");
String jspName = getPortletConfig().getInitParameter("view");
PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);
rd.include(request, response);
}
public void doEdit(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");
String jspName = getPortletConfig().getInitParameter("edit");
PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);
rd.include(request, response);
}


public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, java.io.IOException
{

String action = request.getParameter("action");
String audit_enabled = request.getParameter("audit_enabled");


if(action.equals("edit")&&audit_enabled!=null){
PortletPreferences prefs = request.getPreferences();
prefs.setValue("audit_enabled",audit_enabled);
prefs.store();
}else if(action.equals("edit")){
PortletPreferences prefs = request.getPreferences();
prefs.reset("audit_enabled");
prefs.store();
}else if(action.equals("view")){
String usr= request.getParameter("usr");
response.setRenderParameter("usr",usr);
}
else{
throw new PortletException("Unexpected Error!");
}
}
}
2. JSP (view_portletpreference.jsp)
<%@ page session="false" %>
<%@ page import="javax.portlet.*"%>
<%@ page import="java.util.*"%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<portlet:defineObjects/>
<BR>
<%
PortletPreferences prefs = renderRequest.getPreferences();
String flag=prefs.getValue("audit_enabled","").toString();
%>
<portlet:actionURL portletMode="view" var="url">
<portlet:param name="action" value="view"/>
</portlet:actionURL>
<form method=post action=<%=url%>>
<table border=0>
<tr><td><b>Name:</b></td><td><input type=text name=usr></tr>
<tr><td colspan=2 align=right><input type=submit value="Enter"></td></tr>
</table>
</form>

<%
String usr=renderRequest.getParameter("usr");
if(usr!=null){
%>Welcome, <%=usr%> !! <BR><%

%>
<%
if(flag.equals("1")){
%>
===============================================<BR>
<table border=0>
<tr>
<td><b>INFO:</b> <%=usr.toUpperCase()%> login at </td>
<td><%=new Date().toString()%></td>
</tr>
</table>
===============================================<BR>
<%
}
}
%>
3. JSP (edit_portletpreference.jsp)
<%@ page session="false" %>
<%@ page import="javax.portlet.*"%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<portlet:defineObjects/>
<BR>
<%
PortletPreferences prefs = renderRequest.getPreferences();
String flag=prefs.getValue("audit_enabled","").toString();
%>

<portlet:actionURL portletMode="view" var="url">
<portlet:param name="action" value="edit"/>
</portlet:actionURL>
<form method=post action=<%=url%>>
<table border=0>
<tr>
<td><b>Auditing Enabled:</b></td>
<td><input type=checkbox name="audit_enabled" value="1" <%=flag.equals("1")?"checked":""%>></td>
</tr>
<tr>
<td colspan=2 align=right><input type=submit value="SAVE"></td>
</tr>
</table>
</form>
4. Preference Validator (PortletPreferencesValidator.java)
package portlets.portletpreference;
/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import javax.portlet.*;
import java.util.*;
public class PortletPreferencesValidator implements PreferencesValidator{
public static final String AUDITING_ENABLED="1";
public static final String AUDITING_DISABLED="0";

public void validate(PortletPreferences preferences)
throws ValidatorException
{
Enumeration prefnms = preferences.getNames();
Collection errKeys = new ArrayList();
while (prefnms.hasMoreElements()){
String prefnm = prefnms.nextElement().toString();
String value = preferences.getValue(prefnm, AUDITING_DISABLED);
System.out.println(value);
if((value.equals(AUDITING_ENABLED))||(value.equals(AUDITING_DISABLED))){
System.out.println("#### INFO: VALID KEY.");
}else{
System.out.println("#### ERROR: INVALID KEY.");
throw new ValidatorException("INVALID KEY",new Throwable("Incorrect Value!"),errKeys);
}
}
}
}

5. Portlet.xml
… …
<!-- Preference Example -->
<portlet>
<description>PortletPreference Example</description>
<portlet-name>PortletPreferenceExample</portlet-name>
<display-name>PortletPreferenceExample</display-name>
<portlet-class>portlets.portletpreference.PortletPreferenceExample</portlet-class>
<init-param>
<name>view</name>
<value>/fragments/portletpreference/view_portletpreference.jsp</value>
</init-param>
<init-param>
<name>edit</name>
<value>/fragments/portletpreference/edit_portletpreference.jsp</value>
</init-param>
<expiration-cache>-1</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>PortletPreference Example</title>
<short-title>PortletPreference</short-title>
<keywords>PortletPreference</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>audit_enabled</name>
<value>0</value>
</preference>
<preferences-validator>portlets.portletpreference.PortletPreferencesValidator</preferences-validator>
</portlet-preferences>
</portlet>

… …
6. pageregistry.xml
… …
<!-- Preference Example Page -->
<fragment name="preferencepage" type="page">
<navigation>
<title>Preference Example Page</title>
<description>Preference Example Page</description>
</navigation>
<fragment name="row1" type="row">
<fragment name="col1" type="column">
<fragment name="p1" type="portlet">
<property name="portlet" value="10.70"/>
</fragment>
</fragment>
</fragment>
</fragment>
… …
7. portletregistry.xml
… …
<portlet id="70">
<definition-id>portlets.PortletPreferenceExample</definition-id>
</portlet>
… …

资源:
• Pluto
http://jakarta.apache.org/pluto
• Pluto Mail List
http://news.gmane.org/gmane.comp.jakarta.pluto.user
• WSRP Spec1.0
http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsrp
• Apache的WSRP实现
http://ws.apache.org/wsrp4j/
• Apache’s Portal, JetSpeed:
http://jakarta.apache.org/jetspeed/site/index.html
• JSR 168:
http://www.jcp.org/en/jsr/detail?id=168
• "Portlet 规范介绍" By Stefan Hepper 和 Stephan Hesmer
Part 1: Get your feet wet with the specification's underlying terms and concepts (August 2003)
Part 2: The Portlet API's reference implementation reveals its secrets (September 2003)


Java Portlet 应用开发, Part 5 - Portlet 的 Session对象
By Jia.li(Terry.li)
SpiritSeekerS@sqatester.com

本系列前一部分阐述了Portlet的Request和Response对象,本部分继续讲解Portlet中Session对象.及其与Servlet中Session对象的不同点.
• Portlet Session中存取对象的作用范围 (Scope)
Servlet中的Session属性和Portlet中的Session属性有一个非常大的不同点, 由于Portlet处于Portal中的缘故, Portlet的Session属性分为两种, 分别作用于不同的范围中:
1. Application Scope
2. Portlet Scope
这两者的区别在于:
1) Application Scope类型的PortletSession中保存的对象对于同一个Portlet Application中的所有其它Portlet来说是可以被访问到的.
2) Portlet Scope类型的PortletSession中保存的对象对于同一个Portlet Application中的所有其它Portlet来说是不可见的.
但对于Portlet Application来说,其实它也是个Web Application , 因此不论是Application Scope也好,或者是Portlet Scope也好,同样都属于HttpSession,因此都可以通过HttpSession 来访问.
实际上Application Scope的Session就是HttpSession , 而Portlet Scope的Session 由于不可被其他Portlet访问, 它的session属性名称有它独特的存取方式, 如下:
javax.portlet.p.<ID>?<ATTRIBUTE_NAME>
其中ID是Portal/Portlet-Container生成用来唯一确定一个Portlet.
Portlet Scope 的Session 使用以上的Attribute Name 用以存取Session上绑定的属性. 我们所设制的Portlet Scope 的Session属性由Portlet容器自动转化成以上格式. 用以保证不被其它的Portlet访问到.
注: 以javax.portlet开头的Session属性名称是保留的,不可以用于Portlet的Session 属性名称.
• Case study: 不同Scope Session的比较

以下我们将编码实现两个Portlet, 其中一个用来创建session属性的Portlet 和另一个用来验证session属性作用范围的Portlet. 用以验证Session属性的正确性.

1. Portlet (PortletSessionExample1_GenerateSesssion.java)
… …
public void processAction(ActionRequest request,ActionResponse response)
throws PortletException,IOException{
String action=request.getParameter("ACTION");
if(action.equals("ApplicationScope")){
PortletSession ps=request.getPortletSession();
ps.setAttribute("PortletSession.AS",action,PortletSession.APPLICATION_SCOPE);
}else{
PortletSession ps=request.getPortletSession();
ps.setAttribute("PortletSession.PS",action,PortletSession.PORTLET_SCOPE);
}
}

… …

以上代码片段根据不同参数分别产生不同Scope的PortletSession 的属性 , 作用范围分别为Application 和 Portlet.
2. Portlet (PortletSessionExample1_DisplaySession.java)
这个Portlet调用一个JSP (jspShowSession.jsp) 来获得Portlet session和HttpSession, 并且示出来.
3. JSP(view_portletsession1_generatesession.jsp)
这个JSP将创建两个ActionURL , 分别用来产生两种PortletSession属性:
… …
<portlet:actionURL windowState="NORMAL" portletMode="view" var="pu1">
<portlet:param name="ACTION" value="ApplicationScope"/>
</portlet:actionURL>
<portlet:actionURL windowState="NORMAL" portletMode="view" var="pu2">
<portlet:param name="ACTION" value="PortletScope"/>
</portlet:actionURL>

… …
4. JSP (jspShowSession.jsp)
取得以上创建的两个PortletSession 的属性值, 由Browser中可以看到只有Application Scope的Session 属性可以被获得.
if(ps.getAttribute("PortletSession.AS",PortletSession.APPLICATION_SCOPE)!=null){
app=ps.getAttribute("PortletSession.AS",PortletSession.APPLICATION_SCOPE).toString();
}

if(ps.getAttribute("PortletSession.PS",PortletSession.PORTLET_SCOPE)!=null){
portlet=ps.getAttribute("PortletSession.PS",PortletSession.PORTLET_SCOPE).toString();
}

以下代码将Httpsession中的所有属性全部列出:
可以看到PortletContainer是如何存取Portlet Scope类型的session属性的.
<%
HttpSession s=request.getSession();
for (Enumeration e = s.getAttributeNames() ; e.hasMoreElements() ;) {
%><tr><td><%=e.nextElement()%></td></tr>
<%
}
%>

将以上源代码编译后, 再通过Eclipse生成/更新Portlet的web.xml后, 将所有配置及相关文件部署后, 启动Tomcat.

在Browser中加载如下页面: Http://localhost:8080/pluto/portal , 可以看到如下的页面(图:5-1)
图:5-1

单击PortletSession Example1 Page后可以看到如下两个Portlet 页面(图5-2)

图:5-2

上图中上边的一个Generate Portlet用来创建两个PortletSession属性,分别是Application Scope 和 Portlet Scope 类型.
下方的Display Portlet用以验证Session的作用范围.
单击Application Scope Session, 可以看到如下页面(图5-3)

图5-3
如上图,生成了一个Application Scope的属性, 名称: PortletSession.AS

单击Portlet Scope Session, 可以看到如下页面(图5-4)
图5-5
生成了一个Portlet Scope Session属性,所以Display portlet 无法取得. 但是从HttpSession 可以看到又创建了一个session属性.

Case study: Session的共享
以上例子验证了Portlet中Session的作用范围, 可能在开发过程中经常需要有Popup页面的处理这个时候就无法使用Portlet, 但是可以使用Servlet或者是JSP, 以下这个例子是一个Portlet和Servlet的Session共享的应用 (或许是Tomcat4的一个BUG), 我们将使用一个Portlet创建一个Application Scope的Session, 然后在一个Servlet中得到它.
1. Portlet (PortletSessionExample2_ShareSession.java)
以下代码将创建一个application scope的Portlet Session:
… …
if(INF!=null){
PortletSession ps=request.getPortletSession();
ps.setAttribute("INF",INF,PortletSession.APPLICATION_SCOPE);
}
… …
2. JSP (jspLoginView.jsp)
… …
<%
PortletSession ps = renderRequest.getPortletSession();

String app=null;

if(ps.getAttribute("INF",PortletSession.APPLICATION_SCOPE)!=null){
app=ps.getAttribute("INF",PortletSession.APPLICATION_SCOPE).toString();
%> <u><a style="cursor:hand" οnclick='window.open("/pluto/popup","a","width=400,height=330,scrollbars=1")'>Click here to Popup</a></u> <%
}
%>
… …
3. Servlet (PopupServlet.java)
… …
HttpSession se=request.getSession();
Object info=se.getAttribute("INF");
… …
注: 由于Tomcat下webapps目录下的pluto和portlets分别是两个web application, 所以将以上的PopupServlet配置到pluto目录下,而非portlets目录下.

将以上源代码编译后, 再通过Eclipse生成/更新Portlet的web.xml后, 将所有配置及相关文件部署后, 启动Tomcat.

在Browser中加载如下页面: Http://localhost:8080/pluto/portal , 可以看到如下的页面


单击PortletSession Example2 Page后可以看到如下页面(图5-6)


图5-6
单击 Click here to generate a session , 后可以看到如下页面(图5-7)
图5-7
单击 Click here to Popup , 后可以看到如下页面(图5-8)

图5-8
• 源代码及Portlet相关配置文件
A. Session Example1
1. Portlet (PortletSessionExample1_GenerateSesssion.java)
package portlets.portletsession;
/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import javax.portlet.*;
import java.io.IOException;
public class PortletSessionExample1_GenerateSesssion extends GenericPortlet{
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException{
response.setContentType("text/html");
String jspName = getPortletConfig().getInitParameter("view");
PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);
rd.include(request, response);
}

public void processAction(ActionRequest request,ActionResponse response)
throws PortletException,IOException{
String action=request.getParameter("ACTION");
if(action.equals("ApplicationScope")){
PortletSession ps=request.getPortletSession();
ps.setAttribute("PortletSession.AS",action,PortletSession.APPLICATION_SCOPE);
}else{
PortletSession ps=request.getPortletSession();
ps.setAttribute("PortletSession.PS",action,PortletSession.PORTLET_SCOPE);
}
}

}

2. Portlet (PortletSessionExample1_DisplaySession.java)
package portlets.portletsession;
/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import javax.portlet.*;
import java.io.IOException;
public class PortletSessionExample1_DisplaySession extends GenericPortlet{
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");
String jspName = getPortletConfig().getInitParameter("view");

PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);
rd.include(request, response);
}
}
3. JSP (view_portletsession1_displaysession.jsp)
<%@ page session="false" %>
<%@ page import="javax.portlet.*"%>
<%@ page import="java.util.*"%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<portlet:defineObjects/>
<BR>
<h3>Display PortletSession and HttpSession Example</h3>
<%
PortletSession ps = renderRequest.getPortletSession();

String app="NULL";
String portlet="NULL";

if(ps.getAttribute("PortletSession.AS",PortletSession.APPLICATION_SCOPE)!=null){
app=ps.getAttribute("PortletSession.AS",PortletSession.APPLICATION_SCOPE).toString();
}

if(ps.getAttribute("PortletSession.PS",PortletSession.PORTLET_SCOPE)!=null){
portlet=ps.getAttribute("PortletSession.PS",PortletSession.PORTLET_SCOPE).toString();
}
%>
<b>PortletSession list:</b>
<table border=1>
<tr><td><b>Session Scope</b></td><td><b>Attribute Name</b></td><td><b>Attribute Value</b></td></tr>
<tr><td>Application scope</td><td>PortletSession.AS</td><td><b><%=app%></b></td></tr>
<tr><td>Portlet scope</td><td>PortletSession.PS</td><td><b><%=portlet%></b></td></tr>
</table>
<br>
<b>HttpSession list:</b>
<table border=1>
<tr><td><b>Attribute Name</b></td></tr>
<%
HttpSession s=request.getSession();
for (Enumeration e = s.getAttributeNames() ; e.hasMoreElements() ;) {
%><tr><td><%=e.nextElement()%></td></tr>
<%
}
%>
</table>
<BR><BR>
4. JSP (view_portletsession1_generatesession.jsp)
<%@ page session="false" %>
<%@ page import="javax.portlet.*"%>
<%@ page import="java.util.*"%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<portlet:defineObjects/>
<portlet:actionURL windowState="NORMAL" portletMode="view" var="pu1">
<portlet:param name="ACTION" value="ApplicationScope"/>
</portlet:actionURL>
<portlet:actionURL windowState="NORMAL" portletMode="view" var="pu2">
<portlet:param name="ACTION" value="PortletScope"/>
</portlet:actionURL>
<BR>
<h3>Generate PortletSession Example</h3>
<a href="<%=pu1%>">Application Scope Session</a>
<Br>
<a href="<%=pu2%>">Portlet Scope Session</a>
<Br><BR>

B. Session Example2
1.Portlet (PortletSessionExample2_ShareSession.java)
package portlets.portletsession;
/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import javax.portlet.*;
import java.io.IOException;
public class PortletSessionExample2_ShareSession extends GenericPortlet{
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");
String jspName = getPortletConfig().getInitParameter("view");

PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);
rd.include(request, response);
}

public void processAction(ActionRequest request,
ActionResponse response)
throws PortletException,
java.io.IOException{
String INF=request.getParameter("INF");
if(INF!=null){
PortletSession ps=request.getPortletSession();
ps.setAttribute("INF",INF,PortletSession.APPLICATION_SCOPE);
}
}
}

2. Servlet (PopupServlet.java)
package servlet;
/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
public class PopupServlet extends HttpServlet{

public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
PrintWriter pw=response.getWriter();
HttpSession se=request.getSession();
Object info=se.getAttribute("INF");
if(info!=null){
pw.println("<table border=1 bordercolor=black>");
pw.println(" <tr>");
pw.println(" <td><b>Attribute</b><td><td><b>Value</b></td> ");
pw.println(" </tr>");
pw.println(" <tr>");
pw.println(" <td>INF<td><td>"+ info.toString() +"</td> ");
pw.println(" </tr>");
pw.println("</table>");
}else{
pw.println("No session");
}
}
}

C. 配置文件
1. Portlet.xml
… …
<!-- PortletSession Example -->
<!-- PortletSession Example1 - GenerateSession -->
<portlet>
<description>PortletSession_Generator Example</description>
<portlet-name>PortletSession_GeneratorExample</portlet-name>
<display-name>PortletSession_Generator Example</display-name>
<portlet-class>portlets.portletsession.PortletSessionExample1_GenerateSesssion</portlet-class>

<init-param>
<name>view</name>
<value>/fragments/portletsession/view_portletsession1_generatesession.jsp</value>
</init-param>
<expiration-cache>-1</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>PortletSession_Generator Example</title>
<short-title>PortletSession_Generator</short-title>
<keywords>PortletSession_Generator</keywords>
</portlet-info>
</portlet>

<!-- PortletSession Example1 - DisplaySession -->
<portlet>
<description>PortletSession_Display Example</description>
<portlet-name>PortletSession_DisplayExample</portlet-name>
<display-name>PortletSession_Display Example</display-name>
<portlet-class>portlets.portletsession.PortletSessionExample1_DisplaySession</portlet-class>

<init-param>
<name>view</name>
<value>/fragments/portletsession/view_portletsession1_displaysession.jsp</value>
</init-param>
<expiration-cache>-1</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>PortletSession_Display Example</title>
<short-title>PortletSession_Display</short-title>
<keywords>PortletSession_Display</keywords>
</portlet-info>
</portlet>
… …
2. pageregistry.xml
… …
<!-- PortletSession Example1 Page -->
<fragment name="portletsessionpage1" type="page">
<navigation>
<title>PortletSession Example1 Page</title>
<description>PortletSession Example Page</description>
</navigation>
<fragment name="row1" type="row">
<fragment name="col1" type="column">
<fragment name="p1" type="portlet">
<property name="portlet" value="10.40"/>
</fragment>
</fragment>
</fragment>
<fragment name="row2" type="row">
<fragment name="col1" type="column">
<fragment name="p1" type="portlet">
<property name="portlet" value="10.50"/>
</fragment>
</fragment>
</fragment>
</fragment>
<!-- PortletSession Example2 Page -->
<fragment name="portletsessionpage2" type="page">
<navigation>
<title>PortletSession Example2 Page</title>
<description>PortletSession Example Page</description>
</navigation>
<fragment name="row1" type="row">
<fragment name="col1" type="column">
<fragment name="p1" type="portlet">
<property name="portlet" value="10.60"/>
</fragment>
</fragment>
</fragment>
</fragment>
… …
3. Portletregiestry.xml
… …
<portlet id="40">
<definition-id>portlets.PortletSession_GeneratorExample</definition-id>
</portlet>
<portlet id="50">
<definition-id>portlets.PortletSession_DisplayExample</definition-id>
</portlet>
<portlet id="60">
<definition-id>portlets.PortletSession_ShareExample</definition-id>
</portlet>
… …


总结
Session对于Web 开发来说是非常重要且必要的元素, 对于Portlet来说, 其Session的功能和Servlet略有不同. 但实际还是HttpSession的延伸及包装.
资源:
• Pluto
http://jakarta.apache.org/pluto
• Pluto Mail List
http://news.gmane.org/gmane.comp.jakarta.pluto.user
• WSRP Spec1.0
http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsrp
• Apache的WSRP实现 (WSRP4J)
http://ws.apache.org/wsrp4j/
• Apache’s Portal, JetSpeed:
http://jakarta.apache.org/jetspeed/site/index.html
• JSR 168:
http://www.jcp.org/en/jsr/detail?id=168


Portlet 应用开发, Part 4 - Portlet 的 Request和Response对象
By Terry.li
SpiritSeekerS@sqatester.com


本文使用本系列中Part1搭建的开发环境,如果没有搭建好开发环境,请参考Portlet应用开发Part1进行开发环境的搭建.在Part1中我们已经介绍了Portlet的GenericPortlet类. 从形式上来看, Portlet与Servlet非常相似, 但是从request和response对象的具体特点及功能来说, 又有所不同. 本部分主要描述了Portlet的Request和Response对象的特点及其与Servlet的Request和Response对象的不同点.

 Portlet的Request 对象
Portlet中的Request与Servlet的Request一样接受Client端发送的Request, 但是与Servlet不同, Portlet的Request分为Action Request及Render Request两种类型,因此Portlet接口中定义了两种方法用来处理不同的Request. 分别是processAction(ActionRequest request,ActionResponse response) 和render(RenderRequest request,RenderResponse response),分别用以处理Action Request和Render Request. 某种意义上来讲,render方法类似Servlet中的service方法,doView,doEdit,doHelp方法又类似doGet,doPost方法,如下图:


1. RenderRequest和ActionRequest有什么不同呢?
对于Portlet来说PortletRequest分为ActionRequest和RenderRequest两种,分别是由renderURL和actionURL来触发的.可以这样理解, renderURL是actionURL的一种优化形式.Portlet开发过程中尽可能使用renderURL而避免使用actionURL. actionURL适用于有确实的Action(行为)的情况下. 比如说, form表单的递交. Persistent状态的改变,session的操作,preference的修改,这种情况下使用actionURL,而不使用renderURL, renderURL通常用来操作portlet内容的导航.

以下是两个例子:

使用actionURL:
<%
PortletURL pu=renderResponse.createActionURL();
pu.setParameter("ACTION","LOGIN");

%>
<form name="usrfrm" method="post" action="<%=pu.toString()%>">

注: form表单递交时,使用HTTP post方法,而不用get方法.因为某些Portal/Portlet Container的实现将内部状态编码到URL的Query字符串中.


使用renderURL:
<%
PortletURL pu=renderResponse.createRenderURL();
pu.setParameter("PAGE",Number);

%>
<a href=”<%=pu%>”>下一页</a>

2. renderURL和actionURL的处理方式有什么不同?
当客户端request是由一个renderURL触发时,Portlet/Portlet Container会调用Portal页面中所有Portlet的render方法. 如下:

renderURL
/ | \
render render render


而当客户端request一个actionURL触发时, Portlet/Portlet Container会先调用目标Portlet的processAction()方法, 当processAction方法处理完毕后,再分别调用Portal页面中所有Portlet的render方法.如下:

actionURL
|
processAction
/ | \
render render render

由于以上原因,所以使用renderURL要比使用actionURL的performance来的好.

3. RenderRequest和ActionRequest的parameter参数作用范围有什么不同?
当客户端request一个actionURL触发时,比如一个form表单的提交,所有的Parameter的get操作必须在processAction方法中进行. 例如:

JSP的form表单页面:
<%
PortletURL pu=renderResponse.createActionURL();
pu.setParameter("ACTION","LOGIN");

%>
<form name="usrfrm" method="post" action="<%=pu.toString()%>">


Portlet的处理:
public void processAction(ActionRequest req,ActionResponse res){
String str=req.getParameter(“ACTION”);
//response.setRenderParameter("ACTION",action);
}

public void doView(ActionRequest req,ActionResponse res){
String str=req.getParameter(“ACTION”);
}

如上processAction方法中,getParamter方法将能成功得到表单中的参数ACTION所对应的值,因为我们知道,当目标portlet的processAction方法运行完后,Portlet Container将调用Portal页面中所有Portlet的render方法.但是实际上doView方法中使用getParameter不会得到任何值.但是如果把processAction方法中注释了的一行uncomment的话,你就可以在doView方法中的得到参数ACTION对应的值. 这说明action request的参数,render方法中不可以直接取到.必须使用了setRenderParameter方法,再次传递一次.


 A case study
在这部分中,我们来做一个简单的Portlet, 实现一个简单的Form submit功能. 以下是代码片段: (完整代码请参考文章末尾)

JSP(view_portletrequest.jsp.jsp):

… …
<!-- Use PortletURL Object//-->
<%
PortletURL pu1=renderResponse.createActionURL();
pu1.setParameter("ACTION","Use PortletURL Object");
pu1.setPortletMode(PortletMode.VIEW);
%>

<table width=100% border=0>
<TR><TD>1. Use PortletURL object to get an ActionURL and set current portlet mode to view</TD></TR>
<tr><td>
<form name="usrfrm" method="post" action="<%=pu1.toString()%>">
<input type=submit name=bt1 value="GetActionByJava">
</form>
<tr><td>
</table>
… …

注: 处理完form后将会将PortletMode设定为VIEW.

以上代码使用了actionURL因为是form表单的递交. 详细请参考Portlet的Request 对象部分. 或者也可以使用Tag. 它同样也可以生成一个Portlet的URL, 如下:

… …
<!-- Use Portlet Tag //-->
<portlet:actionURL windowState="maximized" portletMode="edit" var="pu2">
<portlet:param name="ACTION" value="Use Portlet Tag"/>
</portlet:actionURL>

<BR>
<table width=100% border=0>
<TR><TD>2. Use Portlet Tag to get a ActionURL and and set current portlet mode to edit</TD></TR>
<tr><td>
<form name="usrfrm" method="post" action="<%=pu2%>">
<input type=submit name=bt2 value="GetActionByTag">
</form>
<tr><td>
</table>
… …

注: 它在处理完form后将会将PortletMode设定为EDIT,并且Window state会为最大化.

Portlet(PortletRequestExample.java):

… …
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException
{
String action=request.getParameter("ACTION");
System.out.println("ACTION" + action);
if(action==null){
action="";
}

response.setRenderParameter("ACTION",action);
}
… …


JSP(view_portletrequest.jsp)

… …
<%
String getaction="";
if(request.getParameter("ACTION")!=null){
getaction=request.getParameter("ACTION");
}
%>

<B>ACTION: <%=getaction%></B>
… …


JSP(edit_portletrequest.jsp.jsp)

… …
<%
String getaction="";
if(request.getParameter("ACTION")!=null){
getaction=request.getParameter("ACTION");
}
%>
<B>ACTION: <%=getaction%></B>
… …

将以上源代码编译后, 再通过Eclipse生成/更新Portlet的web.xml后, 将所有配置及相关文件部署后, 启动Tomcat.



在Browser中加载如下页面: Http://localhost:8080/pluto/portal , 可以看到如下的页面(图:4-1)


图:4-1


单击PortletRequest Example Page后可以看到如下Portlet 页面(图4-2)


图:4-2



单击 GetActionByJava 后, 得到如下(图:4-3):

图:4-3

单击 GetActionByTag 后, 将跳转到edit mode, 如下(图:4-4):


图:4-4

 Portlet的Response 对象
与Request对象类似,Response对象也有两种:分别是ActionResponse和RenderResponse, 分别封装了对应ActionRequest和RenderRequest对象返回的所有信息。例如,重定向,windows state,portlet mode等的信息。其中他们的父类,PortletResponse拥有setProperty和addProperty方法,用以传递提供商指定的信息给portal/portlet container

1。ActionResponse和RenderResponse有什么不同?
ActionResonse可以用来处理以下相关功能:
1) 重定向
sendRedirect方法用来进行帮助portal/portlet-container进行头信息,及其内容的设定,并且将URL重定向到用户指定的页面。
2) 改变windows state, portlet mode ,我们在以前章节中介绍了window state 和 portlet mode概念.
3) 传递Parameter参数到RenderRequest中去,如上面request部分中用到的例子。

RenderResponse用来提供如下功能(和Servlet中的Response更相似):
1) 设置ContentType
2) 得到Output Stream and Writer对象,用来产生页面内容
3) Buffering
4) 设定Portlet的Title , 但必须先于portlet的输出递交前来调用,否则将会被忽略。(注:目前的pluto没有实现,如果调用不会修改title)

 A example

… …
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");
PrintWriter pw=response.getWriter();
pw.print(“Hello, Portlet”);
… …


• 源代码及Portlet相关配置文件

A. Portlet (PortletRequestExample.java)

package portlets.portletrequest;

/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import javax.portlet.*;
import java.io.IOException;

public class PortletRequestExample extends GenericPortlet{

public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");

String jspName = getPortletConfig().getInitParameter("view");

PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);

rd.include(request, response);
}

public void doEdit(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");

String jspName = getPortletConfig().getInitParameter("edit");

PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);

rd.include(request, response);
}

public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException
{
String action=request.getParameter("ACTION");
System.out.println("ACTION" + action);
if(action==null){
action="";
}

response.setRenderParameter("ACTION",action);
}
}

B. JSP (view_portletrequest.jsp)

<%@ page session="false" %>
<%@ page import="javax.portlet.*"%>
<%@ page import="java.util.*"%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<portlet:defineObjects/>
<BR>
<h3>Request Example</h3>

<!-- Use PortletURL Object//-->
<%
PortletURL pu1=renderResponse.createActionURL();
pu1.setParameter("ACTION","Use PortletURL Object");
pu1.setPortletMode(PortletMode.VIEW);
%>

<table width=100% border=0>
<TR><TD>1. Use PortletURL object to get an ActionURL and set current portlet mode to view</TD></TR>
<tr><td>
<form name="usrfrm" method="post" action="<%=pu1.toString()%>">
<input type=submit name=bt1 value="GetActionByJava">
</form>
<tr><td>
</table>

<!-- Use Portlet Tag //-->
<portlet:actionURL windowState="maximized" portletMode="edit" var="pu2">
<portlet:param name="ACTION" value="Use Portlet Tag"/>
</portlet:actionURL>

<BR>
<table width=100% border=0>
<TR><TD>2. Use Portlet Tag to get a ActionURL and and set current portlet mode to edit</TD></TR>
<tr><td>
<form name="usrfrm" method="post" action="<%=pu2%>">
<input type=submit name=bt2 value="GetActionByTag">
</form>
<tr><td>
</table>

<%
String getaction="";
if(request.getParameter("ACTION")!=null){
getaction=request.getParameter("ACTION");
}
%>

ACTION: <B><%=getaction%></B>

<BR><BR>
Current Portlet Mode: <B><big><%=renderRequest.getPortletMode()%></big></font></B><br>


C. JSP (edit_portletrequest.jsp)

<%@ page session="false" %>
<%@ page import="javax.portlet.*"%>
<%@ page import="java.util.*"%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<portlet:defineObjects/>
<BR>
<h3>Request Example</h3>


<%
String getaction="";
if(request.getParameter("ACTION")!=null){
getaction=request.getParameter("ACTION");
}
%>

ACTION: <B><%=getaction%></B>

<BR><BR>
Current Portlet Mode: <big><B><%=renderRequest.getPortletMode()%></font></big></B><br>

D. Portlet.xml

… …
<!-- PortletRequest Example -->
<portlet>
<description>PortletRequest Example</description>
<portlet-name>PortletRequestExample</portlet-name>
<display-name>PortletRequest Example</display-name>
<portlet-class>portlets.portletrequest.PortletRequestExample</portlet-class>

<init-param>
<name>view</name>
<value>/fragments/portletrequest/view_portletrequest.jsp</value>
</init-param>
<init-param>
<name>edit</name>
<value>/fragments/portletrequest/edit_portletrequest.jsp</value>
</init-param>

<expiration-cache>-1</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>PortletRequest Example</title>
<short-title>PortletRequest</short-title>
<keywords>PortletRequest</keywords>
</portlet-info>
</portlet>
… …

E. portletentityregistry.xml

<?xml version="1.0" encoding="UTF-8"?>
<portlet-entity-registry>
<application id="10">
<definition-id>portlets</definition-id>
… …
<portlet id="30">
<definition-id>portlets.PortletRequestExample</definition-id>
</portlet>
… …
</application>
</portlet-entity-registry>

F. pageregistry.xml

<?xml version="1.0"?>
<portal>

<fragment name="navigation" class="org.apache.pluto.portalImpl.aggregation.navigation.TabNavigation">
</fragment>

… …

<!-- PortletRequest Example Page -->
<fragment name="portletrequestpage" type="page">
<navigation>
<title>PortletRequest Example Page</title>
<description>PortletConfig Example Page</description>
</navigation>
<fragment name="row1" type="row">
<fragment name="col1" type="column">
<fragment name="p1" type="portlet">
<property name="portlet" value="10.30"/>
</fragment>
</fragment>
</fragment>
</fragment>

… …

</portal>


注: web.xml文件可以从portlet.xml通过Eclipse的Plugin直接生成,所以没有列出配置文件, 请参考本系列中的Part1.

资源:
• Pluto
http://jakarta.apache.org/pluto

• Pluto Mail List
http://news.gmane.org/gmane.comp.jakarta.pluto.user

• WSRP Spec1.0
http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsrp

• Apache的WSRP实现
http://ws.apache.org/wsrp4j/

• Apache’s Portal, JetSpeed:
http://jakarta.apache.org/jetspeed/site/index.html

• JSR 168:
http://www.jcp.org/en/jsr/detail?id=168
• "Portlet 规范介绍" By Stefan Hepper 和 Stephan Hesmer
o Part 1: Get your feet wet with the specification's underlying terms and concepts (August 2003)
o Part 2: The Portlet API's reference implementation reveals its secrets (September 2003)



11:19:51 | 添加评论 | 发送消息 | 固定链接 | 查看引用通告 (0) | 写入日志 | 我的技术文章
Java Portlet应用开发 (JSR168), Part 3 - PortletConfig 对象
By Jia.li(Terry.li)
SpiritSeekerS@sqatester.com


本部份将讲述PortletConfig对象及其PortletContext对象的概念及应用.

• PortletConfig对象
和ServletConfig对象类似, PortletConfig对象提供Portlet初始的所需的参数及其对PortletContext对象存取提供相关方法.
和ServletConfig不同处在于, PortletConfig对象提供对Portlet Title Bar资源的I18N支持,我们可以设定不同的Resource Bundle文件用以提供多语言的支持, 如下portlet.xml文件:

… …
<portlet-info>
<title>PortletConfig Example</title>
<short-title>PortletConfig</short-title>
<keywords>PortletConfig</keywords>
</portlet-info>
… …

以上Portlet描述文件中的设置用于显示Portlet的Title Bar文字, 同样也可以使用Resource Bundle用以显示Title Bar文字, 如下:

… …
<resource-bundle>
portlets.portletconfig.portletconfigexample
</resource-bundle>
… …


• A case study

这里我们将开发一个简单使用Resource Bundle的Portlet.只需要添加所须的Resource Bundle文件.

我们使用英文及其中文的Resource Bundle, 如下:

3) Base Resource Bundle (portletconfigexample.properties)

# English Resource Bundle
#
# filename: portletconfigexample.properties
# Portlet Info resource bundle example
javax.portlet.title=PortletConfig Example
javax.portlet.short-title=PortletConfig
javax.portlet.keywords=PortletConfig

2) Chinese Resource Bundle (portletconfigexample_zh.properties)

# Chinese Resource Bundle
#
# filename: portletconfigexample.properties
# Portlet Info resource bundle example
javax.portlet.title=Portlet配置 例子
javax.portlet.short-title=Portlet配置
javax.portlet.keywords=Portlet配置


3) portlet.xml

… …
<resource-bundle>
portlets.portletconfig.portletconfigexample
</resource-bundle>
… …





• 源代码及Portlet相关配置文件

1) Portlet (PortletConfigExample.java)

package portlets.portletconfig;

/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/

import javax.portlet.*;
import java.io.IOException;
import java.io.Writer;

public class PortletConfigExample extends GenericPortlet{

public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");
String view = getPortletConfig().getInitParameter("view");
Writer writer=response.getWriter();
writer.write(view);
}

public void doEdit(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");
String edit = getPortletConfig().getInitParameter("edit");
Writer writer=response.getWriter();
writer.write(edit);
}

}


2) Portlet.xml

… …
<!-- PortletConfig Example -->
<portlet>
<description>PortletConfig Example</description>
<portlet-name>PortletConfigExample</portlet-name>
<display-name>disPortletConfigExample</display-name>
<portlet-class>portlets.portletconfig.PortletConfigExample</portlet-class>
<init-param>
<name>view</name>
<value>Here is View Mode</value>
</init-param>
<init-param>
<name>edit</name>
<value>Here is Edit Mode</value>
</init-param>
<expiration-cache>-1</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
</supports>
<supported-locale>zh</supported-locale>
<supported-locale>en</supported-locale>
<resource-bundle>portlets.portletconfig.portletconfigexample</resource-bundle>
</portlet>
… …

3) pageregistry.xml

… …
<!-- PortletConfig Example Page -->
<fragment name="portletconfigpage" type="page">
<navigation>
<title>PortletConfig Example Page</title>
<description>PortletConfig Example Page</description>
</navigation>
<fragment name="row1" type="row">
<fragment name="col1" type="column">
<fragment name="p1" type="portlet">
<property name="portlet" value="10.20"/>
</fragment>
</fragment>
</fragment>
</fragment>
… …

4) PortletRegistry.xml

… …
<portlet id="20">
<definition-id>portlets.PortletConfigExample</definition-id>
</portlet>
… …


将以上源代码编译后, 再通过Eclipse生成/更新Portlet的web.xml后, 将所有配置及相关文件部署后, 启动Tomcat.



在Browser中加载如下页面: Http://localhost:8080/pluto/portal , 可以看到如下的页面(图:3-1)

如果机器的Locale及语言设定是以中文简体为缺省,则单击PortletConfig Example Page后可以看到如下Portlet 页面(图3-1):

图3-1

注: 因为现在Pluto的开发中没有做I18N的处理,这里如果你的机器的Locale是中文的话, 显示是乱码,请将IE的encoding设定为GB2312(View -> Encoding -> Chinese Simplified), 如图3-1.


如果机器的Locale及语言设定是英文的话, 将看到如下Portlet 页面(图3-2):

图3-2



资源:
• Pluto
http://jakarta.apache.org/pluto

• Pluto Mail List
http://news.gmane.org/gmane.comp.jakarta.pluto.user

• WSRP Spec1.0
http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsrp

• Apache的WSRP实现
http://ws.apache.org/wsrp4j/

• Apache’s Portal, JetSpeed:
http://jakarta.apache.org/jetspeed/site/index.html

• JSR 168:
http://www.jcp.org/en/jsr/detail?id=168
• "Portlet 规范介绍" By Stefan Hepper 和 Stephan Hesmer
Part 1: Get your feet wet with the specification's underlying terms and concepts (August 2003)
Part 2: The Portlet API's reference implementation reveals its secrets (September 2003)

11:18:16 | 添加评论 | 发送消息 | 固定链接 | 查看引用通告 (0) | 写入日志 | 我的技术文章
Java Portlet应用开发 (JSR168), Part 2 - Pluto中添加新的Portal Page 和 Portlet
By Jia.li(Terry.li)
SpiritSeekerS@sqatester.com


本部分使用本系列中Part1搭建的开发环境,如果还没有搭建好开发环境,请参考Portlet应用开发(JSR168),Part1进行开发环境的搭建.

在Part1中,我们开发了一个简单的portlet程序,但是几乎所有的代码和文件都是由Eclipse的pluto plugin替我们完成的,如何配置用来在Pluto中的Portal中添加新的Portal Page并且将新的Portlet添加到新的Page中去呢? Part2将一步一步教你如何创建一个新Portal Page.


• Portal的设定
Tomcat 中Webapps目录: 其中pluto是portal所在目录, 用以配置Portal Page的两个文件分别是pageregistry.xml和portletentityregistry.xml (如图Figure1_1)




Figure1_1


其中pageregistry.xml用来在Portal中配置Portal Page, 而portletentityregistry.xml 用来在Page中配置Portlet.

• portletentityregistry.xml
打开pageregistry.xml, 内容如下 :

<?xml version="1.0" encoding="UTF-8"?>
<portlet-entity-registry>
<application id="1">
<definition-id>portlets</definition-id>
<portlet id="1">
<definition-id>portlets.SimplePortlet</definition-id>
</portlet>
</application>
</portlet-entity-registry>

其中application 标签表明了目前的application 的 ID, portlet标签定义了一个Portlet , 如果你新开发了一个Portlet , 可以加入以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<portlet-entity-registry>
<application id="1">
<definition-id>portlets</definition-id>
<portlet id="1">
<definition-id>portlets.SimplePortlet</definition-id>
</portlet>
<portlet id="2">
<definition-id>portlets.IntroPortlet</definition-id>
</portlet>
</application>
</portlet-entity-registry>

这样一来你又在portal中注册了一个新的Portlet,接下来是将新注册的Portlet加入Page中.

• pageregistry.xml
打开pageregistry.xml, 内容如下 :

<?xml version="1.0"?>
<portal>

<fragment name="navigation" class="org.apache.pluto.portalImpl.aggregation.navigation.TabNavigation">
</fragment>

<fragment name="sample" type="page">
<navigation>
<title>Sample Portlet</title>
<description>Basic page to show the simple portlet</description>
</navigation>

<fragment name="row" type="row">

<fragment name="col1" type="column">

<fragment name="p1" type="portlet">
<property name="portlet" value="1.1"/>
</fragment>

</fragment>

</fragment>

</fragment>
</portal>

以上是sample portlet的配置.

Fragment标签用来配置navigation(导航栏), Page,以及Page中的Column和Row.
分别用fragment标签的type属性来标识. Pluto自带的Portal使用fragment标签来配置及处理简单的Portlet Layout.

<property name="portlet" value="1.1"/>中的value值是在portletentityregistry.xml中定义的. 分别对应application id 和portlet id, 将其值用”.”连接起来使用用以定义一个Portlet. 同样 , 如果使用<property name="portlet" value="1.2"/>,则将使用portlets.IntroPortlet.



1) 配置同一行中的两个Portlet, 如下:
<?xml version="1.0"?>
<portal>

<fragment name="navigation" class="org.apache.pluto.portalImpl.aggregation.navigation.TabNavigation">
</fragment>

<fragment name="sample" type="page">
<navigation>
<title>Sample Portlet</title>
<description>Basic page to show the simple portlet</description>
</navigation>

<fragment name="row" type="row">

<fragment name="col1" type="column">

<fragment name="p1" type="portlet">
<property name="portlet" value="1.1"/>
</fragment>

<fragment name="p2" type="portlet">
<property name="portlet" value="1.1"/>
</fragment>

</fragment>

</fragment>

</fragment>

</portal>


2) 配置同一列中的两个Portlet, 如下:
<?xml version="1.0"?>
<portal>

<fragment name="navigation" class="org.apache.pluto.portalImpl.aggregation.navigation.TabNavigation">
</fragment>

<fragment name="sample" type="page">
<navigation>
<title>Sample Portlet</title>
<description>Basic page to show the simple portlet</description>
</navigation>

<fragment name="row1" type="row">

<fragment name="col1" type="column">

<fragment name="p1" type="portlet">
<property name="portlet" value="1.1"/>
</fragment>

</fragment>

</fragment>

<fragment name="row2" type="row">

<fragment name="col1" type="column">

<fragment name="p1" type="portlet">
<property name="portlet" value="1.1"/>
</fragment>

</fragment>

</fragment>

</fragment>

</portal>





• Portlet Modes 和 Portlet window states
Portlet模式(Portlet Mode)是Portlet提供的用以区分 Portlet所执行功能的一个概念.通常情况下其拥有以下几种模式:
1. VIEW
2. EDIT
3. HELP

以上各模式分别对应GenericPortlet中的 doView(…) , doEdit(…) , doHelp(…) 方法,分别调用以上方法来产生各个模式中的Fragment内容. 非常类似Servlet中的doGet(…) , doPost(…) 方法,都是Helper方法, 但是概念不同.

Portlet状态(Portlet window states)提供了对于Portlet窗口的控制功能 , 其中有如下三种最基本的状态:
1. Normal
2. Maximized
3. Minimized

Portlet开发人员可以在处理ActionRequest (以后的章节将讲述其概念) 时使用代码实现Portlet模式, 及其Portlet状态的转变.

注: 只能在处理ActionRequest时改变Portlet Modes和Portlet Window states.

以上Portlet Modes和Portlet window states都可以配置成custom Portlet mode和custom portlet window state. 不同的地方在于对于Mode来说, 定制化的Mode需要对GenericPortlet的doDispatch方法进行重写(Overriding), 因为GenericPortlet类通过render方法按照不同的Portlet Mode将request分别分发给doView,doEdit,doHelp等辅助方法. 如果需要定制的Mode , 必须重写doDispatch 方法. 同时如果使用Portal提供商的Portlet Modes 或者 Portlet window States,都必须在部署描述中添加相关的设定.

A. 添加Custom Portlet Modes
以下使用代码实现了一个新的Portlet Mode: CONFIG , 当然也可以使用Portal提供商支持的Portlet Mode. 但是需要Mapping到Portal提供商所支持的Portlet Mode. 使用如下描述:

<custom-portlet-mode>
<description>Provides administration functions</description>
<portlet-mode>CONFIG</portlet-mode>
</custom-portlet-mode>

1. Portlet代码 (CustomPortletModeExample.java)

package portlets.portletmode;

/**
* @author terry
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
import javax.portlet.*;
import java.io.IOException;

public class CustomPortletModeExample extends GenericPortlet{

public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");

String jspName = getPortletConfig().getInitParameter("all");

PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);

rd.include(request, response);
}

public void doEdit(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");

String jspName = getPortletConfig().getInitParameter("all");

PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);

rd.include(request, response);
}

public void render(RenderRequest request, RenderResponse response)
throws PortletException, IOException{
doDispatcher(request,response);
}

public void doDispatcher(RenderRequest request, RenderResponse response)
throws PortletException, IOException{
if(!request.getWindowState().equals(WindowState.MINIMIZED)){
if(request.getPortletMode().equals(PortletMode.VIEW)){
doView(request,response);
}else if(request.getPortletMode().equals(PortletMode.EDIT)){
doEdit(request,response);
}else if(request.getPortletMode().equals(new PortletMode("CONFIG"))){
doConfig(request,response);
}
}
}

public void doConfig(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
response.setContentType("text/html");

String jspName = getPortletConfig().getInitParameter("all");

PortletRequestDispatcher rd =
getPortletContext().getRequestDispatcher(jspName);

rd.include(request, response);
}

public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException
{
String action=request.getParameter("ACTION");
System.out.println("ACTION" + action);
if(action==null){
action="";
}
response.setRenderParameter("ACTION",action);
}
}

2. JSP(all_mode.jsp)

<%@ page session="false" %>
<%@ page import="javax.portlet.*"%>
<%@ page import="java.util.*"%>
<%@ taglib uri='/WEB-INF/tld/portlet.tld' prefix='portlet'%>
<portlet:defineObjects/>
<br>
<h3>Custom Portlet Mode Example</h3>
Current Portlet Mode: <b><%=renderRequest.getPortletMode()%></b><br>
Current Window State: <b><%=renderRequest.getWindowState()%></b><br>
<br>



5. Portlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="/org/apache/pluto/portalImpl/xml/portlet-app_1_0.xsd" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="/org/apache/pluto/portalImpl/xml/portlet-app_1_0.xsd /org/apache/pluto/portalImpl/xml/portlet-app_1_0.xsd">

<!-- Custom PortletMode Example -->
<portlet>
<description>CustomPortletModeExample Example</description>
<portlet-name>CustomPortletModeExample</portlet-name>
<display-name>CustomPortletModeExample</display-name>
<portlet-class>portlets.portletmode.CustomPortletModeExample</portlet-class>
<init-param>
<name>all</name>
<value>/fragments/portletmode/all_mode.jsp</value>
</init-param>
<expiration-cache>-1</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
<portlet-mode>CONFIG</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>Custom PortletMode Example</title>
<short-title>PortletMode</short-title>
<keywords>PortletMode</keywords>
</portlet-info>
</portlet>

</portlet-app>

6. portletregistry.xml.

<?xml version="1.0" encoding="UTF-8"?>
<portlet-entity-registry>
<application id="10">
<definition-id>portlets</definition-id>
<portlet id="10">
<definition-id>portlets.CustomPortletModeExample</definition-id>
</portlet>
</application>
</portlet-entity-registry>

7. pageregistry.xml

<?xml version="1.0"?>
<portal>

<fragment name="navigation" class="org.apache.pluto.portalImpl.aggregation.navigation.TabNavigation">
</fragment>

<!-- Custom PortletMode Example Page -->
<fragment name="customportletmodepage" type="page">
<navigation>
<title>Custom PortletMode Example Page</title>
<description>Custom PortletMode Example Page</description>
</navigation>
<fragment name="row1" type="row">
<fragment name="col1" type="column">
<fragment name="p1" type="portlet">
<property name="portlet" value="10.10"/>
</fragment>
</fragment>
</fragment>
</fragment>

</portal>



将以上源代码编译后, 再通过Eclipse生成/更新Portlet的web.xml后, 将所有配置及相关文件部署后, 启动Tomcat.



在Browser中加载如下页面: Http://localhost:8080/pluto/portal , 可以看到如下的页面(图:2_1)

图2-1


单击Custom PortletMode Example Page后可以看到如下Portlet 页面:


图2-2

单击右上角的config后,可以看到如下页面片段:


图2-3

以上可以看到新添加的Portlet Mode: config.


B. 添加Custom Window States

添加新的window states同样需要在配置文件中加入相应的描述,如下:
<custom-window-state>
<description>Occupies 50% of the portal page</description>
<name>half_page</name>
</custom-window-state>

但是同样需要Mapping到Portal提供商所支持的Window state.

总结:
因为Eclipse 的Pluto plugin使用的是version1.0 , 所以可能有许多Bugs或者没有实现的功能, 所以如果需要最新版本的Pluto , 可以在Apache的CVS上下载, 下载的代码中有现成的Build scripts 以及相关的deploy script.请参考相关文档资料.

累了,去[url=http://www.diy567.com]读意优[/url]休息一下下,QQ空间,美文,非主流,网络日记,搞笑短信,祝福短信,热门短信,有意思啊
基于SSM框架的智能家政保洁预约系统,是一个旨在提高家政保洁服务预约效率和管理水平的平台。该系统通过集成现代信息技术,为家政公司、家政服务人员和消费者提供了一个便捷的在线预约和管理系统。 系统的主要功能包括: 1. **用户管理**:允许消费者注册、登录,并管理他们的个人资料和预约历史。 2. **家政人员管理**:家政服务人员可以注册并更新自己的个人信息、服务类别和服务时间。 3. **服务预约**:消费者可以浏览不同的家政服务选项,选择合适的服务人员,并在线预约服务。 4. **订单管理**:系统支持订单的创建、跟踪和管理,包括订单的确认、完成和评价。 5. **评价系统**:消费者可以在家政服务完成后对服务进行评价,帮助提高服务质量和透明度。 6. **后台管理**:管理员可以管理用户、家政人员信息、服务类别、预约订单以及处理用户反馈。 系统采用Java语言开发,使用MySQL数据库进行数据存储,通过B/S架构实现用户与服务的在线交互。系统设计考虑了不同用户角色的需求,包括管理员、家政服务人员和普通用户,每个角色都有相应的权限和功能。此外,系统还采用了软件组件化、精化体系结构、分离逻辑和数据等方法,以便于未来的系统升级和维护。 智能家政保洁预约系统通过提供一个集中的平台,不仅方便了消费者的预约和管理,也为家政服务人员提供了一个展示和推广自己服务的机会。同时,系统的后台管理功能为家政公司提供了强大的数据支持和决策辅助,有助于提高服务质量和管理效率。该系统的设计与实现,标志着家政保洁服务向现代化和网络化的转型,为管理决策和控制提供保障,是行业发展中的重要里程碑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值