分享

liferay二次开发指南

 WindySky 2017-07-28
2.6.2 portlet.xml
portlet.xml用来定义Portlet的诸如部署名称、初始化参数、支持模式、resource bundle等普通的初始化信息,包括:portlet-name、display-name、portlet-class、init-param、expiration-cathe、supports、portlet-info、security-role-ref等等。其正式的规范请参考:http://java./xml/ns/Portlet/Portlet-app_1_0.xsd 。根目录为portlet-webapp。
portlet-name:Portlet的规范名称,在Portlet应用中必须唯一,主要用在Portlet部署和映射中。
display-name:供部署工具调用的Portlet简称,在Portlet应用中必须唯一。
portlet-class:Portlet对应的类,这个类必须直接或者间接的继承javax.Portlet.GenericPortlet。
init-param:初始化参数,有成对的<name>和<value>子元素。通常定义Portlet相应模式下可用的JSP页面。
expiration-cathe:定义Portlet加载允许最长的过期时间,以秒为单位。-1代表用不过期。
supports:定义Portlet支持的模式。所有的Portlet都必须支持浏览模式。
其他的元素含义请参照:http://java./xml/ns/Portlet/Portlet-app_1_0.xsd
当Web 应用中有多个的Portlet时,可以统一的在Portlet。xml中定义一组的<portlet>元素。
       <portlet>
              <portlet-name>TestPortlet</Portlet-name>
              <display-name>TestPortlet</display-name>
              <portlet-class>com.educhina.portal.FirstPortlet</Portlet-class>
              <init-param>
                     <name>view-jsp</name>
                     <value>/view.jsp</value>
              </init-param>
              <init-param>
                     <name>edit-jsp</name>
                     <value>/edit.jsp</value>
              </init-param>
              <expiration-cache>0</expiration-cache>
              <supports>
                     <mime-type>text/html</mime-type>
              </supports>
              <supports>
                     <mime-type>text/html</mime-type>
                     <Portlet-mode>edit</Portlet-mode>
              </supports>
              <portlet-info>
                     <title>educhina Test Portlet</title>
                     <short-title> educhina Test Portlet </short-title>
                     <keywords> educhina Test Portlet </keywords>
              </portlet-info>
              <security-role-ref>
                     <role-name>guest</role-name>
              </security-role-ref>
       </portlet>
 
2.6.3 liferay-Portlet.xml
定义Portlet默认可用的用户组、默认模板、是否支持多个实例等,规范由http://www./dtd/liferay-Portlet-app_3_5_0.dtd 定义。
liferay-portlet.xml主要包含单独或者成组的<portlet>、<role-mapper>。其中,<portlet>下包含<portlet-name>、<struts-path>、<use-default-template>、<instanceable>等子元素,<portlet-name>在应用中必须唯一,且要跟portlet.xml相同;<role-mapper>下包含成对的<role-name>、<role-link>子元素。具体的元素含义请查看上述dtd定义。
<liferay-portlet-app>
       <portlet>
              <portlet-name> TestPortlet </portlet-name>
              <struts-path> TestPortlet </struts-path>
              <use-default-template>true</use-default-template>
              <instanceable>true</instanceable>
       </portlet>
       <role-mapper>
              <role-name>administrator</role-name>
              <role-link>Administrator</role-link>
       </role-mapper>
       <role-mapper>
              <role-name>guest</role-name>
              <role-link>Guest</role-link>
       </role-mapper>
       <role-mapper>
              <role-name>power-user</role-name>
              <role-link>Power User</role-link>
       </role-mapper>
       <role-mapper>
              <role-name>user</role-name>
              <role-link>User</role-link>
       </role-mapper>
</liferay-portlet-app>
2.6.4 liferay-display.xml
定义Portlet默认的所属类别。Liferay Portal对Portlet实行按类别管理和划分用户权限。正如我们在用户策略中提到的,可以制定某个类别可用的用户组、用户和角色,方便权限控制。Liferay-display.xml规范由http://www./dtd/liferay-display_3_5_0.dtd 定义。
Liferay-display.xml中,<display>下成组的<category>描述了可用的类别,其中portlet元素的id必须与liferay-portlet.xml的portlet-name保持一致,且在应用中唯一。
<display>
       <category name="category.test">
              <portlet id="TestPortlet" />
       </category>
</display>
2.6.5 liferay-layout-templates.xml
定义Portal可用的布局。正如我们在布局与品质中提到的那样,Portal采用tpl文件来规划桌面的布局。liferay-layout-templates。xml采用成组的layout-template来构建一个可用的布局列表。此xml的规范由http://www./dtd/liferay-layout-templates_3_6_0.dtd 来定义。
本文采用Liferay Portal默认的布局,暂时不需要定义自己的布局,故不准备深入讨论。读者有兴趣可以自己查看相关资料。
<layout-templates>
       <layout-template id="1_column" name="1 Column">
              <template-path>/html/layouttpl/1_column。tpl</template-path>
       </layout-template>
       <layout-template id="2_columns_i" name="2 Columns (50/50)">
              <template-path>/html/layouttpl/2_columns_i。tpl</template-path>
       </layout-template>
       <layout-template id="3_columns" name="3 Columns">
              <template-path>/html/layouttpl/3_columns。tpl</template-path>
       </layout-template>
       <layout-template id="1_2_1_columns" name="1-2-1 Columns">
              <template-path>/html/layouttpl/1_2_1_columns。tpl</template-path>
       </layout-template>
</layout-templates>
2.6.7 liferay-look-and-feelxml
定义Portal可用品质的模板、图片、样式表等等,定义完毕后,Portal可以通过“布局与品质”管理工具来进行品质的切换。Liferay-look-and-feel.xml规范由http://www./dtd/liferay-look-and-feel_3_5_0.dtd 定义。
本文采用Liferay Portal默认的品质,不准备对品质的自定义深入探讨。有兴趣的读者可以查看相关资料。
第二部分 Liferay Portal 二次开发
本部分主要内容
GenericPortlet 自定义Portlet类 部署描述文件
第三章 开发自己的Portlet
在了解了Liferay Portal的基础架构,初步体会Liferay Portal良好的个性化定制之后,本章将开始Liferay Portal二次开发之旅,讲述并扩展Portlet的超类GenericPortlet,创建或者修改部署描述文件,构建属于自己的Portlet。
第一节  重要的基类:GenericPortlet
像Servlet一样,编写的Portlet也必须直接或者间接的扩展基类GenericPortlet,这个是由JCP针对Portal提出的JSR168规范定义的。只要扩展自规范的GenericPortlet,所有的Portlet都可以在支持JSR168规范的Portal服务器上运行。
GenericPortlet统一定义了可供Portal容器识别和调用的方法,包括:
public Init():初始化;
public Init(PortletConfig) :初始化;
public getInitParameter(String):取得在Portlet。xml中定义的初始化参数;
public getInitParameterNames():取得在Portlet。xml中定义的全部初始化参数;
public getPortletConfig():取得包含初始化参数的配置对象PortletConfig实例;
public getPortletContext():取得Portlet上下文;
public getPortletName():取得在Portlet。xml中定义的Portlet名称。
public getResourceBundle(Locale) :取得Portlet国际化的Resource Bundle;
protected getTitle(RenderRequest) :取得Portlet的标题;
protected doView(RenderRequest,RenderResponse) :Portlet浏览模式的处理方法;
protected doEdit(RenderRequest,RenderResponse) :Portlet编辑模式的处理方法;
protected doHelp(RenderRequest,RenderResponse) :Portlet帮助模式的处理方法;
protected doDispatch(RenderRequest,RenderResponse) :Portlet行为分发;
protected processAction(RenderRequest,RenderResponse) :Portlet处理Action Request的方法;
protected render(RenderRequest,RenderResponse):Portal处理Render Request的方法;
public destroy():Portlet销毁,终止其生命周期。
在Portlet Portal运行的时候,doView、doEdit、doHelp三个方法分别被调用,用以生成Portlet标记。同样也可以调用Servlet生成Portlet标记,或者不调用JSP或者Servlet,直接在方法中得到PrintWriter然后用最简单的pw.println()打印出内容。这个过程类似Servlet,如下:
PrintWriter pw = renderResponse.getWriter();
pw.println(“Hello,world!”);
与Servlet类似,可以使用getInitParamter(String s)得到配置文件中Portlet的初始值,只不过Servlet在web.xml中,而Portlet在portlet.xml中。
portlet.xml:
<init-param>
<name>jspView</name>
<value>/jsp/view。jsp</value>
</init-param>
针对如上portlet.xml中的初始化信息,可以采用如下的调用方式:
SimplePortlet.java:
String jspName = getPortletConfig()。getInitParameter("jspView");
第二节  Portlet标签
跟Servlet一样,Portlet也自定义了很多灵活的标签。通过这些标签,可以调用Portlet内部的参数比如renderResponse、renderRequest、PortletConfig等,在JSP中跟Portlet通信。当然,在使用之前,除了要在web。xml中声明标签库外,还要在JSP的头部声明标签库调用:<%@ taglib uri="http://java。sun。com/Portlet" prefix="Portlet" %>
3.2.1  defineObjects标签
在使用Portlet典型标签之前,要见声明<portlet:defineObjects/>,这样才可以使用其他的标签。defineObjects中间不允许定义任何属性和包含任何内容。
3.2.2  renderURL标签
属性 值类型 对应值
windowState String minimized
normal
maximized。
PortletMode String view, edit , help
var String
secure
String true
false
创建一个当前RenderURL,当访问它时将使Portlet窗口变为最大化状态,模式变为浏览。<portlet:param/>子元素会在生成的RenderURL中增加number、page两个参数和值。
3.2.3  actionURL标签
属性 值类型 对应值
windowState String minimized
normal
maximized。
portletMode String view, edit , help
var String
secure
String true
false
<portlet:actionURL windowState="normal" PortletMode="edit">
<portlet:param name="action" value="login"/>
</portlet:actionURL>
创建一个当前ActionURL,当访问它时将使Portlet窗口变为正常状态,模式变为编辑。<Portlet:param/>子元素会在生成的ActionURL中增加action参数和值。
renderURL和actionURL两个标签在诸如生成form表单的action等方面特别有用。
3.2.4  param标签
属性 值类型
name String
用在renderURL和actionURL标签内部,用来在生成的URL中增加参数和值。param标签不运行body内容存在。
3.2.5  namespace标签
为目前的Portlet产生一个唯一的Value,防止与其他Portlet或者Portal上面的Value冲突。
上述标签的具体属性及其约束,请参阅{PORTAL_HOME}/liferay/WEB-INF/tld/liferay-portlet.tld 。
第三节  Portal的对象
JSR168给Portal定义了几个特别的对象,用来操作Portal特有的信息。这些对象跟Servlet的对象有点类似,又有点不同。这些对象都封装在{PORTAL_HOME}/common/lib/ext/portlet.jar包中,具体支持实现要视Portal服务器而定。
3.3.1  Request对象
Portlet中的Request与Servlet的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方法。
①、RenderRequest和ActionRequest
PortletRequest分为RenderRequest和ActionRequest两种,分别由renderURL和actionURL来触发。renderURL是actionURL的一种优化。Portlet的开发过程中尽量使用renderURL而避免actionURL。actionURL适用于有确实的Action(行为)的情况下。比如说,表单form提交后Persistent状态的改变、session的改变、perference的修改等等。renderURL通常用来处理Portlet的导航。举个例子:
使用actionURL:
<%
PortletURL pu = renderResponse.createActionURL();
pu.setParameter("ACTION","LOGIN");
<form name="usrform" method="post" action="<%=pu.toString()%>">
%>
说明:表单提交最好使用Post方法而不是Get方法,因为某些Portal服务器可能会将内部状态编码到URL的Query字符串中。
使用renderURL:
<%
PortletURL pu=renderResponse.createRenderURL();
Pu.setParameter("PAGE",Number);
%>
<a href="<%=pu%>">下一页</a>
②、renderURL和actionURL的处理方式
当客户端请求是由一个renderURL触发的时候,Portal服务器会调用该Portal页面所有Portlet的render方法。
而当客户端请求是由一个actionURL触发的时候,Portal服务器会先按用该页面所有Portlet的processAction方法再调用render方法。所以,要明确自己到底使用那种URL来出发客户端请求。
③、RenderRequest和ActionRequest的parameter参数作用范围
当客户端请求由一个actionRequest触发时,所有parameter参数的取得都必须在processAction方法中进行。比如:
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方法中,getParameter方法将能成功得到表单中的参数ACTION所对应的值,因为我们知道,当目标Portlet的processAction方法运行完后,Portlet Container将调用Portal页面中所有Portlet的render方法.但是实际上doView方法中使用getParameter不会得到任何值.但是如果把processAction方法中注释了的一行解除注释的话,你就可以在doView方法中的得到参数ACTION对应的值. 这说明action request的参数,render方法中不可以直接取到.必须使用了setRenderParameter方法,再次传递一次.
3.3.2  Response对象
与Request对象一样,Response对象也有两种:RenderResponse和ActionResponse,分别用来封装对应的RenderRequest和ActionRequest的返回信息,比如重定向、窗口状态、Portlet模式等。他们两者的父类PortletResponse拥有serPorperty和getPorperty两个方法,用来传递信息给Portal容器。
ActionResponse主要用来处理以下功能:
a、 重定向
b、 改变窗口状态、Portlet模式
c、 传递parameter参数到RenderRequest中去
RenderResponse主要用来提供以下功能:
a、 设置ContentType
b、 得到OutputStream和Writer对象,用来输出页面内容
c、 Buffering缓冲
d、 设定Portlet的标题,但是必须在Portlet输出前调用,否则将被忽略
3.3.3  PortletConfig对象
和ServletConfig对象类似,PortletConfig对象提供对Portlet初始化信息以及PortletContext对象存取的方法。
和ServletConfig对象不同的是,PortletConfig对象提供对Portlet的标题等资源的I18N支持,可以通过设定不同的Resource Bundle文件以提供多种语言支持。
3.3.4  Session对象
由于容器不同,Portal的Session对象与Servlet的Session对象略有不同。
由于Portlet处于Portal服务器的缘故,Portlet的Session分为Application Scope和Portlet Scope。两者的区别在于:
①、Application Scope范围的Session中保存的对象,对于同一个Portlet应用范围内的所有Portlet都是可用的。
②、Portlet Scope范围的Session中保存的对象,只对本Portlet可用,其他Portlet即使在同一个应用中,也不可用。
但是对于Portlet应用来说,可以通过HttpSession来访问。毕竟Portlet应用也是Web应用。在使用Session对象的时候,最好能明确指出使用的是那个Scope范围的Session。比如:
<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>
这个JSP创建了两个ActionURL,分别产生了两种PortletSession对象。
PortletSession ps = req.getPortletSession();
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();
}
以上代码根据需要取得不同Scope范围的Session对象值。
同一个应用下,可以直接通过ServletSession取得PortletSession。APPLICATION_SCOPE范围下的Session对象值。
HttpSession se = request.getSession();
if(se.getAttribute("PortletSession.AS")!=null){
app=se.getAttribute("PortletSession.AS");
}
3.3.5  Preference对象
Preference对象被设计用来实现用户的个性化设置,可以帮助用户对Portlet进行符合用户需求的显示定制和行为定制,可以替代部分的数据库功能。需要指出的是,Preference对象只是用来存取简单的配置信息,并不能完全替代数据库应用。
Preference对象对于配置信息采用键-值的形式存取,用户可以将需要的信息暂时保存在Preference中。
PortletPreference p= req.getPortletPreferences();
p.setValue("educhina.username","educhina");
p.store();
Preference对象用来存取用户的个性化信息,所以不同用户的Preference对象不能共享,这点跟Session不同。
可以在Portlet.xml中配置Preference信息,如下:
<Portlet-preferences>
  <preference>
    <name>educhina。username</name>
    <value>educhina</value>
    <read-only>true</read-only>
  </preference>
</Portlet-preferences>
另外,还可以配套使用PreferencesValidator对象,对Portlet的Preference在存储之前进行验证,以确保Preference的正确性。
具体规范可以参照http://java./xml/ns/Portlet/Portlet-app_1_0.xsd 的<complexType name="preferenceType">部分。
第四节  编写自己的Portlet类
Liferay Portal内部集成了78个Portlet,包括直接用PrintWriter输出的、调用JSP输出的、调用Servlet输出的,数据来源有直接从数据库取得的、通过Web Service取得的等等。这里,我们只讲述直接用PrintWriter输出的和调用JSP输出的,目的在于讲述如何编写自己的Portlet类。其他的与此类似,不赘述。
3.4.1  开发环境
IDE:Eclipse V3.0.1
JDK:V1.4.2_06
ANT:V1.6.2
Tomcat:V5.0(集成在Liferay Portal中)
Liferay Portal:liferay-portal-pro-3.6.0-tomcat
3.4.2  准备工作
①、安装JDK V1.4.2_06,在系统环境变量中增加变量JAVA_HOME,指向JDK安装目录。
②、安装ANT,在系统环境变量中增加变量ANT_HOME,指向ANT安装目录。
③、下载并启动Eclipse V3.0.1.
④、下载并解压缩liferay-portal-pro-3.6.0-tomcat.zip到某一文件夹,该文件夹即为{PORTAL_HOME}。
⑤、在Eclipse中新建一个Java项目,命名为TestPortal,路径为D:/TestPortal,将{PORTAL_HOME}/common/ext/portlet.jar以外部jar的形式添加到库中。下文中,D:/TestPortal将以{APP_HOME}代称。在{APP_HOME}下创建文件夹webapp、deploy、bak。项目缺省输出文件夹为{APP_HOME}/webapp/WEB-INF/classes 。
⑥、在{APP_HOME}/webapp/WEB-INF目录下创建web.xml,内容如下:
<?xml version="1。0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc。//DTD Web Application 2。3//EN" "http://java。sun。com/dtd/web-app_2_3。dtd">
<web-app>
<display-name>TestPortal</display-name>
</web-app>
⑦、在{APP_HOME}/webapp/WEB-INF下创建tld文件夹,将{PORTAL_HOME}/liferay/WEB-INF/tld/liferay-portlet.tld拷贝到创建的tld文件夹下,备用。
⑧、新建一个Java包com.educhina.portal 。
3.4.3  HelloWorldPortlet
HelloWorldPortlet类计划用单纯的PrintWriter输出Portlet标记片断。在包com.educhina.portal下新建Java类HelloWorldPortlet,这个类必须扩展自javax.Portlet.GenericPortlet类。设计让HelloWorldPortlet支持浏览和编辑两种模式,所以HelloWorldPortlet重写doView和doEdit方法。简单的代码如下:
package com.educhina.portal;
import java.io.IOException;
import javax.Portlet.GenericPortlet;
import javax.Portlet.PortletException;
import javax.Portlet.RenderRequest;
import javax.Portle.RenderResponse;
public class HelloWorldPortlet extends GenericPortlet{
public void doView(RenderRequest req, RenderResponse res)
throws IOException, PortletException {
res.setContentType("text/html");
res.getWriter().println("HelloWorld!");
}
public void doEdit(RenderRequest req,RenderResponse res)
throws IOException,PortletException {
res.setContentType("text/html");
res.getWriter().println("HelloWorld!");
}
}
doView和doEidt方法从RenderRequest取得PrintWriter对象,直接输出一个String字符“HelloWorld!”。这个String字符将作为HelloWorldPortlet的片断内容。
 
3.4.4  HelloJSPPortlet
HelloJSPPortlet类计划调用外部JSP输出。同样的,HelloJSPPortlet也要扩展自GenericPortlet类。HelloJSPPortlet调用getPortletConfig().getInitParameter("..")方法,取得在Portlet。xml中配置的view-jsp和edit-jsp参数值,以此确定JSP页面的具体位置。然后调用PortletRequestDispatcher的include方法,将JSP页面加载到RenderResponse。代码如下:
package com.educhina.portal;
import java.io.IOException;
import javax.Portlet.GenericPortlet;
import javax.Portlet.PortletException;
import javax.Portlet.PortletRequestDispatcher;
import javax.Portlet.RenderRequest;
import javax.Portlet.RenderResponse;
public class HelloJSPPortlet extends GenericPortlet{
public void doView(RenderRequest req, RenderResponse res)
throws IOException, PortletException {
res.setContentType("text/html");
String jspName = getPortletConfig().getInitParameter("view-jsp");
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(jspName);
rd.include(req,res);
}
public void doEdit(RenderRequest req,RenderResponse res)
throws IOException,PortletException {
res.setContentType("text/html");
String jspName = getPortletConfig().getInitParameter("edit-jsp");
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(jspName);
rd.include(req,res);
}
}
在{APP_HOME}/webapp目录下创建view.jsp和edit.jsp,view.jsp代码如下,edit.jsp类似:
<table cellpadding="8" cellspacing="0" width="100%">
<tr>
<td>
<font class="Portlet-font" style="font-size: x-small;">
This is a <b>Sample JSP Portlet</b> used in viewing model。 Use this as a quick way to include JSPs。
</font>
</td>
</tr>
</table>
JSP文件不能包含关于HTML的<head>、<body>、<html>的信息,只能包含原来位于<body></body>内部的HTML内容。那些<head>、<body>、<html>信息由Portal页面来提供。
只有在JSP页面中使用<%@ taglib uri="http://java./portlet" prefix="portlet" %>和<portlet:defineObjects/>,JSP页面才可以直接操作Portlet的一些变量,比如:renderResponse、renderRequest、portletConfig。
第五节  修改Web部署描述文件
正如2.6.1所指出的那样,要保证Portlet能够在Liferay Portal成功部署,必须对web.xml进行必要的修改,添加Portlet监听器、Servlet映射、Portlet标签库。在先前web.xml的<display>节点下增加如下内容:
<listener>
<listener-class>com.liferay.portal.servlet.PortletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>HelloWorldPortlet</servlet-name>
<servlet-class>com.liferay.portal.servlet.PortletServlet</servlet-class>
<init-param>
<param-name>Portlet-class</param-name>
<param-value>com.educhina.portal.HelloWorldPortlet</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldPortlet</servlet-name>
<url-pattern>/HelloWorldPortlet/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HelloJSPPortlet</servlet-name>
<servlet-class>com.liferay.portal.servlet.PortletServlet</servlet-class>
<init-param>
<param-name>Portlet-class</param-name>
<param-value>com.educhina.portal.HelloJSPPortlet</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloJSPPortlet</servlet-name>
<url-pattern>/HelloJSPPortlet/*</url-pattern>
</servlet-mapping>
<taglib>
<taglib-uri>http://java./Portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/liferay-Portlet.tld</taglib-location>
</taglib>
其中,<listener>节点是增加一个监听器,以便Liferay Portal监听所有针对Portlet的操作。<servlet>以及<servlet-mapping>是将上述两个Portlet类加入Servlet容器中。Portlet类实质上也是Servlet。<tablib>是将Liferay Portal标签库加入列表中,以便JSP调用。
 
第六节  创建Liferay Portal部署描述文件
修改完web.xml之后,还要创建2.6所说的三个Portlet部署描述文件:portlet.xml、liferay-portlet.xml、liferay-display.xml。
①、portlet.xml
portlet.xml定义Portlet的初始化信息。这里,我们在portlet.xml中增加两个Portlet节点,分别代表HelloWorldPortlet和HelloJSPPortlet。其中,HelloWorldPortlet支持PringWriter输出,HelloJSPPortlet支持JSP输出;两者都支持浏览和编辑两种模式。HelloJSPPortlet需要定义两个init参数,告诉系统JSP文件的位置。
<portlet>
<portlet-name>HelloWorldPortlet</portlet-name>
<display-name>HelloWorldPortlet</display-name>
<portlet-class>com.educhina.portal.HelloWorldPortlet</portlet-class>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<supports>
<mime-type>text/html</mime-type>
<Portlet-mode>edit</Portlet-mode>
</supports>
<portlet-info>
<title>HelloWorldPortlet</title>
<short-title>HelloWorldPortlet</short-title>
<keywords>HelloWorldPortlet</keywords>
</portlet-info>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
<portlet>
<portlet-name>HelloJSPPortlet</portlet-name>
<display-name>HelloJSPPortlet</display-name>
<portlet-class>com。Educhina.portal.HelloJSPPortlet</portlet-class>
<init-param>
<name>view-jsp</name>
<value>/view。jsp</value>
</init-param>
<init-param>
<name>edit-jsp</name>
<value>/edit。jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<supports>
<mime-type>text/html</mime-type>
<Portlet-mode>edit</Portlet-mode>
</supports>
<portlet-info>
<title>HelloJSPPortlet</title>
<short-title>HelloJSPPortlet</short-title>
<keywords>HelloJSPPortlet</keywords>
</portlet-info>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
②、liferay-Portlet.xml
Liferay-Portlet.xml主要定义Portlet的模板、实例总数、是否允许重复定义等。同样的,我们增加了两个<Portlet>节点,代表HelloWorldPortlet和HelloJSPPortlet。
<?xml version="1。0"?>
<!DOCTYPE liferay-Portlet-app PUBLIC "-//Liferay//DTD Portlet Application 3。5。0//EN" "http://www。liferay。com/dtd/liferay-Portlet-app_3_5_0。dtd">
<liferay-portlet-app>
<portlet>
<Portlet-name>HelloWorldPortlet</Portlet-name>
<struts-path>HelloWorldPortlet</struts-path>
<use-default-template>true</use-default-template>
<instanceable>true</instanceable>
</portlet>
<portlet>
<Portlet-name>HelloJSPPortlet</Portlet-name>
<struts-path>HelloJSPPortlet</struts-path>
<use-default-template>true</use-default-template>
<instanceable>true</instanceable>
</portlet>
<role-mapper>
<role-name>administrator</role-name>
<role-link>Administrator</role-link>
</role-mapper>
<role-mapper>
<role-name>guest</role-name>
<role-link>Guest</role-link>
</role-mapper>
<role-mapper>
<role-name>power-user</role-name>
<role-link>Power User</role-link>
</role-mapper>
<role-mapper>
<role-name>user</role-name>
<role-link>User</role-link>
</role-mapper>
</liferay-portlet-app>
③、liferay-display.xml
liferay-display.xml定义Portlet所属类别。Liferay Portal默认定义了一个category.test类别,这里,我们将HelloWorldPortlet和HelloJSPPortlet归属到category.test。
<?xml version="1。0"?>
<!DOCTYPE display PUBLIC "-//Liferay//DTD Display 3。5。0//EN" "http://www。liferay。com/dtd/liferay-display_3_5_0。dtd">
<display>
<category name="category。test">
<Portlet id="HelloWorldPortlet" />
<Portlet id="HelloJSPPortlet" />
</category>
</display>
至此,一个简单的Portlet就开发完成了。接下来,我们把它部署到Liferay Portal上。
第三部分 Liferay Portal部署
本部分主要内容
Portlet部署  ANT  管理Portlet
第四章 部署自己的Portlet
Liferay Portal跟Tomcat5.0集成在一起,从本质上讲,liferay-portal-pro-3.6.0-tomcat.zip是一个Tomcat压缩包,只是其中将liferay作为默认应用,并将跟Portlet有关的操作都交给liferay应用处理而已。因此,Liferay Portal支持所有针对Tomcat5.0的部署方式,包括:手动部署、Ant部署,并且支持热部署。
第一节  手动部署
手动部署可以采用拷贝文件夹、war部署、编写部署文件三种方式:
①、拷贝文件夹:与单纯的Tomcat一样,我们可以将{APP_HOME}/webapp目录拷贝到{PORTAL_HOME}/webapps/下,该webapp目录名为TestPortal。启动Liferay Portal(双击{PORTAL_HOME}/bin/startup。bat)即可。
②、war部署:或者将{APP_HOME}/webapp打包成TestPortal.war,拷贝war到{PORTAL_HOME}/webapps/下,启动Liferay Portal,让Tomcat自动解压。在命令行模式下切换到{APP_HOME}/webapp目录,执行 jar cvf TestPortal.war * 。
③、编写部署文件:
{PORTAL_HOME}/conf/Catalina/localhost目录下,创建TestPortal.xml文件,内容如下:
<Context path="/TestPortal" docBase="D:/TestPortal/webapp" debug="0" reloadable="true" crossContext="true">
</Context>
部署成功后,登录Liferay Portal,可以在桌面底部的下拉列表中看到HelloWorldPortlet和HelloJSPPortlet两个Portlet。将它们添加到桌面中。
第二节  Ant自动部署
确保之前已经安装Apache Ant,并正确添加ANT_HOME到系统环境变量。
①、拷贝之前打包的TestPortlet.war到{APP_HOME}/deploy目录;
②、从http://prdownloads。sourceforge。net/lportal/Portlet-deployer-3。6。0。xml 下载Portlet-deployer-3.6.0.xml 到{APP_HOME}/deploy,改名为build。xml以便Ant自动加载;
③、确保JDK1.4.2和Ant 1.6安装成功,并配置到系统环境变量;
④、确保Tomcat或者其他服务器已经正确安装,或者Liferay Portal正常安装。
编辑build.xml,使其只想你的应用服务器或者Servlet容器。比如,如果你安装JBoss+Jetty到/opt/liferay目录,那么编辑build.xml,确保只有JBoss+Jetty部分没有被注释,修改app.server属性为/opt/liferay。
Build.xml默认是开启JBoss+Jetty部分,本文采用的是Tomcat集成包,所以将JBoss+Jetty部分注释掉,开始Tomcat部分。修改app.server.dir属性,指向{PORTAL_HOME}。如下图:
⑤、命令行切换到到{APP_HOME}/deploy目录,执行 ant deploy ,系统会自动将TestPortal。war解压,必要时修改web.xml、portlet.xml等部署文件,将解压后的TestPortal文件夹拷贝到{PORTAL_HOME}/webapps目录下。
启动Liferay Portal之前,建议先确认修改后的web.xml、portlet.xml等部署文件是否正确。
第三节  加入Liferay Portal自有列表
之前我们提到过,Liferay Portal集成了78个默认的Portlet应用。这些应用都通过{PORTAL_HOME}/liferay/WEB-INF/目录下的portlet.xml、liferay-portlet.xml、liferay-display。xml描述。我们只要更改这些描述文件,就可以将我们自己的应用加入到Liferay Portal的Portlet列表中了,效果跟手动部署和Ant自动部署一样。
①、拷贝{APP_HOME}/webapp目录的内容到{PORTAL_HOME}/liferay/html/Portlet目录下,更改文件夹名称为TestPortal。
②、将TestPortal/WEB-INF/classes文件夹剪切到{PORTAL_HOME}/liferay/WEB-INF目录下。
③、将TestPortal/WEB-INF/web。xml中<servlet>、<servlet-mapping>的内容合并到{PORTAL_HOME}/liferay/WEB-INF/web.xml中。删除TestPortal/WEB-INF/web.xml。
④、将TestPortal/WEB-INF/Portlet.xml中关于HelloWorldPortlet和HelloJSPPortlet的<portlet>的内容合并到{PORTAL_HOME}/liferay/WEB-INF/portlet.xml中。删除TestPortal/WEB-INF/ portlet.xml。
⑤、将TestPortal/WEB-INF/liferay-portlet.xml中关于HelloWorldPortlet和HelloJSPPortlet的<portlet>的内容合并到{PORTAL_HOME}/liferay/WEB-INF/liferay-portlet.xml中。删除TestPortal/WEB-INF/liferay-portlet.xml。
⑥、将TestPortal/WEB-INF/liferay-display.xml中关于HelloWorldPortlet和HelloJSPPortlet的<portlet>的内容合并到{PORTAL_HOME}/liferay/WEB-INF/liferay- display.xml中。删除TestPortal/WEB-INF/ liferay- display.xml。
这个方法比较复杂,而且不容易扩展和调试,通常不建议采用。
第四节  普通Java Web应用转化为Portlet应用
随着开发的深入,我们希望能够将原来的Java Web应用迁移到Liferay Portal,构建真正的企业门户。Liferay Portal灵活的二次开发机制,允许用户将各种各样的内容集成到Portal平台上来,消除信息孤岛。将一个Java Web应用转化为Portlet应用的步骤如下:
①、撰写扩展自GenericPortlet的Portlet和JSP页面。这个Portlet可以使用PrintWriter输出或者调用JSP页面输出方式。通常,如果Java Web应用是采用MVC三层模式,那么只需要更改View层就可以了。
②、修改web.xml,增加2。6。1所述的Portlet监听器和Portlet标签库,增加针对上步骤所写的servlet和servlet映射。
<servlet>
<servlet-name>yourPortlet</servlet-name>
<servlet-class>com.liferay.portal.servlet.PortletServlet</servlet-class>
<init-param>
<param-name>Portlet-class</param-name>
<param-value>full.name.of.yourPortlet</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>yourPortlet</servlet-name>
<url-pattern>/yourPortlet/*</url-pattern>
</servlet-mapping>
③、创建portlet.xml,增加相应的Portlet定义信息,规范参考2.6.2。
④、创建liferay-portlet.xml,增加相应的Portlet定义信息,规范参考2.6.3。
⑤、创建liferay-display.xml,增加相应的Portlet类别定义信息,规范参考2.6.4。
⑥、拷贝portlet.jar和liferay-Portlet.tld到当前应用。其中,portlet.jar是Portlet API包,作用类似servlet-api.jar,位于{PORTAL_HOME}/common/lib/ext/liferay-portlet.tld是Liferay Portal提供的Portlet标签库。
⑦、选择适当的部署方式,将修改后的Java Web应用部署到Portlet平台上。
第四部分 附录
本部分主要内容
资源网站 Portlet范例 参考资料 后序
第五章 相关资源
作为一个开源的门户产品,Liferay Portal已经比较成熟,有比较齐全的文档。随着应用的深入,开源免费的中文化文档也在陆续出现。
第一节 资源网站
Liferay Portal 官方网站:http://www. 
Liferay Portal 中文网站:http://www. 
Liferay Portal 论坛:http://forums. 
Tracker : http://support. 
邮件列表:http:///mailarchive/forum.php?forum=lportal-development 
JavaLobby专题:http://www./articles/liferay/
OSQS专题:http://cstsolaris.cst.nait./ist410/gerry/liferay/index.jsp 
Leonardsoko1专题:http://www./liferay/
Developer专题:http://www./java/web/article.php/10935_3372881_1
第二节  示例
Liferay Portal随程序包提供了丰富的documentation,其中的Portlet Examples对Portal内置的Hello World、IFrame、Calendar、Message Boards、Mail五个Portlet进行了比较详细的解说。启动Liferay Portal后,浏览这里:
http://localhost/web/guest/documentation/development/Portlet
另外,Liferay Portal还在官方网站上提供了Sample Layout Template、Sample Portlet、Sample Themes供下载。其中,Sample Portlet包括Sample JSP Portlet、Sample Struts Portlet、Sample JSF SUN Portlet、Sample JSF MyFaces Portlet。浏览这里:
http://localhost/web/guest/downloads/sample_Portlet

第六章 参考资料
①、文档
《JSR168 PORLET标准手册汉化整理》 作者:Jini等
《Portlet应用开发(JSR168)》 作者:Terry Lee
《(原创翻译)Liferay-Portal架构》                   作者:eamoi
②、网站
http://www.
http://www.
后序
研究Liferay Portal属于半路出家。从开始到本文完成,俩月有余。作为一个开源的Portal产品,Liferay的确值得称许,虽然还有不少bug。在本文截稿的时候,Liferay Portal V3.6.1已经发版,新版本在拖拉Portlet、Spring远程传输和布局热部署方面有比较大的提升。本文不会就此终结,暂称V1.0,作为前段工作的总结。本文的用户策略部分参考了同事Kevin的文档,特此感谢。
PS:写文章真的很费脑筋。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多