By Terry.lee
本部分使用本系列中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.请参考相关文档资料.
资源:
· 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)