`
cloudtech
  • 浏览: 4605825 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

Portlet 开发指南

 
阅读更多

Portlet 开发指南

 目录

Portlet 开发指南...............................................................................................................................1
第一章节入门介绍.........................................................................................................................7
一、 Portlet 简介...............................................................................................................8
什么是Portal ....................................................................................................................9
什么是Portlet...................................................................................................................9
什么是Portlet 容器..........................................................................................................9
三者关系.........................................................................................................................10
版本兼容性.....................................................................................................................10
JSR286 的主要新特性....................................................................................................10
与J2EE 的版本对应.......................................................................................................10
二、 Portlet 与servlet 的关系........................................................................................11
Portlet 与servlet/jsp 中的桥梁......................................................................................12
用servlet 生命周期事件................................................................................................12
Servlet 容器与Portlet 容器之间的关系........................................................................12
三、 开发环境搭建.........................................................................................................13
IBM WebSphere Portal 环境搭建...................................................................................13
Apache Pluto Portal 环境搭建........................................................................................24
快速入门.........................................................................................................................29
第二章节独有概念.......................................................................................................................36
四、 Portlet 概念.............................................................................................................37
Portlet 定义.....................................................................................................................37
Portlet 是Portal 页面中的一个区域.............................................................................37
Portlet 和Web 框架.......................................................................................................38
五、 Portlet URLs.............................................................................................................39
BaseURL 接口.................................................................................................................39
包含Portlet Mode 和Window State 信息...................................................................40
Portlet URL 安全性.........................................................................................................40
总结.................................................................................................................................40
六、 Portlet Modes..........................................................................................................42
查看 Portlet Mode.........................................................................................................42
编辑 Portlet Mode.........................................................................................................42
帮助 Portlet Mode.........................................................................................................42
自定义Portlet Modes ...................................................................................................42
受支持的 Portlet Modes................................................................................................43
七、 Window States ........................................................................................................44
正常Window State ........................................................................................................44
最大化Window State ....................................................................................................44
最小化Window State ....................................................................................................44

2

----------------------- Page 3-----------------------

Portlet 开发指南

自定义Window States ..................................................................................................44
支持的Window State ....................................................................................................44
八、 Portlet Preferences..................................................................................................45
PortletPreferences 接口................................................................................................45
Preference Attributes 范围............................................................................................45
Preference Attributes 定义............................................................................................46
第三章节基础概念.......................................................................................................................47
九、 Portlet 生命周期接口.............................................................................................48
Portlet 实例的数量........................................................................................................48
Portlet 生命周期.............................................................................................................48
Portlet 的个性化............................................................................................................49
Request 请求处理...........................................................................................................50
总结.................................................................................................................................54
十、 Portlet Config ..........................................................................................................55
初始化参数.....................................................................................................................55
Portlet Resource Bundle..................................................................................................55
默认事件命名空间.........................................................................................................56
公告展现参数.................................................................................................................56
发布事件.........................................................................................................................56
处理事件.........................................................................................................................56
支持的国际化.................................................................................................................56
支持的运行时选项.........................................................................................................56
总结.................................................................................................................................57
十一、 Portlet Context ................................................................................................58
Portlet Context 范围.......................................................................................................58
Portlet Context 功能......................................................................................................58
与Servlet Context 关系.................................................................................................58
总结.................................................................................................................................59
十二、 Portlet Requests ..............................................................................................60
PortletRequest 接口......................................................................................................60
ClientDataRequest 接口.................................................................................................64
ActionRequest 接口.......................................................................................................64
ResourceRequest 接口..................................................................................................64
EventRequest 接口........................................................................................................65
RenderRequest 接口......................................................................................................65
Request 对象的时间范围..............................................................................................65
总结.................................................................................................................................65
十三、 Portlet Response .............................................................................................66
PortletResponse 接口....................................................................................................66
StateAwareResponse 接口............................................................................................68
ActionResponse 接口.....................................................................................................68
EventResponse 接口......................................................................................................68
MimeResponse 接口......................................................................................................69
RenderResponse 接口...................................................................................................69

3

----------------------- Page 4-----------------------

Portlet 开发指南

ResourceResponse 接口................................................................................................70
Response 对象的时间范围...........................................................................................70
十四、 Sessions ...........................................................................................................71
创建Session....................................................................................................................71
Session 范围...................................................................................................................71
Session 中设置属性........................................................................................................71
与Web Application HttpSession 关系............................................................................71
写入Portlet Session........................................................................................................72
Session Timeouts.............................................................................................................73

最后访问时间.................................................................................................................73
重要的Session 语义.....................................................................................................73
总结.................................................................................................................................73
十五、 请求分发给Servlets 和JSPs .......................................................................74
获取 PortletRequestDispatcher.....................................................................................74
使用Dispatcher ..............................................................................................................74
Include 方法...................................................................................................................74
forward 方法..................................................................................................................75
Servlet filters ...................................................................................................................76
改变默认的Included Forwarded Session 范围............................................................76
总结.................................................................................................................................76
十六、 Portlet 标签库................................................................................................77
defineObjects 标签........................................................................................................77
actionURL 标签..............................................................................................................79
renderURL 标签.............................................................................................................79
resourceURL 标签...........................................................................................................80
namespace 标签.............................................................................................................81
param 标签.....................................................................................................................81
总结.................................................................................................................................81
十七、 Portlet 应用....................................................................................................82
与Web Applications 的关系..........................................................................................82
与PortletContext 的关系...............................................................................................82
Portlet Application 中的元素.........................................................................................82
目录结构.........................................................................................................................82
Portlet Application Classloader.......................................................................................82
Portlet Application 存档文件........................................................................................82
Portlet application 部署描述符.....................................................................................83
更新Portlet Application .................................................................................................83
十八、 打包和部署描述符.........................................................................................84
Portlet 和部署描述符.....................................................................................................84
打包.................................................................................................................................84
Portlet 部署描述符元素.................................................................................................84
处理Portlet 部署描述符规则.......................................................................................85
Portlet.xml 中唯一的值..................................................................................................85
第四章节 高级特性.......................................................................................................................86

4

----------------------- Page 5-----------------------

Portlet 开发指南

十九、 资源服务.........................................................................................................87
ResourceServingPortlet 接口.........................................................................................87
访问 Render 参数、 Portlet Mode、Window State.................................................88
访问Request 和 Response Headers.............................................................................88
获取 HTTP 方法............................................................................................................89
访问Resource ID ............................................................................................................89
Resource URLs.................................................................................................................89

Generic Portlet 支持......................................................................................................89
Ajax 请求.........................................................................................................................89
二十、 Portlet 协作.....................................................................................................91
Public Render Parameters...............................................................................................91
Portlet Events..................................................................................................................92

Events 传送复杂对象.....................................................................................................96
总结.................................................................................................................................96
二十一、 Portlet Filter ....................................................................................................98
什么是 Portlet filter.......................................................................................................98
主要概念.........................................................................................................................99
总结...............................................................................................................................101
第五章节可选概念.....................................................................................................................102
二十二、 缓存...............................................................................................................103
缓存过期.......................................................................................................................103
验证缓存.......................................................................................................................103
总结...............................................................................................................................104
二十三、 用户信息.......................................................................................................105
定义用户属性...............................................................................................................105
访问用户属性...............................................................................................................105
重要注意事项...............................................................................................................106
总结...............................................................................................................................106
二十四、 安全性...........................................................................................................107
介绍...............................................................................................................................107
角色...............................................................................................................................107
安全性代码开发...........................................................................................................107
总结...............................................................................................................................107
二十五、 Portal Context................................................................................................108
二十六、 Portlet 容器运行时......................................................................................109
动态修改Portlet 标题..................................................................................................109
二十七、 使用注释的方法...........................................................................................111
GenericPortlet Render Handling ...................................................................................111
二十八、 Setting next possible Portlet Modes .............................................................112
二十九、 Struts2 开发Portlet 实例.............................................................................113
三十、 Spring mvc 开发Portlet 实例.......................................................................114
三十一、 附录...............................................................................................................115
修改记录.......................................................................................................................115
名词解释.......................................................................................................................115

5

----------------------- Page 6-----------------------

Portlet 开发指南

疑问...............................................................................................................................116

6

----------------------- Page 7-----------------------

Portlet 开发指南

第一章节 入门介绍

入门介绍主要包括Portlet 开发中三个基本概念(Portlet、Portlet 容器、Portal)的介绍,
Portlet 与servlet 的关系,以及搭建开发环境,并进行部署。

7

----------------------- Page 8-----------------------

Portlet 开发指南

一、 Portlet 简介

Portlet 与servlet 一样,都是JSR 的规范api 定义,不同的Portlet 还比较“年轻”,目前
版本还只到2.0,而servlet 规范已经相当成熟,发布了多个版本。如果不是十分准确的说,
Portlet 只是另一种开发web 程序的api,从这个方面说,开发Portlet 并没有什么神秘的地方,
但是之所以有Portlet 这个规范,Portlet 适用的场景肯定与servlet 是不同的,比如开发Portlet
不但要与Portlet 容器打交道,还要与Portal 打交道。读者在学习Portlet 开发的过程中,可
以不时的用servlet 的概念与Portlet 相比较,比较两者的异同,可以达到事半功倍的效果。
刚才说到Portlet 规范已经出到2.0,分别是JSR168,JSR286。JSR 168 目前在业界受到广
泛支持,目前我们开发的大部分代码都是基于JSR168 的,JSR168 规范支持基本的开发方式,
虽然提供的功能比较少,但是已经基本可以满足日常需要。JSR168 发布三年之后,大多数
支持Java Portlet Specification V1。0 的门户产品都提供一些附加扩展,以支持更高级的用例,
这些附加的扩展造成了各个门户产品的标准不统一,彼此间的交互协作成了不可避免的问题。
为了更好地规范Portlet 开发,以适应业界发展,并提供适应于最高级别用例的标准解决方
案,从而为这些高级功能提供互操作性,在2005 年 11 月开始了Java Portlet Specification
V2.0 (称为JSR 286)的开发,在2008 年1 月Java Portlet Specification V2.0 目前已经正式发
布。JSR 286 规范兼容了JSR 168,并完善了JSR 168 的部分功能,并提供了诸多JSR 168 所
没有的新特性,例如资源服务、事件、Portlet 过滤器、共享呈现参数及 Portlet 窗口等。与
V1 。0 类似,V2.0 也将基于J2EE 1.4,因此可让Portlet 使用J2EE 1.4 增强(如JSP 2.0)。
下面是该新规范的一些主要功能及特性:
1. 资源服务:一种新的通过Portlet 呈现资源的方式。
2. 事件:通过发送事件和接收事件来实现 Portlet 之间的通信。
3. Portlet 过滤器:与 servlet 过滤器类似,根据 Portlet 请求和响应动态的呈现内容
的变换。存在以下四种类型的Portlet 过滤器:
o Action 过滤器
o Render 过滤器
o Resource 过滤器
o Event 过滤器
4. 共享呈现参数:除了 Portlet 私有的呈现参数之外,新增了可以在 Portlet 之间共享
的呈现参数。
5. Portlet 窗口:提供 Portlet 窗口 ID 供 Portlet 使用
要讲解Portlet,首先要明确三个概念:Portal、Portlet、Portlet 容器。Portlet 与Portlet
容器的关系可以比较servlet 与servlet 容器的关系,两者是完全一致的,开发者按照Portlet
规范开发Portlet,部署在中间件提供商(ibm、oracle、apache)提供的Portlet 容器中运行,
比较难理解的是Portal,首先Portal 是一个JEE 的application,Portal 负责提供页面给客户,
其次Portal 里面的内容是Portlet 生成出来的。一般的过程是,用户通过web 客户端向Portal
发起http 请求,Portal 解析这些请求,把请求“下发”给Portlet 容器,Portlet 容器来调用
Portlet,由Portlet 产生输出返回给Portlet 容器,Portlet 容器再把输出返回给Portal,Portal
负责把这些Portlet 的输出聚集起来,把内容返回给web 客户端。下面来具体描述一下Portal、
Portlet、Portlet 容器三个概念。

8

----------------------- Page 9-----------------------

Portlet 开发指南

什么是Portal

Portlet 规范中是这样定义Portal 的:

A Portal is a web based application that –commonly- provides personalization 、
authentication、content aggregation from different sources and hosts the presentation layer of
Information Systems。

Portal 是一个基于web 的提供个性化、登录授权、从不同的数据源聚集内容基于展现层
的信息系统。具体到J2EE 领域,Portal 大多数情况是一个符合J2EE 标准的ear 包工程。

什么是Portlet

规范中式这样定义Portlet 的:

A Portlet is an application that provides a specific piece of content (information or service) to
be included as part of a Portal page。It is managed by a Portlet container、that processes
requests and generates dynamic content

一个Portlet是一个基于java 技术的被Portlet容器管理的web 组建,它可以处理requests、
生成动态的内容输出,一个Portlet 负责提供Portal 页面中的某个特定部位的展现内容。
与servlet 同样,Portlet 的生命周期是被Portlet 容器来管理的。Portlet 生成的内容也可
以称作fragment,这些多个Portlet 生成的多个fragment 会被Portal 聚集(aggregate)在一
起展现。不同用户看到的Portlet 可能不同,这依赖于不同用户对使用Portlet 的配置。

什么是Portlet 容器

规范中式这样定义Portlet 容器的:

A Portlet container runs Portlets and provides them with the required runtime environment。
A Portlet container contains Portlets and manages their lifecycle。It also provides persistent
storage for Portlet preferences。A Portlet container receives requests from the Portal to
execute requests on the Portlets hosted by it。

Portlet 容器提供 Portlet 生命周期环境,管理 Portlet 的生命周期,还提供 Portlet
preferences 的持久化支持,Portlet 从Portal 接受请求,然后分发给运行其上的Portlet。
Portlet 不负责聚集Portlet 生成的内容,这是Portal 责任。根据中间件厂商的实现方式
Portlet 容器与Portal 可以放在一个application 中实现,也可以放在两个不同的application 中
实现。

9

----------------------- Page 10-----------------------

Portlet 开发指南

三者关系

下面是以一个用户使用web 客户端来与Portal 交互的用力,描述Portlet、Portlet 容器、
Portal 三者关系、责任:
1. web 客户端通过http 来对Portal 发起request 请求
2. request 请求被Portal 就收到
3. Portal 分析这个请求是否需要与Portlet 进行交互
4. 如果需要,则Portal 通知Portlet 容器调用Portlet 处理交互
5. Portal 通过Portlet 容器得到Portlet 返回的fragments
6. Portal 聚集Portlet 产生的fragments,生成最终的页面,返回给web 客户端

版本兼容性

JSR286 规范是向后兼容的,所以所有基于JSR168 写的代码生成的war 都可以在JSR286
容器里面运行。不过下面罗列出一些特例,这些特例会在具体章节说明。
1. RenderResponse。setContentType 已经不再需要在getWriter 或者getOutputstream
之前调用了,已经不会产生IllegalStateException
2. 对于在Portlet 工程中嵌入servlet、jsp 调用getProtocol,JSR168 中返回时null,JSR286
中返回时HTTP/1.1

JSR286 的主要新特性

JSR286 对JSR168 是向后兼容的,JSR286 主要增加了如下新特性:
 事件Events,可以是Portlet 可以接受、发送事件
 公共展现参数public render parameters,容许Portlet 之间共享参数
 资源服务resource serving ,提供Portlet 服务资源的能力
 Portlet 拦截器 Portlet filter,容许在Portlet 的request、response 之间建立拦
截器

与J2EE 的版本对应

J2EE servlet jsp

JSR168 1.3 2.3 1.2
JSR286 1.4 2.4 2.0

10

----------------------- Page 11-----------------------

Portlet 开发指南

二、 Portlet 与servlet 的关系

Servlet 规范中是这样定义的:

A servlet is a Java technology based web component、managed by a container、that
generates dynamic content 。 Like other Java-based components、 servlets are platform
independent Java classes that are compiled to platform neutral bytecode that can be loaded
dynamically into and run by a Java enabled web server。Containers、sometimes called servlet
engines、are web server extensions that provide servlet functionality。Servlets interact with
web clients via a request/response paradigm implemented by the servlet container。

中文翻译是:servlet 是基于java 技术的web 组件,被servlet 容器管理,生成动态内容。
Servlet 通过servlet 容器与web 客户端展开request、response 交互。
其实很难说出Portlet 与servelt 之间的关系,从某个层面说Portlet 与servlet 之间没有任
何关系,但是从另一个层面来说又有个千丝万缕的关系,所以这里只是做一些技术上的比较。
Portlets 与servlets 的相同点:
 都是基于java 技术的web 组件
 都被专门的容器管理
 都生成动态内容
 生命周期都被容器管理
 都是与web 客户端通过request/response 的方式交互
Portlets 与servlets 的不同点:
 Portlet 只生成内容片断,Portal 来负责把这些片断聚集在一个页面中。
 Portlet 不能直接映射成一个URL
 Web 客户端同Portlet 交互需要通过Portal application
 Portlets 有多种request,比如: action request、render request、event request、
resource rquest
 Portlets 定义了 Portlet modes 和window states
 同一个Portlets 可以存在多次在同一个Portal 页面
Portlet 提供的附加功能但是servlet 没有提供
 Portlets 可以持久化存储和访问数据
 Portlets 可以访问用户的信息
 Portlets 具有生成URL 功能,可以让Portal 来生成访问Portlet 的链接和请求
 Portlets 可以在session 的两个范围中存储数据,application-wide scope 和the
Portlet private scope

 Portlet 之间可以互相接受、发送事件
Portlets 不具备的servlet 提供的功能
 在render response 中设置字符编码
 直接通过URL 访问
虽然render 不能设置字符编码,但是JSR286 中新提供的serveResource 方法具有完全的
response 控制功能。
就是由于上述的不同,才定义了这个新的web 组件规范。Portlet 重用了很多servlet 中
基础的、重要的概念,比如部署方式、类加载、生命周期管理、session 管理、request 分发。

11

----------------------- Page 12-----------------------

Portlet 开发指南

Portlet application 包括servlet、jsp 、Portlet、静态文件、图片等内容,在同一个Portlet
应用中的Portlet、servlet、jsp 共享类加载、应用上下文、session。

Portlet 与servlet/jsp 中的桥梁

Portlet 可以利用servlet、jsp 生成内容,一个Portlet 可以使用request 分发调用servlet、
jsp ,就像一个servlet 可以调用servlet、jsp 。当一个servlet 被Portlet 调用,servlet 的request
基于Portlet 的request,servlet 的response 基于Portlet 的response。比如:
 在Portlet 中request 设置的属性,Portlet include 调用的servlet 可以获得。
 Portlet 和此Portlet include 的servlet、jsp 共享一个输出流。
 使在Portlet 中session 设置的属性,servlet 可以获得。

用servlet 生命周期事件

Portlet 中的PortletContext 、PortletSession 与servlet 中的SevletContext、HttpSession 是
有关联关系的,所有这对servlet 生命周期的listener 同样对Portlet 有效。下面的servlet 中
的listener 对Portlet 同样有效:
 javax.servlet.ServletContextListener
 javax.servlet.ServletContextAttributeListener
 javax.servlet.http.HttpSessionActivationListener
 javax.servlet.http.HttpSessionAttributeListener
 javax.servlet.http.HttpSessionBindingListener
 javax.servlet.ServletRequestListener

Servlet 容器与Portlet 容器之间的关系

Portlet 的容器是servlet 容器的扩展,根据中间件厂商的实现方式Portlet 容器可以单独
实现也可以基于servlet 扩展。

12

----------------------- Page 13-----------------------

Portlet 开发指南

三、 开发环境搭建

本文涉及两套开发环境,一个是商业上最成功的IBM Portal 的开发环境,一个是开源界
Apache 旗下的Pluto。开发环境有分为开发工具(IDE)、Portal server 的搭建。

IBM WebSphere Portal 环境搭建

本文使用的是WebSphere Portal 版本是6.1.5,开发工具是RAD 7.5

安装Portal Server

请参考Portal 安装手册,待补充。

安装开发工具RAD

请参考RAD 安装手册,待补充。

配置RAD

RAD 是一个Eclipse 的插件扩展,开发习惯和Eclipse 非常像。需要配置的地方也是普通
使用eclipse 开发需要配置的地方。

配置Portal Server

1. 新建服务器
首先需要配置一个server,这块与配置tomcat 基本上没啥区别。

13

----------------------- Page 14-----------------------

Portlet 开发指南

14

----------------------- Page 15-----------------------

Portlet 开发指南

15

----------------------- Page 16-----------------------

Portlet 开发指南

配置首选项

1. 去掉验证

16

----------------------- Page 17-----------------------

Portlet 开发指南

2. 文本文件编码
文本文件编码一律统一使用UTF-8 格式
CSS、HTML、JSP 也使用UTF-8 格式

17

----------------------- Page 18-----------------------

Portlet 开发指南

18

----------------------- Page 19-----------------------

Portlet 开发指南

19

----------------------- Page 20-----------------------

Portlet 开发指南

20

----------------------- Page 21-----------------------

Portlet 开发指南

21

----------------------- Page 22-----------------------

Portlet 开发指南

3. 缺省包
缺省包使用 :com。Portalguide

22

----------------------- Page 23-----------------------

Portlet 开发指南

4. 添加用户库
如果开发Portlet 需要设置用户库,可以添加

23

----------------------- Page 24-----------------------

Portlet 开发指南

Apache Pluto Portal 环境搭建

Apache Pluto Portal 支持JSR286,定位是简单容器实现,并不适合在生产环境下使用。
目前Pluto 的版本是2.0。2,开发环境可以使用eclipse 比如eclipse-jee-helios-SR1-win32 版
本,也可以是RAD,本文使用了RAD,因为这样同事开发IBM、Apache Portal 的时候比较方
便。

安装Portal Server

1. 下载Pluto 2.0 binary distribution
2. 解压缩zip 文件
3. 设置CATALINA_HOME 环境变量
4. 通过startup。bat 启动Apache Pluto 门户
5. 通过http://192。168。0。198:8080/pluto/Portal 访问门户

6. 修改pluto-2.0。2\webapps\pluto\WEB-INF\themes\pluto-default-theme。jsp、添加

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

解决中文乱码问题
7. 通过tomcat/tomcat 登陆

24

----------------------- Page 25-----------------------

Portlet 开发指南

配置RAD

配置首选项的设置于IBM WebSphere Portal 环境是一样的,主要区别是新建server,Pluto 使
用的server 就是Apache Tomcat Version 6 。0。26,所以这里我新建的server 使用tomcat6

25

----------------------- Page 26-----------------------

Portlet 开发指南

26

----------------------- Page 27-----------------------

Portlet 开发指南

新建好Portal 服务之后还需要设置一下tomcat 的模块部署方式。

27

----------------------- Page 28-----------------------

Portlet 开发指南

28

----------------------- Page 29-----------------------

Portlet 开发指南

快速入门

首相给出两个例子,一个是最简单的hello world,另一个是增删改查,如果现在还不能
理解,没有关系以后的章节会具体讲解。因为这里开发的Portlet 是符合JSR168、JSR286 规
范的,所以可以同时在WebSphere Portal、Pluto Portal 中运行,但是在开发IDE 中由于开发
工程需要设定不同的配置,所以还是有些不同的,这里采用的方式是首先在IDE 中开发适合
WebSphere Portal 的工程,通过RAD 可以直接部署到WebSphere Portal,如果要部署到Pluto
Portal 可以通过工程打成war 包,然后把war 包稍加修改部署到Pluto Portal 中。

HelloPortlet

新建Portlet

29

----------------------- Page 30-----------------------

Portlet 开发指南

30

----------------------- Page 31-----------------------

Portlet 开发指南

31

----------------------- Page 32-----------------------

Portlet 开发指南

32

----------------------- Page 33-----------------------

Portlet 开发指南

部署

33

----------------------- Page 34-----------------------

Portlet 开发指南

CRUDPortlet

CrudPortlet 主要实现增删改查功能,具体请见代码实现,后续章节会讲解

在Pluto Portlet 中部署

在Pluto Portal 中部署唯一的区别是要在web.xml 中添加Portlet 的定义,比如:

<servlet>
<servlet-name>PG03FirstPortlet</servlet-name>
<servlet-class>org。apache。pluto。container。driver。PortletServlet</servlet-class>
<init-param>
<param-name>Portlet-name</param-name>
<param-value>PG03FirstPortlet</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

34

----------------------- Page 35-----------------------

Portlet 开发指南

<servlet-mapping>
<servlet-name>PG03FirstPortlet</servlet-name>
<URL-pattern>/PlutoInvoker/PG03FirstPortlet</URL-pattern>
</servlet-mapping>

以helloPortlet 为例整个过程如下
1. 使用RAD 导出war 包PG03FirstPortlet。war
2. 修改web.xml,添加Portlet 定义
3. 把 war 包部署在 Pluto Portal 中,因为Pluto Portal 就是tomcat,所以可以直接把
PG03FirstPortlet。war 拷贝到webapp 目录下面。
4. 登陆Pluto Portal,添加测试页面,在测试页面中添加PG03FirstPortlet。

CRUDPortlet 部署过程如下
5. 使用RAD 导出war 包ContactsPortlet。war
6. 修改web.xml,添加Portlet 定义,添加数据源定义
7. 在META-INF 中添加context。xml

<?xml version="1。0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/pdwDS" auth="Container" type="javax。sql。DataSource"
maxActive="50" maxIdle="30" maxWait="10000" logAbandoned="true"

username="test" password="test" driverClassName="org 。apache 。
derby。jdbc 。ClientDriver"
URL="jdbc:derby://localhost:1527/test;create=true"/>
</Context>

8. 把 war 包部署在 Pluto Portal 中,因为Pluto Portal 就是tomcat,所以可以直接把
ContactsPortlet。war 拷贝到webapp 目录下面。
9. 在pluto-2.0。2\lib 中添加jstl 、jdbc 的jar 包。
10. 登陆Pluto Portal,添加测试页面,在测试页面中添加ContactsPortlet

35

----------------------- Page 36-----------------------

Portlet 开发指南

第二章节 独有概念

本章介绍 Portlet 独有的一些概念,比如 Portlet url、Portlet mode、window state、
preferences 等。

36

----------------------- Page 37-----------------------

Portlet 开发指南

四、 Portlet 概念

Portlet 定义

Portlet 提供了面向服务(SOA)的界面(User Interface),而且规范定了events、application
sessions、public render parameters 等特性来提供组件之间的交互的能力。Portal 提供整体页
面,Portlet 提供页面中一个区域,Portal 负责把Portlet 组合起来。值得注意的是规范都是针
对Portlet 和Portlet 容器的,并没有定义门户的实现方式。

Portlet 是Portal 页面中的一个区域

Portlet 负责生成一个个的页面片断,Portal 负责把这些片断聚集起来,Portal 还可以添
加一些title control buttons 元素。下图是一个页面的示意图,可以看到这个页面中共包括四
个Portlet。

请记住上图只是一个 Portal 实现的例子,可能存在其他的实现方式,这里要强调的是
Portal 中除了能聚集Portlet 还能有其他页面片断。

37

----------------------- Page 38-----------------------

Portlet 开发指南

Portal 页面的生成

Portlet 是运行在Portlet 容器中的,Portlet 容器服务通过Portlet 来生成内容,通常情况
下,Portlet 容器把生成的内容返给Portal,Portal 负责把生成的内容组合到一个页面,之后
把页面发送给客户端(比如web 客户端)。整个流程如下图:

Portal 页面请求

Portal 的请求顺序大概是这样的,客户端访问Portal 页面,Portal 会分析出需要处理
request 的Portlet 列表,Portal 通过Portlet 容器调用Portlet,Portlet 处理请求,之后通过Portlet
容器返回内容,Portal 把Portlet 产生的内容片断聚集起来返回给客户端。

Portlet 和Web 框架

Portlet 规范本身就提供了一套清晰的请求处理流程,使用 processAction 和
processEvent 处理提交请求,使用render 和serveResource 处理展现请求。Portlet 和web
框架(比如spring mvc、struts)可以配合使用,具体后续分析。

38

----------------------- Page 39-----------------------

Portlet 开发指南

五、 Portlet URLs

由于Portlet 不像servlet 有便准确定的URL 对应,但是浏览器最终还是需要通过URL 来
访问Portlet 的。所有Portlet 要提供生成Portlet URL 的功能。这些通过Portlet 容器为每个
Portlet 生成的可以请求相应Portlet 的URL 就叫做Portlet URL。
PortletAPI 中定义了PortletURL 和 ResourceURL 两个接口,Portlet 容器生成的必须是
PortletURL 或者 ResourceURL 接口对应的对象。Portlet 使用 PortletResponse 接口的
createActionURL、createRenderURL,createResourceURL 三个方法来生成Portlet URL。
Render URL 必须是幂等的,也就意味着不能在render 方法中作修改状态、做后台数据
的工作,需要特别注意,不能把render URL 用在form 中,否则容器将不会把form 中的参数
传输给Portlet。

BaseURL 接口

BaseURL 接口提供了所有 Portlet URL 的公共功能,它有两个子接口 PortletURL 和
ResourceURL。可以通过 PortletResponse 对象调用 createActionURL、 createRenderURL、
createResourceURL 来生成 PortletURL 和 ResourceURL 对象。BaseURL 对象可以调用
setParameter 和setParameters 来添加设置参数。Portlet 可以调用BaseURL 的setProperty、

39

----------------------- Page 40-----------------------

Portlet 开发指南

addProperty 方法来设置属性。

PrintWriter writer=response.getWriter();
PortletURL URL = response.createRenderURL();
URL.setParameter("customer"、"foo.com");
URL.setParameter("show"、"summary");
Writer.print("<A HREF=\"");
URL.write(writer);
Writer.print("\">Summary</A>");

包含Portlet Mode 和 Window State 信息

可以调用PortletURL 的setWindowState 和setPortletMode 来设置state、mode。

PrintWriter writer=response.getWriter();
PortletURL actionURL = response.createActionURL();
actionURL.setParameter("paymentMethod"、"creditCardInProfile");
actionURL.setWindowState(WindowState.MAXIMIZED);
writer.print("<FORM METHOD=\"POST\" ACTION=\" ");
actionURL.write(writer);
writer.print("\">");
writer.print("<INPUT name=\"submit\" type=\"submit\" value=\" 改变 Portlet
window state\" />");
writer.print("</FORM>");

Portlet URL 安全性

可以调用PortletURL 的setSecure 来设置Portlet 安全性,如果没有调用setSecure,默认
Portlet 使用安全性策略与Portal 一致。

总结

本章介绍了Portlet URL 的使用方法,请注意在Portlet 中用代码生成URL 的方式可以被
在jsp 中直接使用标签来代替。
对于使用JSR 168 API 的URL 生成,Portlet 始终必须在将 URL 对象写入到标记中之
前,使用 PortletURL.toString() 方法将其转换为字符串。由于WebSphere Portal 中的URL 的
丰富性质和长度不叫长,此字符串转换会负面影响创建大量URL 的Portlet 的性能。
JSR 286 添加了write() 方法,允许您将 URL 对象直接流向响应写出程序,从而避免创
建临时字符串对象。应该使用此方法来写出 URL。与toString() 方法不同,此方法还自动提

40

----------------------- Page 41-----------------------

Portlet 开发指南

供XML 和 HTML 规范所要求的 URL 的正确XML 转义。类似的注意事项同样适用于jsp
中的Portlet URL 标记:直接写出 URL 的标记语法优先于在临时字符串变量中存储生成的
URL 的标记语法。

41

----------------------- Page 42-----------------------

Portlet 开发指南

六、 Portlet Modes

Portlet 的modes 用来指定访问的render 方式,默认情况下Portlet 有三种modes,分别
是view,edit,help,与其对应默认有三个调用方法分别是doview,doedit,deohelp。一般
情况下Portal 会对用户访问view,edit,help 的权限做一些限制,比如可以让所有用户访问
view,help mode,但是只有特殊权限的用户可以访问edit modes。用户可以直接通过门户来
修改当前Portlet 的mode,门户提供的此功能是根据不同厂商而定的,当然也可以通过编程
的方式调用标准的api 来修改修改当前Portlet 的mode。

查看 Portlet Mode

view mode 通过名字就可以理解,是用来Portlet 日常展现的modes,Portlet 必须具有此
mode。Portlet在view mode 的时候后台访问的是doView 方法,开发者通过重载GenericPortlet
抽象类的doView 方法来自定义此Portlet 的view mode 展现内容。

编辑 Portlet Mode

一般来说edit mode 用来设置用户的个性化设置,可以通过preferences 来设置,一般来
说不是所有用户都具备使用edit mode 的权限。Edit 是一个可选的modes。Portlet 在edit mode
的时候后台访问的是doEdit 方法,开发者通过重载GenericPortlet 抽象类的doEdit 方法来自
定义此Portlet 的edit mode 展现内容。

帮助 Portlet Mode

Help mode 是用来提供Portlet 的帮助信息的mode,help 同样也是一个可选的mode。
Portlet 在help mode 的时候后台访问的是doHelp 方法,开发者通过重载GenericPortlet 抽象
类的doHelp 方法来自定义此Portlet 的help mode 展现内容。

自定义Portlet Modes

除了默认提供的三个mode,可以也可以自己来定义mode,比如ibm 的Portal 中就自
己定义了两种mode (config、edit_defaults)。首先需要在Portlet.xml 进行定义。

<custom-Portlet-mode>

42

----------------------- Page 43-----------------------

Portlet 开发指南

<Portlet-mode>config</Portlet-mode>

</custom-Portlet-mode>

<custom-Portlet-mode>

<Portlet-mode>edit_defaults</Portlet-mode>

</custom-Portlet-mode>

之后要重写请求分发的doDispatch 方法

protected void doDispatch(RenderRequest request、RenderResponse response) throws
PortletException、IOException {
if (!WindowState。MINIMIZED。equals(request。getWindowState())){
PortletMode mode = request。getPortletMode();
if (CUSTOM_CONFIG_MODE。equals(mode)) {
doCustomConfigure(request、response);
return;
}
else if (CUSTOM_EDIT_DEFAULTS_MODE。equals(mode)) {
doCustomEditDefaults(request、response);
return;
}
}
super。doDispatch(request、response);
}

受支持的 Portlet Modes

每个Portlet 必须定义它们支持的mode 类型,portlet.xml 中定义,如下图:

<supports>
<mime-type>text/html</mime-type>
<Portlet-mode>view</Portlet-mode>
<Portlet-mode>edit</Portlet-mode>
<Portlet-mode>help</Portlet-mode>
<Portlet-mode>config</Portlet-mode>
<Portlet-mode>edit_defaults</Portlet-mode>
</supports>

43

----------------------- Page 44-----------------------

Portlet 开发指南

七、 Window States

Portlet state 主要定义了某个Portlet 占所在Portal 页面的大小,Portlet 默认共有三种state,
分别是 normal、maximized、minimized,normal 代表正常大小,maximized 代表最大化,
minimized 代表最小化。

正常Window State

正常状态下,Portal 会按照正常的设定大小来展现。Portlet 会与其他portlet 共享此portal
页面,共同在portal 页面中展现内容。

最大化 Window State

最大化情况下,Portal 会在整个页面只展现这一个Portlet,或者用大部分页面来展现这
个Portlet,这取决有Portal 的实现。

最小化 Window State

最小化情况下Portal 页面中只展现Portlet 的title,不展现具体内容。

自定义Window States

客户可以自定义window 的状态,比如一半大小,不过对于笔者开来,这样通常意义不
大,很少有这样的需求

支持的 Window State

如果没有特殊定义,所有 portlet 默认是支持 normal、maximized、minimized 这三种
window state 。

44

----------------------- Page 45-----------------------

Portlet 开发指南

八、 Portlet Preferences

Portlet 通过配置功能来提供个性化的内容展现,配置信息必须有一个持久化的机制,
JSR168 规范中规定了这个机制,并提供Portlet preferences 来作为具体调用的方式。值得说
明的是,Portlet preferences 只是用来提供Portlet 配置信息的持久化功能,并不能用来替代
数据库。

PortletPreferences 接口

Portlet 使用PortletPreferences 接口来调用preferences,Portlet 可以在处理请求的时候
访问PortletPreferences,但是只能在processAction、processEvent 和serveResource 方法中
修改Preferences、这点需要注意,不能在render 中修改Preferences,否则可能造成Preferences
的混乱。Preferences 中保存的对象只能是String,也可以设置为null。
PortletPreferences 接口中提供如下方法
 getNames

 getValue

 setValue

 getValues

 setValues

 getMap

 isReadOnly

 reset

 store

具体使用方式见下面代码

PortletPreferences prefs = request.getPreferences();
try {
prefs.setValue(TEST_KEY,request.getParameter(CONFIG_TEXT));
prefs.store();
}
catch( ReadOnlyException roe ) {
}
catch( ValidatorException ve ) {
}

Preference Attributes 范围

Preference Attributes 也有范围得概念,但是规范中并没有对这块定义的特别明确,究
其原因是因为各个门户的实现厂商会利用preference 的概念来对门户的个性化提供支持,但
是实现的理论基础可能不一样,所以这块没有特别进行明确清楚。

45

----------------------- Page 46-----------------------

Portlet 开发指南

Preference Attributes 定义

Preference 可以预先在Portlet.xml 里面定义作为出事值,可以在定义是设置此属性是否
为只读。下面是一个例子:

<portlet>
...
<!—- Portlet Preferences -->
<portlet-preferences>
<preference>
<name>PreferredStockSymbols</name>
<value>FOO</value>
<value>XYZ</value>
<read-only>true</read-only>
</preference>
<preference>
<name>quotesFeedURL</name>
<value>http://www.foomarket.com/quotes</value>
</preference>
</portlet-preferences>
</portlet>

46

----------------------- Page 47-----------------------

Portlet 开发指南

第三章节 基础概念

本章节主要描述Portlet 开发中最重要、基础的概念,比如Portlet config、context、request、
response、session 等。

47

----------------------- Page 48-----------------------

Portlet 开发指南

九、 Portlet 生命周期接口

Portlet 规范中共有三个接口定义了Portlet 的生命周期,分别是Portlet、EventPortlet 和
ResourceServingPortlet 接口。Portlet 接口是Portlet API 中的主要点和关键点。所有Portlet 直
接或者间接的实现这个接口。Portlet 可以选择性的实现 EventPortlet 和
ResourceServingPortlet 接口来实现附加的功能。GenericPortlet 类实现了Portlet、EventPortlet
和ResourceServingPortlet 三个接口,并且提供了一些实用的默认实现。开发者可以直接继承
GenericPortlet 类来方便开发Portlet。

Portlet 实例的数量

Portlet 部署描述符中(Portlet.xml )中定义了Portlet 容器怎么创建Portlet 实例。默认情
况下,Portlet 不是在分布式环境中,Portlet 容器必须实例化和使用唯一的一个Portlet 实例
对象。如果是在分布式环境中每个jvm 维护一个Portlet 实例对象。不过这些都是对Portlet
容器实现厂商的规定,开发者一般不用过多关注。

Portlet 生命周期

和servlet 一样,Portlet 容器管理着Portlet 的生命周期,Portlet 生命周期定义了Portlet
怎么被加载、实例化、初始化,怎么接受客户端发过来的request,怎么销毁。Portlet 生命
周期通过Portlet 接口中的init、processAction、render 和destroy 几个方法来实现。当然
EventPortlet 和ResourceServingPortlet 接口中定义了附加的一些方法。

加载和实例化

Portlet 容器负责加载和实例化Portlet。加载和实例化可以发生在Portlet 刚部署时,亦
可以延时到有请求要访问这个Portlet。Portlet 容器加载Portlet 的类加载器要与servlet 容器
加载servlet 的类加载器一致。当Portlet 容器加载好Portlet 后就会实例化这个Portlet。

初始化

当Portlet 被实例化之后,Portlet 容器必须先初始化这个Portlet 才能让请求访问这个
Portlet。Portlet 容器调用Portlet 接口的init 方法初始化Portlet。这里很像servlet 的方式,
在Portlet 接口的init 方法中可以调用PortletConfig 接口的对象,通过PortletConfig 的实例可

48

----------------------- Page 49-----------------------

Portlet 开发指南

以访问 Portlet.xml 中的一些初始化参数和 ResourceBundle 。和servlet 一样可以通过
PortletConfig 访问 PortletContext 接口的对象,PortletContext 是用来保存上下问信息的。
PortletConfig 和PortletContext 介绍请见后续章节。
在初始化的过程中,Portlet 对象可能会抛出UnavailableException 或者PortletException
异常,此时Portlet 容器必须不能把此Portlet 对象作为可接受请求状态,必须释放此Portlet
对象。destory 方法也不能调用,因为并没有初始化成功。Portlet 容器可以在失败之后重新
尝试实例化和初始化此Portlet 对象。
开发者不能通过在Portlet 中添加静态变量和静态方法的方式来达到初始化资源的目的,
在init 被调用之前,不应该使用其他方式来初始化资源,所以最佳实践是在init 方法中初始
化这些资源。

结束服务

Portlet 容器没有必要一直加载这 Portlet 的实例,这要看中间件实现厂商的决定。当
Portlet 容器决定暂时停掉某个Portlet 的服务的时候,它会调用destory 方法,开发者可以在
desyory 方法中作一些释放资源和保存必要信息。例如Portlet 容器可以在决定减少服务器内
容资源或者app server 停止的时候来调用这个方法,什么时间、什么策略来调用主要看中间
件实现厂商的决定。当Portlet 容器调用destory 之前,它会让目前还在执行的线程执行完成,
当然为了避免永远等待下去,Portlet 容器也会有相应的策略来结束这种等待。一旦destory
方法被调用,Portlet 就不能再接受任何请求,如果容器想重启启动这个Portlet,就要重复之
前的加载、实例化、初始化过程。如果在在调用destory 的过程中出现了RuntimeException,
Portlet 容器必须保证Portlet 可以正常毁灭。当Portlet 被毁灭掉之后,Portlet 对应的对象就
会被释放,等待垃圾收集。

Portlet 的个性化

Portlet model 利用轻量级的模式提供所有请求的访问,这保证了Portlet 实例尽可能的
少并且对大量用户访问提供了可扩展性。为了区别不能级别的个性化,Portlet 规范中定义了
Portlet entity 和Portlet window。

Portlet 定义和 Portlet Entity

Portlet.xml 对Portlet 的定义中可以包括一组带有默认值的preferences,这组preferences
用来创建preferences 对象。在运行时,当Portlet 被request 请求的时候,Portlet 自身会与
一组preferences相关联。这些与特定的preferences绑定的Portlet产生的结果被定义成Portlet
Entity。Portlet Entity 概念是抽象的,并没有一个具体的对象(页面片断)与之相关联。这些
preferences 一般定义在Portlet.xml 里面,Portlet 中的行为和内容一般会与这些preferences
相关联,当然Portal 和Portlet 容器也提供了途径在运行时读取、增加和修改这些preferences。
首选项对象的操作、管理与配置和Portlet 窗口的创建是通过Portal 或Portlet 容器的实

49

----------------------- Page 50-----------------------

Portlet 开发指南

现来进行。该实现也可以提供其它高级特征,如首选项对象的分线管理或首选项属性的级联
变更。

Portlet Window

相对于Portal 这个具体的概念,Portlet 对用户来说还是比较抽象化的。Portal 中会包含
一个到多个Portlet window(页面片断),在Portal 页面中的每个Portlet,我们叫做一个Portlet
window。Portlet entity 通常会对应多个Portlet window,比如普通用户可以通过Portlet entity
的一个Portlet window 来查看信息,管理员可以通过这个 Portlet entity 的赢一个Portlet
window 来修改preferences 来达到管理此Portlet entity 的目的。
没有 Portlet window 对应一个唯一的 ID ,此 window ID 可以通过
PortletRequest.getWindowID()来获得。

Request 请求处理

当Portlet 对象被初始化的时候,Portlet 对象就可以处理Portlet 容器发过来的request
请求了。Portlet 接口定义了两个方法来处理请求,分别是processAction 方法和render 方法。
Portlet 还可以通过实现 EventPortlet 或者 ResourceServingPortlet 接口,从而通过
processEvent 和 serveResource 方法来处理请求。
当Portlet 容器调用Portlet 的processAction 方法的时候,Portlet request 对象被封装成
一个action request,然后发送给processAction 方法。作为这个action 处理的结果,这个Portlet
可能发布一些Portlet event,这时候另外的Portlet 的processEvent 会被调用,在processEvent
方法中会有一个event request 对象包含着事件请求。
当Portlet 容器调用Portlet 的render 方法的时候,Portlet request 对象被封装成一个
render request 对象。
当Portlet 容器调用Portlet 的serveResource 方法的时候,Portlet request 对象被封装成
一个resource request 对象。
通常情况下Portlet 的请求是URL 触发的,这些有Portlet 生成的URL 叫做Portlet URL。
Portlet URL 分为三类action URLs、render URLs 和 resource URLs。
假设这种场景,一个Portal 页面中有n 个Portlet (n>1),那么一个Portlet action 请求会
触发一个antion 请求、0-m 个event 请求,n 个render 请求。一个render 请求,会触发n
个render 请求。一个resource 请求,会触发一个resource 请求。
如果是一个process 请求,那个Portlet 容器必须先调用这个Portlet 的process action 方
法。等待process 方法完成之后才能调用event 方法。等event 方法调用完成之后再调用这
个页面中所有Portlet 的render 方法,除非某个Portlet 定义了缓存。值得注意的是render
方法的调用时没有特定顺序的。
如果是一个render 请求,Portlet 容器调用页面中所有Portlet 的render 方法,除非某个
Portlet 定义了缓存。值得注意的是render 方法的调用时没有特定顺序的。
如果是一个resource 请求,Portlet 容器调用页面中所有Portlet 的serveResource 方法,
除非某个Portlet 定义了缓存。

50

----------------------- Page 51-----------------------

Portlet 开发指南

如果Portlet 中定了缓存,Portal 可以按照策略不调用Portlet 的render、serveResource
请求。
之前也说过如果某个Portlet 一段时间没有被请求,可能被Portlet 容器给销毁掉。

Action Request

一般情况下action Request 请求用来修改数据库、Portlet preferences 等信息。
processAction 方法有两个参数ActionRequest 和ActionResponse 。
ActionRequest 提供了获得action 参数、window state、Portlet mode,Portal context、Portlet
session、Portlet preferences 的途径。
当处理action 请求的时候,Portlet 可以指示Portlet 容器redirect 到一个URL。通过在
processAction 中调用redirect 方法,这时与servlet 进行页面的redirect 达到的效果一样。
可以通过ActionResponse 对象来改变window 状态、Portlet 模式,要修改Portlet 模式,
前提是当前用户有这个权限来进入到相关的Portlet 模式。
可以在处理action 请求的时候调用ActionResponse 对象来设置render 参数。
Portlet 可以把一个action 请求委派给servlet 处理。
Portlet 可以通过ActionResponse 的setEvent 方法来发布事件。

Event Request

一般情况下event 用来在不同Portlet 之间进行协作。

51

----------------------- Page 52-----------------------

Portlet 开发指南

EventPortlet 接口的processEvent 方法有两个参数EventRequest 和EventResponse。
可以从 EventRequest 中得到 event payload 、window state 、Portlet mode 、render
parameters、Portal context、Portlet session 、Portlet preferences。
Portlet 可以在通过EventResponse 来更改window 状态、Portlet 模式,要修改Portlet
模式,前提是当前用户有这个权限来进入到相关的Portlet 模式。
可以在event 请求的时候调用EventResponse 对象来设置render 参数。
Portlet 可以把一个event 请求委派给servlet 处理。
Portlet 可以通过EventResponse 的setEvent 方法来发布事件。

Render Request

一般情况下render 请求用来产生展现内容。
Portlet 接口的render 方法有两个参数RenderRequest 和 RenderResponse。
可以从RenderRequest 得到请求参数、window state、Portlet mode、render parameters、
Portal context、Portlet session、Portlet preferences。
Portlet 可以通过本身的renderResponse 来产生内容,或者委托给servlet\jsp 。
Render 请求不应该触发任何的状态的改变,也就是说render 请求时幂等的。

Resource Request

Resource request 是为了服务资源和内容片断,可以通过实现ResourceServingPortlet 接
口来做此工作。
ResourceServingPortlet 接口的 serveResource 方法有两个参 ResourceRequest 和
ResourceResponse。
可以从ResourceRequest 得到请求参数、window state、Portlet mode、render parameters、
Portal context、Portlet session 、Portlet preferences 数据。
Portlet 可以通过本身的serveResource 来产生内容,或者委托给servlet\jsp 。

GenericPortlet

GenericPortlet 是一个抽象类,它实现了 Portlet、EventPortlet、ResourceServingPortlet
三个接口,所以它提供了为events、resource 和 render 请求提供服务的能力,我们开发的
时候一般继承GenericPortlet 类。

Action Dispatching

GenericPortlet 中的processAction 来处理分发,也可以使用注解的方式。

52

----------------------- Page 53-----------------------

Portlet 开发指南

Event Dispatching

GenericPortlet 中的processEvent 来处理分发,也可以使用注解的方式。

Resource Serving Dispatching

GenericPortlet 中的serveTesource 来处理分发,也可以使用注解的方式。

Rendering Dispatching

GenericPortlet 中的render 来处理分发,也可以使用注解的方式。不过一般情况下render
方法会根据Portlet state 把请求分发给
 doView 用来处理VIEW 请求
 doEdit 用来处理EDIT 请求
 doHelp 用来处理HELP 请求

并行执行的请求

由于Portlet容器处理Portlet请求的时候是并行的,所以Portlet开发者必须处理话Portlet
的并行问题。

请求处理异常

在处理 Portlet 请求的时候可能会抛 PortletException 、PortletSecurityException 、
UnavailableException。

线程安全

与servlet 一样,在实现Portlet 是要注意线程安全的问题。

53

----------------------- Page 54-----------------------

Portlet 开发指南

总结

Portlet 规范中共有三个接口定义了Portlet 的生命周期,分别是Portlet、EventPortlet 和
ResourceServingPortlet 接口。
通过实现这三个接口,共有四个方法来分别处理四种不同的请求,分别是render(Portlet
接口定义)方法来处理render 请求,processAction (Portlet 接口定义)方法来处理action
请求,processEvent (EventPortlet 接口中定义)方法来处理 event 请求,serveResource
(ResourceServingPortlet 接口中定义)方法来处理resource 请求。
GenericPortlet 中实现了Portlet、EventPortlet 和ResourceServingPortlet 三个接口,并且
提供了一些默认方法的实现。可以通过直接继承抽象类GenericPortlet 来达到简化开发的目
的。
Portlet 的生命周期与servlet 生命周期有很多可比性,Portlet 容器管理着Portlet 的生命
周期,Portlet 生命周期定义了Portlet 怎么被加载、实例化、初始化,怎么接受客户端发过
来的request,怎么销毁。

54

----------------------- Page 55-----------------------

Portlet 开发指南

十、 Portlet Config

Portletconfig 对象提供了Portlet 初始化时需要使用的信息,Portletconfig 还提供了访问
Portlet context、default event namespace、public render parameter names、resource bundle 的
途径。这些信息都是在Portlet.xml 中定义。

初始化参数

可以通过 PortletConfig 接口的 getInitParameterNames 和 getInitParameter 方法从
Portlet.xml 中获取初始化参数,代码如下:

String initPara = this.getInitParameter("Portlet286.initpara");

Log.info(initPara);

Enumeration initParas = getInitParameterNames();

while (initParas.hasMoreElements()) {

initPara = initParas.nextElement().toString();

log.info(getInitParameter(initPara));

}

log.info(this.getInitParameterNames().toString());

Portlet Resource Bundle

可以在Portlet.xml 或者在资源文件里面定义Portlet 标题、关键字等信息,这些信息用
来在Portlet 展现的时候渲染Portlet 的title。比如在portle。xml 里面,代码如下:

<Portlet-info>

<title>PLT6ResourceBundlePortlet</title>

<short-title>PLT6ResourceBundlePortlet</short-title>

<keywords>PLT6ResourceBundlePortlet</keywords>

</Portlet-info>

当然也可以在resource-bundle 里面定义,代码如下:

<resource-bundle>
Com.Portlet286.plt6Portlet.nl.PLT6ResourceBundlePortletResource
</resource-bundle>

我们一般建议在资源文件中定义,这样可以很好的适应国际化的需要。

55

----------------------- Page 56-----------------------

Portlet 开发指南

在GenericPortlet 类中定义的render 方法使用PortletConfig 对象引用的ResourceBundle
对象来设置Portlet 的title

默认事件命名空间

可以通过PortletConfig 接口的getDefaultNamespace 方法从Portlet.xml 中获取默认的命
名空间,在events 和 public render parameters 中需要命名空间。

公告展现参数

可以通过PortletConfig 接口的getPublicRenderParameterNames 方法从Portlet.xml 中获取
到此Portlet 支持的public render parameter。

发布事件

可以通过PortletConfig 接口的getPublishingEventQNames 方法从Portlet.xml 中获取到此
Portlet 支持的publish event。

处理事件

使用 PortletConfig 接口的 getProcessingEventQNames 方法从 Portlet.xml 中获取到此
Portlet 支持的Process event。

支持的国际化

使用PortletConfig 接口的getSupportedLocales 方法从Portlet.xml 中获取到此Portlet 支
持的local(国际化)。

支持的运行时选项

使用 PortletConfig 接口的getContainerRuntimeOptions 方法从 Portlet.xml 中获取到此
Portlet 支持的Portlet 容器运行时。
容器运行时选项允许 Portlet 从门户和 Portlet 容器请求特定的运行时行为。

56

----------------------- Page 57-----------------------

Portlet 开发指南

总结

Portletconfig 对象提供了Portlet 初始化时需要使用的信息,Portletconfig 还提供了访问
Portlet context、default event namespace、public render parameter names、resource bundle 的
途径。这些信息都是在Portlet.xml 中定义。

57

----------------------- Page 58-----------------------

Portlet 开发指南

十一、 Portlet Context

Portlet context 与servlet context 在概念上是一致的,都是用来存储、获取Portlet 全局
context 的对象。

Portlet Context 范围

Portlet 容器中每一个实例化的Portlet 都只有一个PortletContext 对象实例,如果部署在
分布式环境中没没有jvm 都会有一个PortletContext 对象实例。

Portlet Context 功能

Portletcontext 的作用与servletcontext 一致,Portletcontext 在所在Portlet 的实例是全局
的,用户可以通过调用api 来从Portletcontext 存放属性和取回属性,也可以通过Portletcontext
来初始化一些参数,获取一个到servlet 和jsp 的分发器(dispatcher)。

与Servlet Context 关系

一个Portlet application 是普通的web application 的扩展版本,所以Portlet application 同
样具有servlet context,可以说Portletcontext 的实现上使用了大量servlet context 的功能,
但是需要强调的是两个对象是完全不同的两个对象。
Context 范围的初始化参数,对Portlet context 和servlet context 来说都是一样的,都是
在web.xml 中定义,而且Portlet context 和servlet context 中的属性是共享的。Portlet context
必须提供访问servlet context 中资源的方法。Portlet context 必须与servlet context 具有同样
的临时目录。Portlet context 必须与servlet context 对于虚拟主机和重新加载策略具有同样行
为和功能。
Portlet context 与servlet context 有同样的方法
 getAttribute
 getAttributeNames
 getInitParameter
 getInitParameterNames
 getMimeType
 getRealPath
 getResource
 getResourcePaths
 getResourceAsStream
 log
 removeAttribute

58

----------------------- Page 59-----------------------

Portlet 开发指南

 setAttribute

总结

Portlet context 的概念与servle tcontext 的概念基本一致,而且可以Portlet context 和
servlet context 之间是可以共享属性的。

59

----------------------- Page 60-----------------------

Portlet 开发指南

十二、 Portlet Requests

PortletRequest 封装了所有客户端的请求信息,比如请求parameters、request content data、
Portlet mode 、 window state 等等。Portlet 可以通过 processAction 、 processEvent 、
serveResource、render 方法来获取PortletRequest 对象。

PortletRequest 接口

与processAction、processEvent、serveResource、render 四个方法相对应,共有四个
具体的 request 对象供处理请求的方法使用,分别是 ActionRequest 、EventRequest 、
ResourceRequest、RenderRequest。PortletRequest 接口定义了所有request 接口的公共功能。
ClientDataquest 提供了ActionRequest 和ResourceRequest 的公共功能。Request 各个接口的
类图请见下图:

Request 参数

PortletRequest 接口可以通过如下方法获取参数
 getParameter

 getParameterNames

60

----------------------- Page 61-----------------------

Portlet 开发指南

 getParameterValues

 getParameterMap

 getPublicParameterMap

 getPrivateParameterMap

Form 表单和查询参数

如果使用form 表单进行提交,form 最好是post 方式。

Action 和 Event 请求参数

在action、event 方法中接受到得参数不能传递到之后需要执行的render 里面,在action
方法中接受到的参数也不会传递到接下来执行的event 方法中。如果确实需要在render 中使
用参数,需要在action、event 的response 调用setRenderParameter 或者setRenderParameters
方法。

Render 请求参数

如果有多个Portlet 在一个页面中,从客户的web 客户端中触发了多次请求,如果其中
一次的请求不是针对某个Portlet,那么这个Portlet 接受到的render 请求获取的参数与这个
Portlet 前一次接受到的请求时获取的参数是一样的。
如果一个Portlet 接受到一个事件,是因为在同一个页面中的针对其他Portlet 产生的(即
其他Portlet 发起事件),那么这个Portlet 接受到的render 请求获取的参数与这个Portlet 前
一次接受到的请求时获取的参数是一样的。
如果一个Portlet 接受到一个render 请求,是因为之前的action、event 请求产生的,那
么这个这个render 请求的参数是在action、event 中设置的。
如果一个Portlet 接受的render 请求就是因为一个针对此Portlet 的render 请求,那么接
受到的参数就是Portlet URL 中设置的参数。
总之,Portal 提供修改Portlet mode 和window state 的方法,URL 也是Portal 负责生成,
URL 触发的render 请求中的参数是会被保存的。Portlet 不能收到其他Portlet 的参数。Portlet
如果收到一个action、event 请求render 参数就会自动清除。

Resource 请求参数

Resource 请求参数是通过resource URL 中传递过来的。

61

----------------------- Page 62-----------------------

Portlet 开发指南

Public Render 参数

为了和在同一个Portlet application 或者跨Portlet application 中Portlet 之间可以进行协
作,Portlet 可以在Portlet.xml 中声明public render parameters,public render parameters 在
processAction、processEvent、render、serveResource 都可以获得和修改。
Portlet 容器只能把 public render 参数发送给在 Portlet.xml 中定义了
“supported-public-render-parameter “的Portlet。
如果Portlet 系统删除掉某个public render 参数,可以使用StateAwareResponse 接口或
者PortletURL 接口的removePublicRenderParameter 方法。
Portlet 获取私有和公共的参数用的都是getParameter 方法,但是获取参数Map 是使用
的方法是分开的,分别是getPrivateParameterMap 和getPublicParameterMap。

额外 Request 参数

Portal、Portlet 容器可以额外定义一些参数来支持本身Portal 应用的运转(以javax.Portlet
开头),但是这些参数对Portlet 来说是不可见的。

Request 属性

Request 属性不能在action、resource、event 和render 请求中共享。属性可以用来在
Portlet 和servlet 中共享信息,在PortletRequest接口中有如下操作属性的方法:
 getAttribute

 getAttributeNames

 setAttribute

 removeAttribute

以javax.Portlet.开头的属性名称是被保留的,开发者请不要使用。

Request 属性中获取用户信息

Portlet 可以通过PortletRequest.USER_INFO 属性访问用户信息。

Request Properties

可以通过PortletRequest 接口的如下方法访问一些properties,这些properties 是Portal、
Portlet 容器的一些特定的properties,或者有可能是http header 中的信息。
 getProperty

62

----------------------- Page 63-----------------------

Portlet 开发指南

 getProperties

 getPropertyNames

cookie

可以通过PortletRequest 接口的getCookies 方法来获取cookie 信息。

Request Context Path

可以通过PortletRequest 接口的getContextPath 方法来获取上下文路径

安全相关信息

可以通过PortletRequest 接口的这些方法访问一些用户信息

 getAuthType

 getRemoteUser

 getUserPrincipal

 isUserInRole

 isSecure

Response Content 类型

Portlet 可以通过getResponseContentType 来获取放回类型。
Portlet 支持多种 content types,默认情况下返回类型是String

国际化

可以通过PortletRequest 接口的getLocale 方法来获取此Portlet 的方言。

Portlet Mode

可以通过PortletRequest 接口的getPortletMode 方法来获取此Portlet 的mode。

63

----------------------- Page 64-----------------------

Portlet 开发指南

Window State

可以通过PortletRequest 接口的getWindowState 方法来获取此Portlet 的state。

访问 Portlet Window ID

可以通过PortletRequest 接口的getWindowID 方法来获取此Portlet 的WindowID。

ClientDataRequest 接口

ClientDataRequest 接口继承 PortletRequest 接口,提供 ActionRequest 和
ResourceRequest 接口的一些公共功能。ClientDataRequest 主要提供的功能是获取http 请求
信息,比如输入流。

接受上传数据

当有 post 表单把数据流上传到了服务器时,ClientDataRequest 接口可通过
getPortletInputStream 和getReader 来获取数据流。
为了管理上传到服务器的数据流,ClientDataRequest 接口提供了如下的方法。
 getContentType

 getCharacterEncoding

 setCharacterEncoding

 getContentLength

setCharacterEncoding 方法只在getReader 之前设置时,起到设置字符流的作用。

ActionRequest 接口

ActionRequest 接口继承ClientDataRequest 接口,目前ActionRequest 没有提供额外什么
功能。

ResourceRequest 接口

ResourceRequest 接口继承 ClientDataRequest 接口。ResourceRequest 接口还提供了

64

----------------------- Page 65-----------------------

Portlet 开发指南

getResourceID 方法来获取ResourceID。

EventRequest 接口

EventRequest 接口继承PortletRequest 接口,EventRequest 还提供了getEvent功能

RenderRequest 接口

RenderRequest 接口继承PortletRequest 接口,目前RenderRequest 没有提供额外什么
功能。

Request 对象的时间范围

每个request 对象都在一个特定的processAction、processEvent、serveResource 、render
方法调用中有效,request 对象只有在特定的范围内才有效。

总结

PortletRequest 封装了所有客户端的请求信息,比如请求parameters、request content data、
Portlet mode 、 window state 等等。Portlet 可以通过 processAction 、 processEvent 、
serveResource、render 方法来获取PortletRequest 对象。与processAction、processEvent、
serveResource、render 四个方法相对应,共有四个具体的request 对象供处理请求的方法使
用,分别是ActionRequest、EventRequest、ResourceRequest、RenderRequest。PortletRequest
接口定义了所有 request 接口的公共功能。ClientDataquest 提供了 ActionRequest 和
ResourceRequest 的公共功能。

65

----------------------- Page 66-----------------------

Portlet 开发指南

十三、 Portlet Response

PortletResponse 封装了所有Portlet 返回给Portlet container 的信息(重定向、Portlet
mode 改变、 标题、 内容等等),Portal 使用这些信息来组装呈现给客户端的内容。在
processAction、processEvent、serveResource 和 render 方法中可以获取response 方法。

PortletResponse 接口

PortletResponse 接口定义了ActionResponse、EventResponse、ResourceResponse 和
RenderResponse 接口的公共方法(功能)。与processAction、processEvent、serveResource、
render 四个方法相对应,共有四个具体的response 对象供处理请求的方法使用,分别是
ActionResponse 、 EventResponse 、 ResourceResponse 和 RenderResponse 。
StateAwareResponse 接口继承PortletResponse 接口,是ActionResponse 和 EventResponse
接口的父接口。MimeResponse 接口继承 PortletResponse 接口 ,是 RenderResponse 和
ResourceResponse 接口的父接口。类图请见下图:

Response Properties

可以使用PortletResponse 接口的下面两个方法来设置属性
 setProperty

66

----------------------- Page 67-----------------------

Portlet 开发指南

 addProperty

PortletResponse 中设置properties 会被作为Portal 的http header 被传递给客户端。如果
希望这些properties 被设置成功,那么必须在response 提交之前被调用,否则将被忽略。
Portlet 设置的 header 不一定会在 Portal application 中保存,有可能出于安全原因Portal
application 会做一些限制,或者Portlet 设置的header 被其他Portlet 所覆盖。

URLs 编码

Portlet 中需要引用Portlet application 中的servlets、JSPs、 图片和其他静态文件。有
些Portal、Portlet 容器的实现要求对这些URL 进行encode,因为有可能Portal 需要在这些
URL 中添加一些额外信息。如果对于某些Portal、Portlet 容器来说encode 是没有必要的,那
么encode 返回的内容是没有变化的。
Resources 的URL 如果没有被encode,那么Resources URL 是不能被保证可以被正常访
问。

Namespacing

可以使用PortletResponse 接口getNamespace 的方法来返回此Portlet 的命名空间,一般
来说namespace 用来在Portal 页面中唯一定义此Portlet 中的dom 元素,这样js 就可以准确
的定位到Portlet 中的元素了。

设定 Cookies

可以通过PortletResponse 接口addProperty 方法添加javax.servlet.http.Cookie 的key 值
来添加cookie。
JSR 286 添加了用于针对 Portlet 请求和响应读取和写入 Cookie 属性的API 方法,但
是门户实现可以自由决定有关如何存储和处理这些Cooie 的细节。WebSphere Portal 直接
将 Cookie 属性转换为实际的 HTTP Cookie。如果您不显式指定CooKie 路径,则会将其缺
省设置为门户的 URL 上下文,因此后续的门户请求可以正确地接收回Cookie,但是相同服
务器上的其他Web 应用程序则不能。
Cookie 不在某个命名空间中,因此可以在Portlet 之间共享,如果需要的话,还可以与
其他Web 应用程序共享。因此 Cookie 提供了 Portlet 之间的替代协作机制,这在某些情
况下可能非常有用。由某个 Portlet 设置的新Cookie 对相同客户端请求的后续生命周期阶
段中的所有 Portlet 可见,除非客户端决定丢弃它们,否则在后续请求中也可见。
WebSphere Portal V6.1 目前不支持在呈现阶段中设置Cookie。当客户端响应已经在呈
现阶段中提交时,这些 Cookie 未传输到客户端,从而在后续的请求中丢失。

67

----------------------- Page 68-----------------------

Portlet 开发指南

StateAwareResponse 接口

StateAwareResponse 接口继承 PortletResponse 接口,是 ActionResponse 和
EventResponse 接口的父接口。StateAwareResponse 接口提供了设置 render parameters、
Portlet mode、window state 的功能。

Render Parameters

使用StateAwareResponse 接口的setRenderParameter 、setRenderParameters 方法来设
置render 参数。与Portlet 在URL 中产生的render 参数一样,如果没有一个新的请求(比如
processaction,processevent,render)来再次请求这个Portlet,这些参数将一直存在。
可以通过removePublicRenderParameter 方法来删除公共参数。

修改Portlet Modes 和Window State

使用StateAwareResponse 接口的setPortletMode 方法来修改mode
使用StateAwareResponse 接口的setWindowState 方法来修改state

发布 Events

使用StateAwareResponse 接口的setEvent 方法来发布事件

ActionResponse 接口

ActionResponse 接口继承StateAwareResponse 接口,这个接口还提供了redirect 到其它
URL 的sendRedirect 方法。
sendRedirect 方法可以让Portal 跳转到另一个URL。如果在sendRedirect 方法之前调用
setPortletMode,setWindowState,removePublicRenderParameter,setRenderParameter 或 者
setRenderParameters 方法,则会抛出IllegalStateException 异常。也就是说在redirect 之前不
要修改Portlet 的属性状态信息。

EventResponse 接口

EventResponse 接口继承StateAwareResponse 接口

68

----------------------- Page 69-----------------------

Portlet 开发指南

MimeResponse 接口

MimeResponse 接口继承 PortletResponse 接口 ,是 RenderResponse 和
ResourceResponse 接口的父接口。MimeResponse 接口提供生成输出内容的功能。

返回内容类型

一般情况用如下方法来设置返回内容类型, setContentType 必须在获取输出的getWriter
或者getPortletOutputStream 方法之前调用,否则会被忽略掉。

Response.setContentType(request.getResponseContentType());

Output Stream 和Writer 对象

可以使用Output Stream 和Writer 来生成输出内容,Output Stream 用来生成二进制内容,
Writer 用来生成字符文本内容。

Buffering

为了输出更加有效Portlet 可以提供(非必须)buffer 功能。一般情况,Portlet 默认会启
用buffer,然后容许Portlet 在运行时设置一些参数,比如:
 getBufferSize

 setBufferSize

 isCommitted

 reset

 resetBuffer

 flushBuffer

RenderResponse 接口

RenderResponse 接口继承MimeResponse 接口。这个接口可以设置Portlet 的title

69

----------------------- Page 70-----------------------

Portlet 开发指南

ResourceResponse 接口

ResourceResponse 接口继承MimeResponse 接口。这个接口可以为客户端直接产生内容,
而不用经过Portlet 容器的封装处理。

Response 对象的时间范围

每个response 对象都在一个特定的processAction、processEvent、serveResource 、render
方法调用中有效,response 对象只有在特定的范围内才有效。

70

----------------------- Page 71-----------------------

Portlet 开发指南

十四、 Sessions

Portlet 中的session 与servlet 中的session 概念和作用上基本一致,都是为了保存一个
用户的信息,使之可以在多次操作中共享信息。有很多种方法来达到服务端跟踪客户的状态:
 HTTP Cookies

 SSL Sessions

 URL rewriting

开发者可以方便的通过PortletSession 来获取到当前的用户信息,而不用实际关心服务
端(容器)是怎么跟踪用户状态的。

创建Session

在同一个Portlet application 中的多个Portlet 必须使用同一个session。

Session 范围

在不同的Portlet application 中的Portlet 不能共享session。

Session 中设置属性

Portletsession 定义了 APPLICATION_SCOPE 和 PORTLET_SCOPE 两个范围,
APPLICATION_SCOPE 代表这个Portlet war 中的所有Portlet 共享的范围,PORTLET_SCOPE 代表
单独的这个Portlet windows 的范围。
通过HttpSessionBindingListener 可以知道session 中何时保存了属性何时删除了属性。
PortletSessionUtil 工具类中提供了方法确定 PortletSession 中对象的范围,如果对象保存在
PORTLET_SCOPE 范围内,PortletSessionUtil 工具类的decodeAttributeName方法可以检索
属性名称,开发者可以通过PortletSessionUtil 工具类来在servlet 中处理PORTLET_SCOPE 范围
内保存的属性。

与Web Application HttpSession 关系

之前强调过一个 Portlet 的application 同样也是一个 web application 。一个Portlet
application 中可能包含jsp 和servlet。Portlets、servlets 、JSPs 可以通过session 共享信息
(数据)。注意这里面说的session 对象可能和servlet 中定义不是同一个对象,但是Portlets、
servlets 、JSPs 从session 中获取信息(数据)的方法是一致的。
Portlet container 必须保证所有保存在PortletSession 中的属性在httpsession 中同样可以

71

----------------------- Page 72-----------------------

Portlet 开发指南

获取到。比如Portlet 保存在PortletSession 中APPLICATION_SCOP 范围里的数据,jsp 、servlet
通过httpsession 也能获取到,PortletSessionjsp 、servlet 保存在HttpSession 中数据,Portlet
通过HttpSession 在APPLICATION_SCOP 范围内也能获取的到。

HttpSession 方法映射

HttpSession 与PortletSession 方法必须对应,例如:
 getCreationTime

 getId

 getLastAccessedTime

 getMaxInactiveInterval

 invalidate

 isNew

 setMaxInactiveInterval

 getAttribute

 setAttribute

 removeAttribute

 getAttributeNames

getAttribute、setAttribute、removeAttribute 和getAttributeNames 方法在HttpSession 接
口和PortletSession 接口中具有同样的功能,符合下列规则:

 PortletSession 中在在APPLICATION_SCOP 范围的属性与HttpSession 中的

属性具有同样的名称。

 PortletSession 中在在PORTLET_SCOPE 范围的属性,HttpSession 中的属性名

称有一定的前戳。

写入Portlet Session

可以在action、event、render 中处理session,但是在render 中处理session 会遇到一些
问题。

action 和 process event 中写入session

存在这并发问题

Render 中写入session

规范中并没有规定不可以在render 中修改session 的值,但是基于一般上的概念,render

72

----------------------- Page 73-----------------------

Portlet 开发指南

是只用来展现内容而并不是用来提供、修改什么内容,一般意义上render 方法是可以重复
调用而结果是一样的 (幂等)。所以在调用render 时并不建议修改session 数据。

保留的 HttpSession Attribute 名称

在session 中属性名称以javax 。Portlet 为开头是为Portlet 容器供应商保留的。Portlet
容器供应商使用此开头的属性来实现一些特定的功能,Portlet 开发者不应该使用此开头的
session 属性。

Session Timeouts

Portlet 中的session timeout 与servlet 中的session timeout 一样。

最后访问时间

Portlet 中的最后访问时间与servlet 中的最后访问时间一样。

重要的 Session 语义

Portlet 中的session 语义与servlet 中的session 语义一样。

总结

73

----------------------- Page 74-----------------------

Portlet 开发指南

十五、 请求分发给 Servlets 和 JSPs

Portlet 可以把生成内容、逻辑处理等工作委托给servlet、jsp 来做。一般来说Portlet 来
做mvc 中的控制器,jsp 用来做展现。PortletRequestDispatcher 接口提供了分发委托的能力。

获取 PortletRequestDispatcher

可以通过PortletContext 的两个方法获得PortletRequestDispatcher
 getRequestDispatcher

 getNamedDispatcher

一般通过getRequestDispatcher 来获取PortletRequestDispatcher

在Dispatcher 中添加查询参数

可以通过以“/ ”开头的字符串获得一个PortletRequestDispatcher 对象,可以在URL 中
添加参数。

String path = "/raisons.jsp?orderno=5";

PortletRequestDispatcher rd = context.getRequestDispatcher(path);

Rd.include(renderRequest, renderResponse);

使用Dispatcher

上面给出的例子是调用PortletRequestDispatcher 的include 方法,也可以调用forward 。
Portlet 容器必须保证调用PortletRequestDispatcher 的线程和servlet、jsp 的线程是同一个线
程。

Include 方法

在Portlet 的生命周期中所有方法中都可以调用PortletRequestDispatcher 接口的include
方法,而且可以调用多次。被include 的servlet、jsp 将接收到一个受限版的HttpServletRequest
和HttpServletResponse 对象。被Portlet include 的servlet、jsp 不能再调用RequestDispatcher
的forward 方法,否则会发生不可预知的问题。Render 方法include 的servlet、jsp 必须调用
get 请求。

74

----------------------- Page 75-----------------------

Portlet 开发指南

Included Request 参数

被include 的servlet、jsp 可以通过访问如下属性得到一些信息
 javax.servlet.include.request_uri

 javax.servlet.include.context_path

 javax.servlet.include.servlet_path

 javax.servlet.include.path_info

 javax.servlet.include.query_string

Included Request 属性

被Portlet include 的servlet、jsp 除了标准的servlet 规范中的属性,还可以通过访问如
下属性得到一些信息

范围 属性 类型
所有 javax.Portlet.config javax.Portlet.PortletConfig

processAction javax.Portlet.request javax.Portlet.ActionRequest

javax.Portlet.response javax.Portlet.ActionResponse

processEvent javax.Portlet.request javax.Portlet.EventRequest

javax.Portlet.response javax.Portlet.EventResponse

render javax.Portlet.request javax.Portlet.RenderRequest

javax.Portlet.response javax.Portlet.RenderResponse

serveResource javax.Portlet.request javax.Portlet.ResourceRequest

javax.Portlet.response javax.Portlet.ResourceResponse

forward 方法

只有 Portlet 中还没有输出提交到 response 时才可以调用 forward 方法。cookies,
properties, Portlet mode, window state, render parameters 和 Portlet title 这些信息必须在
forward 之前进行调用。在forward 返回之前,Portlet 容器不可以提交、关闭response 内容。
在Portlet forward 到的servlet 中,可以使用ServletRequest 获得RequestDispatcher 对象,
但不能通过ServletContext 对象获得。

Forwarded Request 参数

被forward 的servlet、jsp 可以通过访问如下属性得到一些信息
 javax.servlet.include.request_uri

75

----------------------- Page 76-----------------------

Portlet 开发指南

 javax.servlet.include.context_path

 javax.servlet.include.servlet_path

 javax.servlet.include.path_info

 javax.servlet.include.query_string

Servlet filters

Servlet filter 可以拦截Portlet 中include、forword 的servlet、jsp 。

改变默认的Included Forwarded Session 范围

默认情况下include 、forward 的servlet、jsp 与Portlet 对应的session 范围是application,
可以通过在Portlet.xml 中设置运行时参数来改变为Portlet 范围。但是现在还不能确认都有
哪些容器提供了这个特性。

总结

76

----------------------- Page 77-----------------------

Portlet 开发指南

十六、 Portlet 标签库

Portlet tag 可以让jsp 方便的访问request、 比如RenderRequest 或者ResourceRequest
和 response、 比如ActionResponse 或者 RenderResponse。也可以用来生成 Portlet URLs。
Portlet 容器负责提供标签库的实现,开发者使用Portlet tag 需要在jsp 页面中包含如下
内容:

<%@ taglib uri=”http://java。sun。com/Portlet_2_0” prefix=”Portlet”%>

当然为了规范的向后兼容性,也可以在jsp 页面中包含如下,这样jsp 就只能使用JSR168
中定义的“对象”

<%@ taglib uri=”http://java。sun。com/Portlet” prefix=”Portlet” %>

defineObjects 标签

defineObjects 标签负责定义jsp 中使用的对象,所以基本所有jsp 中都会有defineObjects
标签的定义,例如下面的写法:

<Portlet:defineObjects/>

有了上面定义,jsp 中有了很多有用的对象,具体包括如下对象:

 如果是render 方法include 的jsp ,必须有RenderRequest renderRequest、RenderResponse

renderResponse 对象

 如果是serveResource 方法include 的jsp ,必须有ResourceRequest resourceRequest、

ResourceResponse resourceResponse 对象

 如果是 processAction 方法 include 的jsp ,必须有 ActionRequest actionRequest 、

ActionResponse actionResponse 对象

 如果是 processEvent 方法 include 的jsp ,必须有 EventRequest eventRequest 、

EventResponse eventResponse 对象

 PortletConfig PortletConfig 对象

 PortletSession PortletSession,不产生新的session,如果还没有session 创建就返回空

 Map<String、Object> PortletSessionScope、返回的是PortletSession。getAttributeMap()

 PortletPreferences PortletPreferences 对象

 Map<String、String[]> PortletPreferencesValues、,返回的是PortletPreferences。getMap()

 其实这些对象就是放在servletRequest 中属性中的对象。

下面是一些例子:

<Portlet:defineObjects />

<%

out.println("renderRequest : " + renderRequest);

77

----------------------- Page 78-----------------------

Portlet 开发指南

out.println("");

out.println(".。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

out.println("renderResponse : " + renderResponse);

out.println("");

out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

out.println("PortletConfig : " + PortletConfig);

out.println("");

out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

out.println("PortletSession : " + PortletSession);

out.println("");

out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

out.println("。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

out.println("PortletPreferences : " + PortletPreferences);

%>

输出内容是:

renderRequest : com 。ibm 。ws 。Portletcontainer 。core 。impl 。

RenderRequestImpl@d700d7 wrapping com 。 ibm 。 wps 。 engine 。

PortalRequestWrapper@53435343 wrapping com 。 ibm 。wps 。engine 。

ExtendedLocaleRequest@532d532d wrapping com。ibm。ws。webcontainer。srt。

SRTServletRequest@73e573e5 。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。renderResponse :

com。ibm。ws。Portletcontainer。core。impl。RenderResponseImpl@10e010e

wrapping com 。 ibm 。 wps 。 engine 。

HttpServletResponseWrapperOnWriter@7fb17fb1 wrapping com。ibm。wps 。

engine。HttpServletResponseWrapperOnWriter@7a107a10 wrapping com。ibm。

wps。engine。HttpServletResponseWrapperOnWriter@72fa72fa wrapping com。

ibm。wps。engine。HttpServletResponseWrapperOnWriter@71a671a6 wrapping

com。ibm。wps。engine。PortalResponseWrapper@54b354b3 wrapping com。ibm。

ws 。 webcontainer 。 srt 。

SRTServletResponse@74577457 。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。PortletConfig :

com 。 ibm 。 wps 。 pe 。 pc 。 waspc 。 core 。 impl 。

PortletConfigWrapper@4ec04ec 。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。PortletSession :

com 。 ibm 。 ws 。 Portletcontainer 。 core 。 impl 。

PortletSessionImpl@94a094a 。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。PortletPreferences :

PortletWindowIdentifier[7_8000CB1A00OM10IMKFFMF820G1、/。PGTagPortlet、
PGTagPortlet] - PortletPrefences : {}

78

----------------------- Page 79-----------------------

Portlet 开发指南

再次提醒,Jsp要想用这些对象必须在jsp中写<Portlet:defineObjects/>标签。

actionURL 标签

actionURL 标签生成一个指向此Portlet 的processAction 方法的URL,在actionURL 标签
中可以放入param 标签来设置参数
actionURL 中可以定义一些属性,这些属性不是必须的。

1. windowState,
2. PortletMode
3. var
4. secure
5. copyCurrentRenderParameters
6. escapeXml
7. name

<FORM method="POST"
action="<Portlet:actionURL copyCurrentRenderParameters="true"
windowState="maximized" PortletMode="edit" name="editStocks">
<Portlet:param name="page"value="1"/>
</Portlet:actionURL>">
<LABEL for="<%=com。Portalguide。pgtagPortlet。PGTagPortlet。FORM_TEXT%>">最大
化此Portlet、进入编辑模式:</LABEL><BR>
<INPUT name="<%=com。Portalguide。pgtagPortlet。PGTagPortlet。FORM_TEXT%>"
type="text"/> <INPUT
name="<%=com。Portalguide。pgtagPortlet。PGTagPortlet。FORM_SUBMIT%>"
type="submit"value="提交"/>
</FORM>

上面的例子创建了一个指向processAction 的URL,这个URL 可以使Portlet 进入编辑模
式、最大化此Portlet。

renderURL 标签

renderURL 标签生成一个指向此Portlet render 方法的URL,在renderURL 标签中可以放
入param 标签来设置参数
renderURL 中可以定义一些属性,这些属性不是必须的。

1. windowState,
2. PortletMode
3. var
4. secure

79

----------------------- Page 80-----------------------

Portlet 开发指南

5. copyCurrentRenderParameters
6. escapeXml
7. name

<FORM ACTION='<Portlet:renderURL PortletMode="view" windowState="normal">
<Portlet:param name="showQuote" value="myCompany"/>
<Portlet:param name="showQuote" value="someOtherCompany"/>

</Portlet:renderURL>

' METHOD="POST">
<INPUT NAME="back" TYPE="submit" VALUE="返回视图方式、Portlet变为正常大小">

</FORM>

上面的例子创建了一个指向render 的URL,这个URL 可以使Portlet 进入查看模式、使
Portlet 变为正常大小。

resourceURL 标签

resourceURL 标签生成一个指向此Portlet serveSesource 方法的URL,在resourceURL 标
签中可以放入param 标签来设置参数
resourceURL 中可以定义一些属性,这些属性不是必须的。

1. var
2. secure
3. id
4. cacheability

<Portlet:resourceURL id="/icons/mypict。gif" var="iconsURL "/>
<img src="<%=iconsURL%>" >

上面的例子创建了一个指向serveResource 的URL,这个URL 指向的是icons/mypict。
gif这个图片。是因为GeneralPortlet中默认的serveResource 如下

public void serveResource(ResourceRequest request 、 ResourceResponse response)
throws PortletException、IOException {
if (request。getResourceID() != null) {
PortletRequestDispatcher rd = getPortletConfig() 。getPortletContext() 。
getRequestDispatcher(
request。getResourceID());
if (rd != null)
rd。forward(request、response);
}
}

80

----------------------- Page 81-----------------------

Portlet 开发指南

namespace 标签

namespace 生成一个和PortletResponse。getNamespace 方法返回一样的唯一字符串,这
个字符串主要功能是在一个Portal 页面中有很多个相同的Portlet 的时候用来唯一确定一些
dom 元素

<A HREF=”javascript:<Portlet:namespace/>doFoo()”>Foo</A>

param 标签

param 标签用来定义actionURL、renderURL、resourceURL 标签的参数,前边的例子中已
经有介绍。

总结

Portlet 中的标签主要作用是方便开发者使用各种Portlet 的对象,如果不使用标签也能
使用代码的方式打到同样的目的,但是代码会看上去比较凌乱。在Portlet 中同样也可以使
用JSTL 等标签。

81

----------------------- Page 82-----------------------

Portlet 开发指南

十七、 Portlet 应用

一个Portlet application 就是一个普通定义web application。在Portlet application 中包括
Portlet 、Portlet.xml 、servlet、jsp 、html、classes、其他资源。

与Web Applications 的关系

除了Portlet 之外的所有Portlet application 中的组件(servlet、jsp 、html)都是运行在
servlet 容器之中的。Portlet 容器的实现一般来说是基于servlet 容器。

与PortletContext 的关系

Portlet 容器必须确保PortletContext 对象与Portlet application 是一对一对应关系的。如
果Portlet application 是分布式部署的,Portlet 容器必须为每个JVM 创建一个PortletContext
实例对象。

Portlet Application 中的元素

Portlet application 中包括web application 中的所有元素(servlet、jsp 、html)和Portlet
独有的元素(Portlet.xml)。

目录结构

Portlet application 与web application 的目录结构基本一致,Portlet application 还多包涵
一个Portlet.xml 文件

Portlet Application Classloader

Portlet 容器与servlet 容器必须使用同一个classloader。

Portlet Application 存档文件

Portlet application 与web application 一致,部署包形式是war 包。

82

----------------------- Page 83-----------------------

Portlet 开发指南

Portlet application 部署描述符

除了web application 标准的web.xml 部署描述符之外,Portlet application 还有一个
Portlet.xml 部署描述符。Portlet.xml 的作用是描述Portlet 容器、Portlet。

更新Portlet Application

Portlet 容器可以更新一个Portlet application 而不用重启Portlet 容器

83

----------------------- Page 84-----------------------

Portlet 开发指南

十八、 打包和部署描述符

Portlet.xml 部署描述为应用开发者、应用分发者、应用部署者之间定义了各种元素和配
置信息。
每个Portlet application 都需要一个Portlet.xml、一个web.xml 来定义Portlet application
的各种配置,web.xml 用来定义web application,Portlet.xml 来专门定义Portlet。Portlet 分
为两个版本(JSR168、JSR286),JSR286 版本的Portlet.xml 必须兼容于JSR168 的Portlet.xml。

Portlet 和部署描述符

在Portlet 规范中,web 资源(servlet、jsp 、html)和Portlet 有清晰的区别。Web.xml
部署描述符是不可以扩展的,所有的web 资源(servlet、jsp 、html)都在web.xml 中定义。
所有的Portlet 和Portlet 相关的设置都在Portlet.xml 中定义。

打包

和servlet 一样,Portlet application 中的所有web 资源(servlet、jsp 、html)、Portlet、
Portlet.xml、web.xml 都要打包成war 包。

版本信息

在META-INF/MANIFEST。MF 文件中用Implementation 来定义版本信息
例如

Implementation-Title: myPortletApplication
Implementation-Version: 1。1。2
Implementation-Vendor: SunMicrosystems。Inc

Portlet 部署描述符元素

Portlet.xml 包括两块内容Portlet Application 定义和Portlet 定义。

84

----------------------- Page 85-----------------------

Portlet 开发指南

处理Portlet 部署描述符规则

下面是一些对于Portlet 部署描述符通用的规则
1. Portlet 容器会忽略所有Portlet.xml 中的空格
2. Portlet容器会检查war 包是否是一个合格的Portlet war,包括是否包含Portlet.xml、
web.xml、Portlet 容器被建议根据dtd、xml schema 来检查Portlet.xml、web.xml 的
格式是否正确。

Portlet.xml 中唯一的值

下面的值必须在Portlet application 范围内唯一

 Portlet <Portlet-name>
 custom-Portlet-mode <Portlet-mode>
 custom-window-state <window-state>
 user-attribute中的<name>
 event-definition中的<name> 、<qname>
 public-render-parameter 中的<name> 、<qname>
 filter <filter-name>
下面的值必须在Portlet 范围内唯一

 init-param <name>
 supports <mime-type>
 preference <name>
 security-role-ref <role-name>
 <supported-processing-event>
 <supported-publishing-event>
 <supported-public-render-parameter>

Portlet 国际化支持

Portlet 用来<supported-locale>来定义支持的国际化

85

----------------------- Page 86-----------------------

Portlet 开发指南

第四章节 高级特性

高级特性部分主要包括事件模型、filter 等内容

86

----------------------- Page 87-----------------------

Portlet 开发指南

十九、 资源服务

Portlet 可以生成两种resource 链接
1. 直接引用同一个 Portlet application 中的一些静态资源,使用PortletResponse 。

encodeURL()方法来encode。这些请求并不会具有上下文信息,所以比较适合引用静态

资源。

2. Resource URL,这样的请求会调用Portlet 的serveResource 方法,这些请求具有上
下文信息,资源 URL 包含当前 Portlet 的瞬时状态(Portlet 模式、窗口状态和呈
现参数),但不能为此状态设置新值。
资源服务为您提供了对HTTP 协议的所有方面的完全控制。WebSphere Portal 将您在资
源响应上指定的所有响应属性作为 HTTP 标头写出,因此您可以控制所提供的内容的语言、
内容类型和其他信息。另一面在于,与普通页面请求相反,门户不为响应提供任何缺省标头
信息;所有信息都必须在资源服务过程中显式地进行设置。

ResourceServingPortlet 接口

通过调用 ResourceServingPortlet 接口的 serveResource() 方法,Portlet 不仅可以通过
控制门户访问而对资源进行保护,并且 Portlet 容器不会呈现任何除 serveResource() 方法
返回的内容之外的附加输出。这样,用户由于可以直接通过操作响应对象而被赋予了更多的
控制权限,并且没有额外门户请求的开销,减轻了门户服务的负载。而 Portal 服务器此时
只是充当了一个代理服务器的作用。

87

----------------------- Page 88-----------------------

Portlet 开发指南

访问 Render 参数、Portlet Mode、Window State

可以通过ResourceRequest 来获取Render 参数、Portlet Mode、Window State

PortletMode mode=request。getPortletMode();
System。out。println("PortletMode : "+mode);
System。out。println("WindowState : "+request。getWindowState());
System。out。println("WindowID : "+request。getWindowID());
System。out。println("Preferences : "+request。getPreferences());

访问Request 和 Response Headers

由于Portlet 容器、Portal 不会在request 中添加任何额外内容,也不会再response 中附
加输出,所有resource 可以完全获取request 和控制response。Portlet 可以像所有处理方法
一样通过getProperty 或者getProperties,使用resource 访问http header。同样resource 也
可以通过setProperty 或者addProperty 设置http header。值得注意的是,设置http header

88

----------------------- Page 89-----------------------

Portlet 开发指南

要在产生输出之前,否则会被Portlet 容器忽略。

获取 HTTP 方法

可以通过ResourceRequest 接口的getMethod 方法来获取http 方法,比如GET、POST 、
PUT

访问Resource ID

可以通过ResourceRequest 接口的getResourceID 方法来获取resource ID 方法,当调用了
setResourceID 方法后getResourceID 返回的是setResourceID 中设置的参数,如果没有调用过
setResourceID,则返回null。

Resource URLs

Resource URL 中的参数不能与render 的参数共享

Generic Portlet 支持

Generic Portlet 中提供了默认的serveResource 实现,默认情况下会forward 到resourceid
指向的资源。

public void serveResource(ResourceRequest request、ResourceResponse response)

throws PortletException、IOException {

if (request。getResourceID() != null) {

PortletRequestDispatcher rd = getPortletConfig()。getPortletContext()。

getRequestDispatcher(

request。getResourceID());

if (rd != null)

rd。forward(request、response);

}

}

Ajax 请求

Render 和serveResource 都可以接受到ajax 请求,两个方法使用的场景不一样,render

89

----------------------- Page 90-----------------------

Portlet 开发指南

可以用来修改Portlet 的state、window mode 等信息,serveResource 一般提供一些返回信息
的片段,比如json 、xml 等。

90

----------------------- Page 91-----------------------

Portlet 开发指南

二十、 Portlet 协作

为了提供协作的能力规范引入了如下特性:
1. 在application session 范围,同一个application 中的Portlet 可以共享session 信息。
2. Public render parameter 可以共享render 信息
3. Event 可以让Portlet 之间发送、接受事件Public Render Parameters
本章将介绍共享呈现参数和事件。
请注意Portlet 规范中并没有定义怎么把两个Portlet 中连线,具体实现(配置)方式需
要参考具体的Portal application。

Public Render Parameters

共享呈现参数,顾名思义,就是指 Portlet 之间共享参数,每一个 Portlet 对该参数的
修改都能够直接被另外支持该参数 Portlet 所获得。
Public render pararmeter 用来共享render 信息,比如,在页面中有两个Portlet,一个用
来展现用户所在城市的天气,一个用来展现用户所在城市的地图,我定义了一个共享呈现参
数来表示用户所在城市,那么如果客户在天气Portlet 中选择了一个城市,地图Portlet 可以
通过public render pararmeter 来获取用户所在城市,从而展现城市地图。从而实现了不同
Portlet 之间的协作。
除了Portlet 事件以外,公共呈现参数代表 Portlet 之间的协作方法。尽管两种机制都
允许在 Portlet 之间交换信息,但它们在几个方面存在差异。
正如在本文的第一部分所指出的,从编程的角度看,公共呈现参数的处理几乎与普通(私
有)呈现参数的处理完全相同:Portlet 可以使用JSR 168 为私有呈现参数引入的相同API
方法来设置和读取此参数。共享呈现参数与JSR 168 中已经有私有呈现参数的区别就在于,
私有呈现参数只为 Portlet 内部使用,而共享呈现参数则为多个Portlet 之间通信协作而设
置。共享呈现参数与事件相比的优势就在于避免了事件处理过程调用的繁琐。从程序员的角
度看,重要的区别在于,公共呈现参数是在 Portlet.xml 部署描述符中声明的。

声明

对共享呈现参数的使用声明包括两个部分,对共享呈现参数定义的声明和支持共享呈现
参数的 Portlet 声明。
1. 共享呈现参数定义声明:对于共享呈现参数定义的声明必须在 Portlet.xml 部署文
件中使用 <public-render-parameter> 关键字,该元素与 <Portlet> 元素并列为
<Portlet-app> 的分支。

<public-render-parameter>

<identifier>publicrenderparameter</identifier>

<name>publicrenderparameter</name>

</public-render-parameter>

2. 支持共享呈现参数 Portlet 声明:对于支持共享呈现参数的 Portlet 的声明需要在

91

----------------------- Page 92-----------------------

Portlet 开发指南

Portlet.xml 中<Portlet> 元素中使用<supported-public-render-parameter> 关键字

<supported-public-render-parameter>publicrenderparameter</supported-public-render-para
meter>

使用

与非共享呈现参数的使用方法相同,共享呈现参数可以通过 ActionResponse 的
setRenderParameter("标识","值") 方法设定,并通过 RenderRequest 的getParameter("标识
") 来获得。

response 。 setRenderParameter("publicrenderparameter", request 。
getParameter(FORM_TEXT));

<%=request。getParameter("publicrenderparameter") %>

Portlet Events

JSR 286 定义的事件模型是一种松耦合的代理事件模型。在此模型中,Portlet 定义可以
接收以及在 Portlet 部署描述符中公布的事件。在运行时,门户管理员(或业务用户)可以
将不同的 Portlet 连接在一起。
事件可以让Portlet接收到调用(从而修改Portlet 的状态等信息),而不是客户端触发的,
是事件触发的。
Portlet 事件服务并不是一个可信任消息服务(例如JMS )的替代。很多情况下Portlet
事件并不能总是保证能够传送到目的地。因此 Portlet 必须能够在部分或即使所有事件都不
能正确接收的情况下仍然能够工作。
另外,有的时候 Portlet 为了响应某一个事件,也会向另外的 Portlet 发布新的事件,
这样就形成了事件的衍生代。这在一定程度上可能造成事件的死锁,JSR 286 本身没有对衍
生代做出限制,但是很多 Portlet 容器会定义事件的最大衍生代以防止死锁的发生。读者在
开发相关应用时请注意其本身的限制。

EventPortlet 接口

为了可以接受到事件,Portlet必须实现EventPortlet接口,Portlet容器会调用processEvent
方法来处理接收到的事件

92

----------------------- Page 93-----------------------

Portlet 开发指南

Event 声明

对于一个事件的声明包括三个部分,分别是事件的定义声明、事件的发布载体声明也就
是发布该事件的 Portlet 声明、事件接收载体的 Portlet 声明。
1. 事件定义声明:我们需要在 Portlet.xml 中使用<event-definition> 元素对事件进行
声明,并且该元素与<Portlet> 元素并列作为<portlent-app> 的子元素

<default-namespace>http://PGEventPortlet/</default-namespace>

<event-definition>

<name>com。Portalguide。simpleevent</name>

<value-type>java。lang。String</value-type>

</event-definition>

<event-definition>

<name>com。Portalguide。complesevent</name>

<value-type>com。Portalguide。pgeventPortlet。SampleComplexEvent</value-type>

</event-definition>

对于一个事件的声明有两点需要注意:事件的名称和值的类型。对于事件名称,JSR 286
既可以为事件定义默认的命名空间,其作用域为所有未声明 QName 的事件;也可以为事
件单独定义自己的 QName。对于QName 和命名空间的理解,请读者参考XML 规范的相
关文档,本文不做详细介绍。对于事件值的类型,既可以是简单的Java 对象,例如 Integer,
String 等,也可以是预先定义的Java 复杂对象,但是前提是该对象必须实现 Serializable 接
口。上面的代码是默认命名空间的声明,下面的代码是自定义命名空间的声明方式

<event-definition>

<qname xmlns:key="http://www。ibm。com">event-with-simple-value</qname>

<value-type>java。lang。Integer</value-type>

</event-definition>

<event-definition>

<qname xmlns:key="http://www。ibm。com">event-with-qname</qname>

<value-type>com。ibm。JSR286。。TestEventBean</value-type>

</event-definition>

2. 事件发布载体声明:事件的发布载体声明需要在 Portlet.xml 的<Portlet> 元素中

93

----------------------- Page 94-----------------------

Portlet 开发指南

用<supported-publishing-event> 关键字。对应事件声明格式,事件发布载体 Portlet
声明亦有默认命名空间和自定义命名空间以及简单对象和复杂对象的情况,见示例:

<Portlet>

<Portlet-name>ComplexEventSenderPortlet</Portlet-name>

<display-name xml:lang="zh">ComplexEventSenderPortlet</display-name>

<display-name>ComplexEventSenderPortlet</display-name>

<Portlet-class>com。Portalguide。pgeventPortlet。

ComplexEventSenderPortlet</Portlet-class>

<supported-publishing-event>

<name>com。Portalguide。complesevent</name>

</supported-publishing-event>

</Portlet>

3. 事件接收载体声明与事件发布载体声明类似,事件的接收载体声明需要在
Portlet.xml 的<Portlet> 元素中用<supported-processing-event> 关键字。

<Portlet>
<Portlet-name>SimpleEventReceiverPortlet</Portlet-name>
<display-name xml:lang="zh">SimpleEventReceiverPortlet</display-name>
<display-name>SimpleEventReceiverPortlet</display-name>
<Portlet-class>

com。Portalguide。pgeventPortlet。SimpleEventReceiverPortlet</Portlet-class>
<supported-processing-event>

<name>com。Portalguide。simpleevent</name>
</supported-processing-event>
</Portlet>

发送 Events

JSR 286 事件传播机制描述每当某个 Portlet 发布了事件时的自动化 Portlet 交互。
Portlet 生命周期的事件阶段不允许任何类型的客户端用户交互。
我们可以在希望发布事件的 Portlet 的 processAction() 方法里,通过调用
ActionResponse 的setEvent() 进行事件发布,setEvent() 方法的输入参数为事件的名称和对
应的值,这些参数必须与我们前面在 Portlet.xml 中的事件声明一致。

//Initialize the fields in the class as per your requirement

java。lang。String sampleObject = new java。lang。String("test event");
response。setEvent("com。Portalguide。simpleevent", sampleObject);

94

----------------------- Page 95-----------------------

Portlet 开发指南

Event 处理

事件的接收 Portlet 必须实现javax 。Portlet。EventPortlet 接口,事件的接收处理则在
该接口包含 processEvent() 方法中进行,JSR 286 定义该方法提供了两个输入参数:
EventRequest 和 EventResponse,我们可以通过调用EventRequest 实例的getEvent() 方法
来获得当前事件,该方法返回一个事件对象的实例,该实例封装了事件的唯一标识和对应的

值。获得事件对象后,我们也可以通过 getQNames() 方法或者 getName() 获得事件的
名称。两种获得事件方法的区别是 getQNames() 可以得到事件的全称标识,而 getName()
只是取得本地标识名。而取得事件的值则可以通过事件的getValue() 方法获得。

Event sampleEvent = request。getEvent();
if(sampleEvent。getName()。toString()。equals("com。Portalguide。simpleevent"))
{
Object sampleProcessObject = sampleEvent。getValue();
System。out。println(sampleProcessObject);

}

GenericPortlet support

在JSR 168 Portlet 的开发中,开发者通常继承抽象类javax 。Portlet。GenericPortlet 来
实现自己的 Portlet 逻辑代码。同JSR 168 相比,JSR 286 的GenericPortlet 增加了javax 。
Portlet。EventPortlet 和javax 。Portlet。ResourceServingPortlet 接口的实现,从而增加了事
件处理和资源服务的功能。
在GenericPortlet 中添加了默认的processEvent 实现,所以默认情况下processEvent 只
是把eventRequest 作为参数传递(response。setRenderParameters(request);)

public void processEvent(EventRequest request, EventResponse response) throws
PortletException, IOException {

String eventName = request。getEvent()。getQName()。toString();

try {
// check for exact match
Method eventMethod = processEventHandlingMethodsMap。get(eventName);
if (eventMethod != null) {

eventMethod。invoke(this, request, response);
return;

95

----------------------- Page 96-----------------------

Portlet 开发指南

} else {
// Search for the longest possible matching wildcard annotation

int endPos = eventName。indexOf('}');
int dotPos = eventName。lastIndexOf('。');
while (dotPos > endPos) {

String wildcardLookup = eventName。substring(0, dotPos + 1);
eventMethod = processEventHandlingMethodsMap 。
get(wildcardLookup);
if (eventMethod != null) {
eventMethod。invoke(this, request, response);
return;
}
if (dotPos == 0) {
break;
}
dotPos = eventName。lastIndexOf('。', dotPos - 1);
}
}
} catch (Exception e) {
throw new PortletException(e);
}

// if no event processing method was found just keep render params
response。setRenderParameters(request);
}

Events 传送复杂对象

JSR 286 规范允许 Portlet 作为事件有效负载发送和接收复杂Java 对象,前提是这些有
效负载是Java 和JAXB XML 可序列化的。这种许可允许跨类加载器甚至事件服务器传输复
杂对象,例如在与遵循Web Services for Remote Portlets (WSRP) 2.0 协议的远程 Portlet 通
信的时候。WebSphere Portal 6。1 支持WSRP 2.0,并允许本地和远程Portlet 之间的完全
互操作性和事件传播。

总结

正如我们从前面的讨论中看到的,可以将公共呈现参数视为对 Portlet 事件的较轻量级
的通信替代方法。下面的列表将各自的功能进行了对比,以帮助您决定哪一种机制更适合您

96

----------------------- Page 97-----------------------

Portlet 开发指南

的用例。
公共呈现参数具有以下特性:

 它们通常不需要显式的编码,而是只需在 Portlet.xml 部署描述符中进行声明。
 它们仅限于简单字符串值。
 它们不需要显式的管理来设置协作。
 它们不会随着共享信息的 Portlet 数量的增长而导致性能开销。
 它们通过 URL 更改进行更新,例如跳转到某个书签。
 可以在门户主题和皮肤中编码的链接中对它们进行设置。
 可以在使用特定于产品的API 创建的链接上对它们进行设置,这样的链接从一个
Portlet 指向不同页面上的另一个 Portlet。

Portlet 事件具有以下特性:

 需要显式的 Portlet 代码来发送和接收它们。
 它们可以包含复杂信息。
 它们允许通过在 Portlet 之间设置不同类型的连接(页面内或跨页面,公共或私有)
实现细粒度的控制。
 它们可以触发具有不同信息的级联更新。例如,Portlet A 可以将事件X 发送到
Portlet B,后者又将不同的事件Y 发送到 Portlet C。
 它们随着通信链接数量的增长而导致增加处理开销。
 它们必须由某个显式的用户交互(通常是通过单击 Portlet 中的某个操作链接)发
起,并且不能在第一次跳转到某个页面时将它们用于设置协作视图。

两种机制都允许您将数据交互与某个页面切换耦合在一起。对于事件,正如前面所解释
的,您可以定义页面切换跨页面连接。对于公共呈现参数,您可以在一个Portlet 中使用特
定于产品的API 生成指向不同页面上的另一个 Portlet 的链接,并为该目标设置公共呈现
参数。
当然,您甚至可以组合使用两种技术;例如,您可以在Portlet 中声明一个设置呈现参
数的处理事件,同时将此参数设置为公共参数,以便能够通过两种方式接收信息。
此讨论应该有助于您确定哪一种功能更适合给定的用例。根据一般经验,应该在可使用
公共呈现参数的场合使用公共呈现参数,并对呈现参数不足够的较复杂情况使用 Portlet 事
件。

97

----------------------- Page 98-----------------------

Portlet 开发指南

二十一、 Portlet Filter

Portlet 过滤器是JSR 286 提供的有一个非常重要的新特性。事实上,在JSR 286 之前,
就已经有很多厂商(包括 IBM)自定义扩展了JSR 168,提供了过滤器功能。由此可见,Portlet
过滤器的重要性。为了避免各种厂商不同 Portlet 过滤器的不兼容性,JCP (Java Community
Process)对JSR 286 定义了标准的过滤器实现。

什么是 Portlet filter

与Servlet 相似,Portlet 过滤器可以使用户改变一个 request 和修改一个 response。
Filter 不是一个 Portlet,它不能产生一个response,它能够在一个request 到达 Portlet 之
前预处理 request,也可以在离开Portlet 时处理response。换句话说,过滤器其实是一个
“Portlet chaining”(Portlet 链)。它能够实现的功能包括:

1. 在 Portlet 被调用之前截获;
2. 在 Portlet 被调用之前检查 servlet request;
3. 根据需要修改 request 头和 request 数据;
4. 根据需要修改 response 头和 response 数据;
5. 在 Portlet 被调用之后截获;

事实上,从宏观功能的角度看来,Portlet 过滤器和 Servlet 过滤器是很相似的。这是
因为二者都可以声明性地嵌入,从而截获并修改请求和响应。但是理解它们之间存在着很大
的不同是非常重要的。在一定程度上,它们之间的差异是与Servlet 和 Portlet 之间的差异
相联系的:Servlet 过滤器是一个门户级过滤器,它可以修改由一些小的部分(来自页面上
所有 Portlet 的响应)集合而成的整个门户页面;而Portlet 过滤器只能用于那些小的部分。
Servlet 过滤器(如果已经安装的话)是接收和修改客户端请求的第一个组件,同时也是修
改对客户端的响应的最后一个组件。
另外一点需要注意的是,Servlet 过滤器比 Portlet 过滤器的优先级别要高,容器将首
先进行Servlet 过滤,其次是 Portlet 过滤。一个过滤器链包含一个或多个过滤器。在一个
过滤器完成处理之后,新的请求和响应将传送到链上的下一个过滤器;链上的最后一个过滤
器调用目标资源(Servlet 或 Portlet)。

98

----------------------- Page 99-----------------------

Portlet 开发指南

主要概念

Portlet 过滤器可以放置在 V2.0 规范提供的任何生命周期方法调用的前面或者后面
(processAction、processEvent、render、serveResource ),而且还支持这些生命周期方法使
用包装的请求和响应。与Servlet 过滤器类似,Portlet 过滤器需要在 Portlet.xml 部署描述
符中进行定义,不同的是,servlet 只有一个service()的请求处理方法,因此servlet 只有一种
类型的过滤器。而Portlet 却有四种请求处理方法,于是有四种类型的过滤器,包括
1. Action 过滤器
2. Render 过滤器
3. Resource 过滤器
4. Event 过滤器
下面我们来介绍四种过滤器的工作原理。
JSR 286 为四种过滤器分别定义了一个接口类,这四个接口类都继承 PortletFilter 类,
并分别添加了各自doFilter() 方法。关于这几个类之间的关系,请见下图

四种过滤器分别对Portlet 的四个方法进行拦截。用户自定义的过滤器必须实现相应的
过滤器接口,通过其doFilter() 方法来实现相应的动作

99

----------------------- Page 100-----------------------

Portlet 开发指南

Filter 生命周期

JSR 286 为Portlet 过滤器提供了接口类 PortletFilter,该接口提供了两个方法。
1. void init(FilterConfig config)
容器调用一次这个方法来准备用于服务的过滤器。对象filterConfig 使得过滤器能够
访问配置参数以及对门户上下文的引用。
2. void destroy()

这个方法是在将过滤器从服务移除之后调用的。这个方法使得过滤器能够清除任何
存放的资源。
Filter 首先需要使用init 方法进行初始化,如果符合filter 的条件,Portlet 容器就会调用
相应filter 的doFilter 方法,doFilter 方法更加不同的拦截的方法会有不同的参数对象
 ActionRequest 和ActionResponse for processAction 调用
 EventRequest 和 EventResponse for processEvent调用
 RenderRequest 和 RenderResponse for render调用
 ResourceRequest 和 ResourceResponse for serveResource调用

Filter 环境

和servlet filter 一样,也可以在定义Portlet filter 的时候定义一些初始化参数,然后通过
FilterConfig 来获取

在Portlet Application 中配置Filters

可以Portlet.xml 中配置filter

<filter>
<filter-name>AllPortletFilter</filter-name>
<filter-class>com。Portalguide。filter。TestAllPhaseFilter</filter-class>
<lifecycle>ACTION_PHASE</lifecycle>
<lifecycle>EVENT_PHASE</lifecycle>
<lifecycle>RENDER_PHASE</lifecycle>
<lifecycle>RESOURCE_PHASE</lifecycle>
</filter>
<filter-mapping>
<filter-name>AllPortletFilter</filter-name>
<Portlet-name>PGFilterPortlet</Portlet-name>
</filter-mapping>

100

----------------------- Page 101-----------------------

Portlet 开发指南

总结

关于 Portlet 过滤器有几点需要声明的是:
 对于一个 Portlet 过滤器的声明亦包括两部分,过滤器的定义声明以及过滤器的映
射声明。
 一个 Portlet 过滤器可以为多个 Portlet 服务,而且 一个 Portlet 可以同时有多个
Portlet 过滤器。
 一个 Portlet 过滤器可以有多个生命周期阶段,当然前提是该 Portlet 过滤器实现
了相应过滤器接口。

101

----------------------- Page 102-----------------------

Portlet 开发指南

第五章节 可选概念

此章介绍一些可选的、非必须的概念,读者可以视情况选读,主要包括缓存、获取用户
信息、安全性。

102

----------------------- Page 103-----------------------

Portlet 开发指南

二十二、 缓存

缓存内容可以帮助减少Portal 的响应时间和application server 的压力。Portlet 规范定义
了一套基于过期的针对具体每个Portlet 的缓存机制。
如果当一个非action、event 请求,而这时恰好Portlet 容器还缓存着数据,那么Portlet
容器就不会调用,而是直接返回缓存的数据。如果是一个action、event 请求,则Portlet 容
器会删除目前此Portlet 的缓存,然后调用action、event 请求。

缓存过期

可以在Portlet.xml 中定义cache 的时间(秒)以及方式(private、public)。如下图中定
义的Portlet 缓存过期未300 秒,并且不能在不同用户之间共享。

<Portlet>

。。。
<expiration-cache>300</expiration-cache>

<cache-scope>private</cache-scope>

。。。
</Portlet>

Portlet 可以使用编程的方式修改缓存的时间和方式,方法是为 RenderResponse 或者
ResourceResponse 设置EXPIRATION_CACHE 和CACHE_SCOPE 属性。或者在MimeResponse
中调用getCacheControl 方法获取 CacheControl 对象,然后调用 CacheControl 对象的
setExpirationTime 和 setScope 方法。
Portlet 必须在输出内容之前设置缓存时间、方式,否则会被Portlet 容器忽略。
如果expiration-cache 是-1 则永不过期,如果是0 则代表立即过期,如果方式是private
的则缓存只能在同一个用户中共享,如果方式是public 的则缓存可以在不同用户中共享。
Private 方式是默认的方式。

验证缓存

作为缓存过期机制的扩展,Portlet 规范提供了验证缓存。验证缓存可以让Portlet 放回

一 些 标 记 。Portlet 可 以 通 过 CacheControl 在 RenderResponse 或者
ResourceResponse 中设置ETAG。下面是一个例子

protected void doView (RenderRequest request, RenderResponse response)

throws PortletException, java。io。IOException
{

103

----------------------- Page 104-----------------------

Portlet 开发指南

if ( request。getETag() != null ) { // validation request
if ( markupIsStillValid(request。getETag()) ) {
// markup is still valid

response。getCacheControl()。setExpirationTime(30);
response。getCacheControl()。setUseCachedContent(true);
return;
}
}
// create new content with new validation tag
response。getCacheControl()。setETag(someID);
response。getCacheControl()。setExpirationTime(60);
PortletRequestDispatcher rd =

getPortletContext()。getPortletRequestDispatcher(“jsp/view。jsp”);
rd。include(request, response);
}

总结

缓存内容可以帮助减少Portal 的响应时间和application server 的压力。Portlet 缓存使用
的一个典型场景是当Portal 页面中的Portlet 大部分只是做内容展现,而这些页面的访问量
还特别的大,这是就可以通过Portlet 缓存机制来提高性能。

104

----------------------- Page 105-----------------------

Portlet 开发指南

二十三、 用户信息

通常Portlet 可以提供个性化的内容,这是Portlet 一般需要获得登陆此Portal 的用户信
息,比如用户名、email 登陆。Portlet 容器提供了一套机制来使开发者获取这些用户信息。

定义用户属性

Portlet.xml 中可以定义用户的信息,如下面的代码

<Portlet-app>

<user-attribute>
<description>User Given Name</description>
<name>user。name。given</name>
</user-attribute>
<user-attribute>
<description>User Last Name</description>
<name>user。name。family</name>
</user-attribute>
<user-attribute>
<description>User eMail</description>
<name>user。home-info。online。email</name>
</user-attribute>
<user-attribute>
<description>Company Organization</description>
<name>user。business-info。postal。organization</name>
</user-attribute>

<Portlet-app>

Portlet 容器会按照Portlet.xml 中的定义来进行用户信息映射。

访问用户属性

开发者可以通过代码的方式获取用户信息,如下面代码

Map userInfo = (Map) request。getAttribute(PortletRequest。USER_INFO);
String givenName = (userInfo!=null) ? (String)

userInfo。get(PortletRequest。P3PUserInfos。USER_NAME_GIVEN) : “”;
String lastName = (userInfo!=null)(String)
userInfo。get(PortletRequest。P3PUserInfos。USER_NAME_FAMILY) : “”;

105

----------------------- Page 106-----------------------

Portlet 开发指南

重要注意事项

Portlet 规范之前并没有java 中并没有定义标准的用户信息的获取方式,在Portlet 规范
中定义Portlet 中定义了用户信息的访问。如果java 标准中定义了获取用户信息的方法,
Portlet 规范中的获取机制就没有必要存在,使用标准的就可以了。

总结

Portlet 中定义了一些获取用户信息的方式。

106

----------------------- Page 107-----------------------

Portlet 开发指南

二十四、 安全性

介绍

和servlet 一样,也可以在Portlet application 中定义安全性。

角色

Portlet 规范中定义的角色与servlet 规范中的一致。

安全性代码开发

可以通过如下几个方法获取安全性用户信息
 getRemoteUser

 isUserInRole

 getUserPrincipal

可以在Portlet.xml 中定义用户和角色的映射关系

<Portlet-app>
。。。
<Portlet>
。。。
<security-role-ref>
<role-name>FOO</role-name>
<role-link>manager</role-link>
</security-role-ref>
</Portlet>
。。。
。。。
</Portlet-app>

总结

107

----------------------- Page 108-----------------------

Portlet 开发指南

二十五、 Portal Context

PortalContext 接口提供了 Portal application 的各种信息,可以通过 Portlet 的
getPortalContext 方法来获取PortalContext 对象。
PortalContext 对象可以通过getPortalInfo 方法获得Portal 的制造商、版本等信息基本信
息,通过 getProperty 和 getPropertyNames 获得 Portal 的属性信息,通过
getSupportedPortletModes 获得Portal 支持的Portlet mode,通过getSupportedWindowStates
获得Portal 支持的windowstate 。

108

----------------------- Page 109-----------------------

Portlet 开发指南

二十六、 Portlet 容器运行时

Portlet 可以在Portlet.xml 中定义Portlet application 级别和具体某个Portlet 级别的运行
时选项。Portlet application 级别的运行时选项对所有Portlet 都有效,具体某个Portlet 级别
的运行时参数只对所定义的Portlet 有效,并且可以覆盖Portlet application 级别的运行时选
项。
可以通过PortletContext 接口的getContainerRuntimeOptions 方法来获取运行时参数

Enumeration containerRuntime =
this.getPortletContext().getContainerRuntimeOptions();
while (containerRuntime.hasMoreElements()) {
log.info(containerRuntime.nextElement().toString());

}

一般情况来说这些运行时参数是为了版本兼容性、container 的个性化设置,但是这些
个性化的设置一般是不为推荐的。所有一般情况不需要设置。
WebSphere Portal V6.1 支持以下容器运行时选项:
 Javax.Portlet.escapeXml (由JSR 286 定义),用于避免JSP 标记生成的 URL 的缺省
XML 转义。
 Javax.Portlet.actionScopedRequestAttributes (由JSR 286 定义),用于跨请求边界保
留Portlet 请求属性。
 Com.ibm.Portal.public.session (特定于产品),用于指示某个Portlet 需要会话才能正
确操作。它请求门户在每当包含该 Portlet 的页面被访问时,即使不存在任何用户
登录,也要创建会话 Cookie。
有些代码不是非常适合 Portlet 规范的概念,但是仍然应该在 WebSphere Portal 中受
到支持,上述所有这些运行时选项就表示此类代码的变通办法。在频繁使用的门户上,使用
后两个运行时选项还会导致性能下降。因此,应该尽量避免使用这些运行时选项,并且最好
以使得这些选项变得不必要的方式编写代码。

动态修改Portlet 标题

读者会发现我在示例2 中定义的CONFIG_TITLE 这个变量始终没有用到,其实是为了实
现Portlet 标题栏文字的自设定而放置的。
WebSphere Portal6 中Portlet 标题栏文字的修改比较怪异,本来按照JSR168 中所规定的,只
要使用 RenderResponse.setTitle(String title)函数就可以设置标题了,而且我用这个方法在
pluto-1.1.4 中测试通过,但在WebSphere Portal 中却怎么调都不行,看了IBM 网站上的一篇
文章《Tip: Changing a Portlet title at run time in WebSphere Portal V6》才有点明白,似乎是IBM
为了访问效率考虑,所以在WebSphere Portal 中调用RenderResponse.setTitle 只是修改了
com.ibm.Portal.Portlet.Constants.DYNAMIC_TITLE 这个值,然后还需要在皮肤中使用DOM,并
读取该值才能显示。

109

----------------------- Page 110-----------------------

Portlet 开发指南

下面是实现步骤。在示例2 的代码中进行修改实现。
(1)修改皮肤。
复制IBM 皮肤文件夹,重命名为IBM_DT,修改其中的control.jsp。
找到其中如下一段代码
<Portal-skin:PortletTitle>
<Portal-fmt:problem bundle="nls.problem"/>
</Portal-skin:PortletTitle>

为其添加span 或者div 标签,用于修改时的定位,修改为
<span id="title.<Portal-skin:PortletID/>">
<Portal-skin:PortletTitle>
<Portal-fmt:problem bundle="nls.problem"/>
</Portal-skin:PortletTitle>
</span>

然后在control.jsp 文件的最下方,添加如下代码用于修改标题栏文字。
<script type="text/javascript">
var dynamicTitle
="<%=request.getAttribute(com.ibm.Portal.Portlet.Constants.DYNAMIC_TITLE)%>";
var titleElement = document.getElementById("title.<Portal-skin:PortletID/>");
if (titleElement != null) {
if (dynamicTitle != "" && dynamicTitle != "null")
titleElement.innerHTML = dynamicTitle;
}
</script>
如此,皮肤就修改完成了。
(2)修改PortletExamplePortletView.jsp,在其中添加一行代码。
renderResponse.setTitle(prefs.getValue(PortletExamplePortlet.CONFIG_TITLE, "ConfigTitle"));

(3)转入Portal 中查看显示效果。
安装该皮肤,并且设置要修改标题的Portlet 都要使用该皮肤。
为了演示此种方式可以同时在一个页面中给多个Portlet 设置不同的标题文字,我们可以再
复制一个PortletExample Portlet,命名为PortletExample2,然后将其也添加到测试页面上。
然后给这两个Portlet 配置不同的参数,如下图,可以看到,两个Portlet 的标题是不同的,
显示内容、高度等也都不同。

这种方式修改的只是View 视图时的标题,如果我们进入配置模式,会发现标题栏还是原来
的名字。

RenderResponse.setTitle(String title)函数也可以在PortletExamplePortlet.java 中的doView、
doEdit 等函数中调用,显示结果与直接在jsp 中调用相同,留待读者自己尝试

110

----------------------- Page 111-----------------------

Portlet 开发指南

二十七、 使用注释的方法

GenericPortlet Render Handling

可以通过@RenderMode 这种方式来定义与view、edit、help mode 对应的方法,但是笔
者觉得没有什么必要,用默认的方法名称就成了。

111

----------------------- Page 112-----------------------

Portlet 开发指南

二十八、 Setting next possible Portlet Modes

112

----------------------- Page 113-----------------------

Portlet 开发指南

二十九、 Struts2 开发Portlet 实例

我们在开发Servlet 应用时,习惯于将数据存放在 request 作用域中,通过页面的跳转
将数据呈现到jsp 视图页面。但是,这种做法在 Portlet 开发中是不可行的。与servlet 的
生命周期有所不同,Portlet 存在操作响应阶段和呈现阶段。 在 Portlet 操作响应阶段存放
在 request 作用域的变量,在呈现阶段就会失效。在原有API 上解决这个问题既费时又不
优雅,而 Struts 2 对 Portlet 的支持将能够很好的解决这些问题。

113

----------------------- Page 114-----------------------

Portlet 开发指南

三十、 Spring mvc 开发Portlet 实例

Portlet 与Servlet 生命周期最主要的区别在于Portlet 的请求分为两个明显的阶段:行
动阶段和呈现阶段。行动阶段只执行一次是由于“后台”有改变或者行动发生,例如修改数
据库操作。呈现阶段是每次显示被刷新,然后产生显示结果给用户。这里的关键点是在单个
全生命周期的请求,行动阶段只被执行一次,但是呈现阶段可能执行多次。这样就使修改您
系统的持久状态的活动和产生显示给用户的活动有一个清晰的分离。
Portlet 两个阶段是JSR-168 规范的一个功能强大的特性。例如,动态搜索显示结果可以
在显示修改而不需要用户重新运行搜索功能。很多其它的Portlet mvc 框架努力对开发人员
隐蔽两个阶段使Portlet 的开发尽可能像开发传统的servlet 应用那样-我们认为这种方式减少
使用Portlet 的一个重要好处。所以Spring 的Portlet mvc 框架是始终保留两个分离的阶段。
这种方式的主要的表现是servlet mvc 的版本的类有一个方法处理请求,Portlet mvc 版
本的类有两个方法处理请求:一个是行动阶段和一个呈现阶段。例如,servlet 版本的
AbstractController 有一个handleRequestInternal(。。)方法;Portlet 版本的AbstractController
有handleActionRequestInternal(。。)和handleRenderRequestInternal(。。)方法。

114

----------------------- Page 115-----------------------

Portlet 开发指南

三十一、 附录

修改记录

版本号 修改日期 描述

0.1 2010/12/12 正式开始编写

0.2 2010/12/22 草稿第一次完成

0.3 2010/12/29 整理文档总体结构、分为五章,完善了部分章节(缓存、用
户信息、安全性、Portlets 协作、Portlet Filter)内容

0.31 2010/12/30 完善资源管理章节

0.32 2010/12/31 完善部署章节

0.33 2011/01/03 完善session、Portlet context、Portlet config、Portlet 生命周期
接口章节

0.34 2011/01/04 完善request、response 章节

0.4 2011/01/07 草稿第一次完善完毕、附带代码完成

名词解释

名词 解释
Portlet 一个Portlet 是一个基于java 技术的被Portlet 容器管理的web 组建,它可
以处理requests、生成动态的内容输出,一个Portlet 负责提供Portal 页
面中的某个特定部位的展现内容
Portal Portal 是一个基于web 的提供个性化、登录授权、从不同的数据源聚集内

容基于展现层的信息系统。

Portlet 容器 Portlet 容器提供Portlet 生命周期环境,管理Portlet 的生命周期,还提供
Portlet preferences 的持久化支持,Portlet 从Portal 接受请求,然后分发给
运行其上的Portlet。

fragment 指Portlet 生成的内容片断

aggregate 指Portal 把Portlet 生成的组合在一起集中展现

Portlet window Portlet 窗口

Portlet Entity Portlet 实体

preferences 首选项

Web application Web 应用

Portlet Portlet 应用
application

115

----------------------- Page 116-----------------------

Portlet 开发指南

Resource service 资源服务

Public render 共享呈现参数
parameter

Event Portlet 事件

Portlet filter Portlet 拦截器

Tag 标签,可以在Portlet 的jsp 里面使用的标签。

疑问

标签库
1 怎么在action、event 中include jsp

116

分享到:
评论

相关推荐

    portlet开发指南

    portlet 开发指南 开发指南 中文

    IBM portlet开发指南

    Portlet开发指南............................................................................................................................... 1 第一章节 入门介绍 ........................................

    Portlet开发指南

    详细介绍了Portlet的开发过程,转载。

    portlet开发资料.rar

    portlet资料 portlet开发指南 portlet开发手册

    金蝶BOS企业版V632_开发指南_管理门户_Portlet开发.doc

    金蝶BOS企业版V632_开发指南_管理门户_Portlet开发.doc

    JSR286 portlet开发标准

    文章专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学习完本系列后,您将了解相对于 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增强功能, 以及这些...

    JSR-168 Portlet指南.doc

    JSR-168是适合于portlet开发人员的Java API集合。设计符合规范的JSR-168 portlet的原因有很多。可移植性就一个显而易见的好处。根据规范编写的代码更容易在门户服务器之间移动。多数基于Java的门户服务器都支持JSR-...

    金蝶eas__二次开发Portlet (BOS开发指南)

    金蝶eas__二次开发Portlet

    portlet-guide:用华丽的方式开发 MyUW portlet 的指南

    用华丽的方式开发 MyUW portlet 的指南。 公共回购,但毫无歉意地专注于 my.wisc.edu 小心! 这是一个公共回购。 促进透明度和与同行 portlet 开发机构的协作是公开的。 但是,本指南毫无歉意地以 MyUW 为重点。 ...

    JSR286 portlet新特性

    文章专门针对具有 JSR 168 Portlet 开发基础,并且想了解 JSR 286 Portlet 新特性和开发流程的开发人员。在学习完本系列后,您将了解相对于 JSR 168 Portlet,JSR 286 Portlet 究竟提供了哪些增强功能, 以及这些...

    BOS V6.2开发指南_Web开发平台

    2 开发过程 4 2 1 概述 4 2 2 环境准备 4 2 2 1 开发工具 4 2 2 2 JDK约束 4 2 3 开发规约 4 2 4 序时簿开发 5 2 4 1 序时簿界面开发过程 5 2 4 2 通用过滤实现 14 2 4 3 框架内置服务 16 2 5 编辑界面开发 17 2 5 1...

    Liferay入门帮助文档(Liferay开发指南)

    Liferay 是一个完整的门户解决方案,基于J2EE的应用,使用了EJB以及JMS等技术,前台界面部分使用Struts MVC 框架,基于XML的portlet配置文件可以自由地动态扩展,使用了Web服务来支持一些远程信息的获取,使用 ...

    liferay 6.0 开发指南

    liferay 6.0 开发指南 liferay-developer-guide-6.0.pdf

    liferay 二次开发指南

    liferay 二次开发指南,非常详尽,不容错过

    Portlet-Specification(2).rar_portlet

    JAVA Portal开发指南,详细讲解门户开发的框架和技术

    Liferay+Portal+二次开发指南_java_

    Liferay Portal 二次开发指南 pdf格式,本文从Liferay Portal的架构入手,详细讲解Portal的用户策略、内容布局、桌面和品质的要素,引导读者完成Liferay Portal初步的二次开发,在Liferay Portal上定制自己的Portlet...

    LiferayPortal二次开发指南破解版.pdf

    随着信息化建设的深入,Portal 门户已经成为新型办公环境的一...的要素,引导读者完成Liferay Portal 初步的二次开发,在Liferay Portal 上定制自己的Portlet。 Liferay Portal 程序框架和源码分析不在本文的讨论范围。

    LiferayPortal二次开发指南

    LiferayPortal二次开发指南(read)是比较实用的技术文档 ,适合于初学者阅读,详细介绍了基础知识

    Struts2权威指南完整版

    改为使用Convention插件提供“零配置”,Struts 2.1新增了Portlet支持……为了让众多Struts学习者、工作者快速从Struts 2.0的开发升级到Struts 2.1,笔者升级了《Struts 2权威指南》,第二版改写了第一版中所有程序...

Global site tag (gtag.js) - Google Analytics