`

5.Liferay Portal的部署描述文件

阅读更多

第六节 Liferay Portal的部署描述文件

跟所有的Web应用一样,Liferay Portal采用多个XML部署描述文件,来初始化部署信息,规范操作模式,比如Portlet的初始化信息、可用的Portlet列表、Portlet所属角色和用户组等等。通过这些部署描述文件,Liferay Portal可以在启动的时候自动加载Portlet,根据需要生成所需的Portlet页面。普通的Web应用,也可以很方便的转换成可部署的Portlet。这种实现也是JSR168所规定的。

2.6.1 web.xml

http://java.sun.com/dtd/web-app_2_3.dtd 定义。

       与其他普通Web应用相比,Liferay Portal的Portlet 应用还需要在web.xml中增加如下内容:

a、监听器:

       <listener>

       <listener-class>com.Liferay.portal.servlet.PortletContextListener</listener-class>

       </listener>

这个要求web 服务器监听所有跟Portlet有关的请求信息,并将监听到的内容交给Liferay Portal的Portlet容器处理。

b、Portlet 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>

其中,servlet-name为部署的servlet名称;init-param中定义自己的Portlet类,这个param-name要跟portlet.xml、liferay-portlet.xml、liferay-display.xml中的portlet-name节点值一致。

c、标签库映射:

       <taglib>

              <taglib-uri>http://java.sun.com/Portlet</taglib-uri>

              <taglib-location>/WEB-INF/tld/liferay-Portlet.tld</taglib-location>

       </taglib>

定义了这个标签库映射,在JSP文件中才可以使用诸如<portlet:defineObjects />在内的一些特定的Portlet标签。

如果在应用中有用到其他的元素,可以按照web.xml规范加入到相应的位置当中。

Liferay Portal默认的liferay应用,由于使用了Struts、Hibernate、Spring在内的多个开源框架,所以{PORTAL_HOME}/liferay/WEB-INF/web.xml文件会相对复杂些。

在自定义的Portlet,可以使用getPortletConfig().getInitParameter(“ ”)和getPortletConfig().getParameterNames(“”)两个方法来取得在web.xml中定义的参数。

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.sun.com/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.sun.com/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.liferay.com/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.liferay.com/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.liferay.com/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-feel。xml

定义Portal可用品质的模板、图片、样式表等等,定义完毕后,Portal可以通过“布局与品质”管理工具来进行品质的切换。Liferay-look-and-feel.xml规范由http://www.liferay.com/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.sun.com/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.sun.com/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.sun.com/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.com 

Liferay Portal 中文网站:http://www.liferay.cn 

Liferay Portal 论坛:http://forums.liferay.com 

Tracker : http://support.liferay.com 

邮件列表:http://sourceforge.net/mailarchive/forum.php?forum=lportal-development 

JavaLobby专题:http://www.javalobby.org/articles/liferay/

OSQS专题:http://cstsolaris.cst.nait.ab.ca/ist410/gerry/liferay/index.jsp 

Leonardsoko1专题:http://www.leonardsokol.com/liferay/

Developer专题:http://www.developer.com/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 La

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics