1、Portlet Request & URL
在一个 Portal 页面中,通常都包含了多个 Portlet ,在一个时刻用户只能与一个 Portlet 交互,当用户向一个 Portlet 发出请求(例如点击了“ submit ”按钮),整个 Portlet 页面将会重新构成。在这个过程中,是否有与用户交互的 Portlet 处理方式显然是不同的,而且用户没有与之交互的 Portlet 显然不应该接收到用户的请求参数。
因此 JSR168 规范中将对 Portlet 的请求分为 Action 和 Render 两种。 Portlet 在收到 Action 请求,获取用户所提交的信息,进行相应的处理;受到 Render 请求后,则生成页面代码。当用户向一个 Portlet 发出请求,该请求被 Portlet 容器接受, Portlet 容器再调用相应 Portlet 的 processAction() 方法;等到 processAction() 方法执行完毕后, Portlet 容器再调用所有 Portlet 的 render() 方法,并将这些方法所返回的内容组合形成一个页面返回给客户端。在上述过程中,所有 Portlet 的 render() 方法的调用次序在规范中没有规定,既可能是有顺序的串行调用,也可能是多线程的同步调用,依赖于厂商的具体实现。
为了接受用户请求,一个 Portlet 需要有一个指向其自身的 URL ,例如用在 HTTP FORM 的 ACTION 字段。但是与 Servlet 不同的是, Portlet 不是一个完整的页面而只是页面的一部分,一个 Portlet 可以出现在多个页面中,所以 Portlet 无法绑定具体的 URL 。在 JSR168 规范中定义了 PortletURL 接口,通过该接口可以得到指向 Portlet 自身的 URL ,对应两种用户请求有两种产生 URL 的方法: q?4k2@*v_rk*l
一、for render():
PortletURL url = response.createRenderURL(); www.portalfan.com&S A(`L v(s
url.setParameter(“customer”,”foo.com”);
url.setParameter(“show”,”summary”); !g{f#vk^
writer.print(“<A HREF=\””+url.toString()+”\”>Summary</A>”);
4x_kUS/^![
二、for processAction():
`kTi3O
PortletURL url = response.createActionURL();
url.setParameter(“paymentMethod”,”creditCardInProfile”);
url.setWindowState(WindowState.MAXIMIZED); www.portalfan.com1x"p VfH
writer.print(“<FORM METHOD=\”POST\” ACTION=\””+ url.toString()+”\”>”);
(r/aI iI(v/i
上面的代码我们可以看到,除了得到 URL 外,还可以在其中加入参数。另外由于 Portal 服务器厂商通常都会利用 URL 增加一些产品相关的参数,因此强烈建议在 Portlet 中提交用户请求采用 POST 方式。
2、 Portlet Modes & Window States
在 Portal 应用中,用户通常需要设置、调整 Portlet 的显示方式,对此 JSR168 同样做出了规定。分别有 Portlet Modes 和 Window States 。
Portlet Modes 说明 Portlet 目前所执行的功能模式,规范要求 Portal 服务器必须支持以下三种模式: www.portalfan.com\ k6k7cWk
)e-[_lj rq&sI
q
VIEW ——内容显示,通常为缺省模式
EDIT ——编辑相关的设置
HELP ——显示帮助信息
除此之外可以Portal服务器可以实现自定义的模式。portal爱好者0XLqXP5iv J
每个 Portlet 在 Portal 页面中就是一个“窗口”,类似于 MS Windows 、 XWindo 等窗口系统 Portlet 也有自己的窗口状态( Window States ),规范要求 Portal 服务器必须支持以下三种窗口状态 :
NORMAL ——普通 portlet 窗口,在这个状态下通常是与其它 Portlet 共享 Portal 页面; portal爱好者t8u/O/F;F
MAXIMIZED ——最大化 portlet 窗口,独占 Portal 页面;
J&?'X$az9u_eJ
MINMIZED ——最小化 portlet 窗口 #la|M@!YP?2N g
除此之外可以Portal服务器可以实现自定义的窗口状态
在规范中对这些特性进行定义,使得 Portlet 开发者无需关心这方面实现细节,另外在 processAction() 和 render() 方法中开发者都可以通过 getPortletMode() 和 getWindowState() 等方法获得当前 Portlet 的情况从而决定相关操作。
3、Preferences & User Information say?d
Portal 应用一个重要功能就是“个性化”,一方面 Portal 服务器需要根据用户的不同显示不同的 Portlet ,另一方面同一个 Portlet 也会根据用户的偏好显示不同的内容。这就要求 Portlet 需要保存一些用户的相关信息,例如一个股票实时信息的 Portlet 会根据用户所关注的股票显示相应的信息。
每个 Portlet 都可能有自己相应的个性化信息, JSR168 规范提供了 PortletPreferences 接口来操纵这些信息。
PortletPreferences 接口提供读取、设置属性的方法,如下:
PortletPreferences prefs = req.getPreferences();
String[] symbols = prefs.getValues(”preferredStockSymbols”, l&Fnew String[]{”ACME”,”FOO”}); www.portalfan.com*J4WF2WI qg
#f_,[$j({6M
在 JSR168 规范中 PortletPreferences 是用户相关的,也就是通过 getPreferences() 获得的对象是与当前登录用户绑定的, PortletPreferences 不会在用户之间共享属性。 lg4a {^a2zb q ]
PortletPreferences 提供了一个基本的读取、设置个性化属性的途径,使得 Portlet 无需依赖具体的数据储存环境(例如数据库联接、表结构等等)就可以实现个性化并能够在不同的 Portal 服务器之间移植。但是不应该使用 PortletPreferences 来替代一般的数据库功能。
在实现个性化功能中经常需要获取各种用户信息,例如用户姓名、地址等等。因此 JSR168 也提供了一个获取用户信息的途径,如下:SK2B7KK
~}
n%R3I
Map userInfo = (Map) request.getAttribute(PortletRequest.USER_INFO);
String givenName = (userInfo!=null) ? (String) userInfo.get(“user.name.given”) : “”;
String lastName = (userInfo!=null) ? (String) userInfo.get(“user.name.family”) : “”;
所获得的 Map 对象是一个只读对象,不能更改。但是用户信息应该包含什么内容不在 JSR168 规范的范围,事实上目前还没有关于访问用户信息的 Java 标准, JSR168 提到在以后形成访问用户信息的 Java 标准时,当前的机制就会被取代。
4、Sessions K5u{g|)Q
w
portal爱好者SS"uu+~`
作为一个 Web 应用组件, Portlet 同样有 Session 这个机制用于跟踪用户操作,而与一般的 Web 应用所不同的是 Portlet 的 Session 属性有两种作用域:fi
PORTLET_SCOPE:属性只能被设置它的Portlet访问
APPLICATION_SCOPE:属性可以被同一个Portal应用中的所有Portlet访问 4VgU\;F
PortletSession session = request.getSession(true);
URL url = new URL(“http://www.foo.com”);
session.setAttribute(“home.url”,url,PortletSession.APPLICATION_SCOPE);
session.setAttribute(“bkg.color”,”RED”,PortletSession.PORTLET_SCOPE);
5、Request Dispatch & Portlet Tag
在实现 Portlet 应用时,开发者往往会利用 Servlet 、 JSP 等资源,起码会有两个目的会这样做: 为了利用现有的资源,简单地将已经写好的 Servlet 、 JSP 应用转换成 Portlet ; 方便 Portlet 的表现层开发。 Portlet 规范类似于 Servlet 规范,在表现层开发上远远不如 JSP ,因此需要利用 JSP 来开发界面。JSR168 提供了类似 Servlet RequestDispatcher 的接口来实现利用 Servlet 、 JSP 等资源的功能。
例子如下: portal爱好者.c
oJ#m|7SJ,M2vh
String path = "/raisons.jsp?orderno=5"; portal爱好者'J0q|lh:Vu&[']
PortletRequestDispatcher rd = context.getRequestDispatcher(path); rd.include(renderRequest, renderResponse);
当一个 JSP 页面需要作为 Portlet 应用的一部分, JSP 开发者需要获得相关的 Portlet 信息,为此 JSR168 提供了相应的 JSP Tag 来实现相关的功能。通过相应的 Portlet Tag , JSP 开发者可以获得相应的 Portlet Request/Response 对象,产生 ActionURL 或者 RenderURL 等等。
5、缓存qB&gWN(N_
www.portalfan.com/yza"x1g-PB1C
在前面中我们知道,用户每次向Portal 应用发送一个请求,该页面中所有的 Portlet 都会被 Portlet 容器调用 render() 方法来产生相应内容。但是只有一个 Portlet 才会处理用户请求,其它不处理用户请求的 Portlet 可能每次的显示内容都是不变的。
因此 JSR168 定义了缓存机制来提供 Portal 应用的效率。在 portlet.xml 中可以定义缓存的失效时间,如下:
portal爱好者)y2C$\7m.E
<portlet> R`Xh M5co i
...
<expiration-cache>300</expiration-cache>
...
</portlet>
这样 Portlet 容器在调用 Portlet 的 render() 方法之前就会检查有缓存是否已经有效,如果有效的话就直接使用缓存内容。 Portlet 缓存是跟客户端相关的,不同的客户端访问同一个 Portlet 分别有自己的缓存而不会混淆。JSR168 对缓存机制的实现不是强制性的, Portal 服务器厂商可以自行决定是否实现这个特性。
6、CSS Style Definition
在一个 Portlet 应用中,所有 Portlet 应该具有显示上的一致性,例如使用相同的字体等等。为了到达这一点, JSR168 定义了一套 CSS 元素名称, Portlet 开发者都应该采用这套 CSS 来产生显示内容。这套 CSS 定义主要包含了 Fonts 、 Message (例如告警、通知等等)、 Sections 、 Forms 。
7、Portlet VS Servlet
Portlet 和 Servlet 是十分类似的,只是由于 Servlet 无法达到 Portal 应用的要求 JCP 才定义了新的 Portlet 规范,为了尽可能与现有的 Servlet 结合达到重复使用的目的, portlet 的规范利用了 Servlet 的规范,许多观念都很相似的。在讲述了 Portlet 的特性后,我们再来看看他们直接的异同。相似之处:]3b AC|Z2g
Portlet 也是 Java 技术的 web 组件 z&MBh[] T6sEy
Portlet 也是有特定的 container 在管理
Portlet 可以动态产生各种内容 &X3Z$r0]W9J)_
Portlet 的生命周期由 container 所管理 bf;YKx
Portlet 和客户端的互动是通过 request/response 的机制wZ
不同之处: portal爱好者 D(e9g$MA2W{L
Portlet 只产生 markup 信息片段,不是完整的网页文件
Portlet 不会和 URL 有直接的关系
客户端必须通过 Portal 系统才能和 Portlet 互动
Portlet 有一些定义好的 request 处理, action request 以及 render request
Portlet 默认定义 portlet modes 及窗口状态
Portlet 可以在同一个 portal 网页之中存在多个
Portlet有的功能而Servlet没有:
Portlet 能够存取及储存永久配置文件及定制资料
Portlet 可以存取使用者数据
Portlet 具有 URL 的重写功能够在它的内容中动态建立连结
Portlet Session 的属性拥有两个不同的范围: application-scope 及 portlet-scope
Portlet不具备而Servlet提供的功能
Servlet 具有设置输出的文字编码 ( character set encoding) 方式
Servlet 可以设置 HTTP 输出的 header
Servlet 才能够接收客户对 portal 发出的 URL 请求
在一个 Portal 页面中,通常都包含了多个 Portlet ,在一个时刻用户只能与一个 Portlet 交互,当用户向一个 Portlet 发出请求(例如点击了“ submit ”按钮),整个 Portlet 页面将会重新构成。在这个过程中,是否有与用户交互的 Portlet 处理方式显然是不同的,而且用户没有与之交互的 Portlet 显然不应该接收到用户的请求参数。
因此 JSR168 规范中将对 Portlet 的请求分为 Action 和 Render 两种。 Portlet 在收到 Action 请求,获取用户所提交的信息,进行相应的处理;受到 Render 请求后,则生成页面代码。当用户向一个 Portlet 发出请求,该请求被 Portlet 容器接受, Portlet 容器再调用相应 Portlet 的 processAction() 方法;等到 processAction() 方法执行完毕后, Portlet 容器再调用所有 Portlet 的 render() 方法,并将这些方法所返回的内容组合形成一个页面返回给客户端。在上述过程中,所有 Portlet 的 render() 方法的调用次序在规范中没有规定,既可能是有顺序的串行调用,也可能是多线程的同步调用,依赖于厂商的具体实现。
为了接受用户请求,一个 Portlet 需要有一个指向其自身的 URL ,例如用在 HTTP FORM 的 ACTION 字段。但是与 Servlet 不同的是, Portlet 不是一个完整的页面而只是页面的一部分,一个 Portlet 可以出现在多个页面中,所以 Portlet 无法绑定具体的 URL 。在 JSR168 规范中定义了 PortletURL 接口,通过该接口可以得到指向 Portlet 自身的 URL ,对应两种用户请求有两种产生 URL 的方法: q?4k2@*v_rk*l
一、for render():
PortletURL url = response.createRenderURL(); www.portalfan.com&S A(`L v(s
url.setParameter(“customer”,”foo.com”);
url.setParameter(“show”,”summary”); !g{f#vk^
writer.print(“<A HREF=\””+url.toString()+”\”>Summary</A>”);
4x_kUS/^![
二、for processAction():
`kTi3O
PortletURL url = response.createActionURL();
url.setParameter(“paymentMethod”,”creditCardInProfile”);
url.setWindowState(WindowState.MAXIMIZED); www.portalfan.com1x"p VfH
writer.print(“<FORM METHOD=\”POST\” ACTION=\””+ url.toString()+”\”>”);
(r/aI iI(v/i
上面的代码我们可以看到,除了得到 URL 外,还可以在其中加入参数。另外由于 Portal 服务器厂商通常都会利用 URL 增加一些产品相关的参数,因此强烈建议在 Portlet 中提交用户请求采用 POST 方式。
2、 Portlet Modes & Window States
在 Portal 应用中,用户通常需要设置、调整 Portlet 的显示方式,对此 JSR168 同样做出了规定。分别有 Portlet Modes 和 Window States 。
Portlet Modes 说明 Portlet 目前所执行的功能模式,规范要求 Portal 服务器必须支持以下三种模式: www.portalfan.com\ k6k7cWk
)e-[_lj rq&sI
q
VIEW ——内容显示,通常为缺省模式
EDIT ——编辑相关的设置
HELP ——显示帮助信息
除此之外可以Portal服务器可以实现自定义的模式。portal爱好者0XLqXP5iv J
每个 Portlet 在 Portal 页面中就是一个“窗口”,类似于 MS Windows 、 XWindo 等窗口系统 Portlet 也有自己的窗口状态( Window States ),规范要求 Portal 服务器必须支持以下三种窗口状态 :
NORMAL ——普通 portlet 窗口,在这个状态下通常是与其它 Portlet 共享 Portal 页面; portal爱好者t8u/O/F;F
MAXIMIZED ——最大化 portlet 窗口,独占 Portal 页面;
J&?'X$az9u_eJ
MINMIZED ——最小化 portlet 窗口 #la|M@!YP?2N g
除此之外可以Portal服务器可以实现自定义的窗口状态
在规范中对这些特性进行定义,使得 Portlet 开发者无需关心这方面实现细节,另外在 processAction() 和 render() 方法中开发者都可以通过 getPortletMode() 和 getWindowState() 等方法获得当前 Portlet 的情况从而决定相关操作。
3、Preferences & User Information say?d
Portal 应用一个重要功能就是“个性化”,一方面 Portal 服务器需要根据用户的不同显示不同的 Portlet ,另一方面同一个 Portlet 也会根据用户的偏好显示不同的内容。这就要求 Portlet 需要保存一些用户的相关信息,例如一个股票实时信息的 Portlet 会根据用户所关注的股票显示相应的信息。
每个 Portlet 都可能有自己相应的个性化信息, JSR168 规范提供了 PortletPreferences 接口来操纵这些信息。
PortletPreferences 接口提供读取、设置属性的方法,如下:
PortletPreferences prefs = req.getPreferences();
String[] symbols = prefs.getValues(”preferredStockSymbols”, l&Fnew String[]{”ACME”,”FOO”}); www.portalfan.com*J4WF2WI qg
#f_,[$j({6M
在 JSR168 规范中 PortletPreferences 是用户相关的,也就是通过 getPreferences() 获得的对象是与当前登录用户绑定的, PortletPreferences 不会在用户之间共享属性。 lg4a {^a2zb q ]
PortletPreferences 提供了一个基本的读取、设置个性化属性的途径,使得 Portlet 无需依赖具体的数据储存环境(例如数据库联接、表结构等等)就可以实现个性化并能够在不同的 Portal 服务器之间移植。但是不应该使用 PortletPreferences 来替代一般的数据库功能。
在实现个性化功能中经常需要获取各种用户信息,例如用户姓名、地址等等。因此 JSR168 也提供了一个获取用户信息的途径,如下:SK2B7KK
~}
n%R3I
Map userInfo = (Map) request.getAttribute(PortletRequest.USER_INFO);
String givenName = (userInfo!=null) ? (String) userInfo.get(“user.name.given”) : “”;
String lastName = (userInfo!=null) ? (String) userInfo.get(“user.name.family”) : “”;
所获得的 Map 对象是一个只读对象,不能更改。但是用户信息应该包含什么内容不在 JSR168 规范的范围,事实上目前还没有关于访问用户信息的 Java 标准, JSR168 提到在以后形成访问用户信息的 Java 标准时,当前的机制就会被取代。
4、Sessions K5u{g|)Q
w
portal爱好者SS"uu+~`
作为一个 Web 应用组件, Portlet 同样有 Session 这个机制用于跟踪用户操作,而与一般的 Web 应用所不同的是 Portlet 的 Session 属性有两种作用域:fi
PORTLET_SCOPE:属性只能被设置它的Portlet访问
APPLICATION_SCOPE:属性可以被同一个Portal应用中的所有Portlet访问 4VgU\;F
PortletSession session = request.getSession(true);
URL url = new URL(“http://www.foo.com”);
session.setAttribute(“home.url”,url,PortletSession.APPLICATION_SCOPE);
session.setAttribute(“bkg.color”,”RED”,PortletSession.PORTLET_SCOPE);
5、Request Dispatch & Portlet Tag
在实现 Portlet 应用时,开发者往往会利用 Servlet 、 JSP 等资源,起码会有两个目的会这样做: 为了利用现有的资源,简单地将已经写好的 Servlet 、 JSP 应用转换成 Portlet ; 方便 Portlet 的表现层开发。 Portlet 规范类似于 Servlet 规范,在表现层开发上远远不如 JSP ,因此需要利用 JSP 来开发界面。JSR168 提供了类似 Servlet RequestDispatcher 的接口来实现利用 Servlet 、 JSP 等资源的功能。
例子如下: portal爱好者.c
oJ#m|7SJ,M2vh
String path = "/raisons.jsp?orderno=5"; portal爱好者'J0q|lh:Vu&[']
PortletRequestDispatcher rd = context.getRequestDispatcher(path); rd.include(renderRequest, renderResponse);
当一个 JSP 页面需要作为 Portlet 应用的一部分, JSP 开发者需要获得相关的 Portlet 信息,为此 JSR168 提供了相应的 JSP Tag 来实现相关的功能。通过相应的 Portlet Tag , JSP 开发者可以获得相应的 Portlet Request/Response 对象,产生 ActionURL 或者 RenderURL 等等。
5、缓存qB&gWN(N_
www.portalfan.com/yza"x1g-PB1C
在前面中我们知道,用户每次向Portal 应用发送一个请求,该页面中所有的 Portlet 都会被 Portlet 容器调用 render() 方法来产生相应内容。但是只有一个 Portlet 才会处理用户请求,其它不处理用户请求的 Portlet 可能每次的显示内容都是不变的。
因此 JSR168 定义了缓存机制来提供 Portal 应用的效率。在 portlet.xml 中可以定义缓存的失效时间,如下:
portal爱好者)y2C$\7m.E
<portlet> R`Xh M5co i
...
<expiration-cache>300</expiration-cache>
...
</portlet>
这样 Portlet 容器在调用 Portlet 的 render() 方法之前就会检查有缓存是否已经有效,如果有效的话就直接使用缓存内容。 Portlet 缓存是跟客户端相关的,不同的客户端访问同一个 Portlet 分别有自己的缓存而不会混淆。JSR168 对缓存机制的实现不是强制性的, Portal 服务器厂商可以自行决定是否实现这个特性。
6、CSS Style Definition
在一个 Portlet 应用中,所有 Portlet 应该具有显示上的一致性,例如使用相同的字体等等。为了到达这一点, JSR168 定义了一套 CSS 元素名称, Portlet 开发者都应该采用这套 CSS 来产生显示内容。这套 CSS 定义主要包含了 Fonts 、 Message (例如告警、通知等等)、 Sections 、 Forms 。
7、Portlet VS Servlet
Portlet 和 Servlet 是十分类似的,只是由于 Servlet 无法达到 Portal 应用的要求 JCP 才定义了新的 Portlet 规范,为了尽可能与现有的 Servlet 结合达到重复使用的目的, portlet 的规范利用了 Servlet 的规范,许多观念都很相似的。在讲述了 Portlet 的特性后,我们再来看看他们直接的异同。相似之处:]3b AC|Z2g
Portlet 也是 Java 技术的 web 组件 z&MBh[] T6sEy
Portlet 也是有特定的 container 在管理
Portlet 可以动态产生各种内容 &X3Z$r0]W9J)_
Portlet 的生命周期由 container 所管理 bf;YKx
Portlet 和客户端的互动是通过 request/response 的机制wZ
不同之处: portal爱好者 D(e9g$MA2W{L
Portlet 只产生 markup 信息片段,不是完整的网页文件
Portlet 不会和 URL 有直接的关系
客户端必须通过 Portal 系统才能和 Portlet 互动
Portlet 有一些定义好的 request 处理, action request 以及 render request
Portlet 默认定义 portlet modes 及窗口状态
Portlet 可以在同一个 portal 网页之中存在多个
Portlet有的功能而Servlet没有:
Portlet 能够存取及储存永久配置文件及定制资料
Portlet 可以存取使用者数据
Portlet 具有 URL 的重写功能够在它的内容中动态建立连结
Portlet Session 的属性拥有两个不同的范围: application-scope 及 portlet-scope
Portlet不具备而Servlet提供的功能
Servlet 具有设置输出的文字编码 ( character set encoding) 方式
Servlet 可以设置 HTTP 输出的 header
Servlet 才能够接收客户对 portal 发出的 URL 请求
这里所说的网络资源是指图片、js、css等文件资源,对于资源的获取,在servlet2.4规范下的服务器中,我们喜欢的方式为(例如获取图片资源images/a.gif):
<img src="${pageContext.request.contextPath}/images/a.gif"/>
但是在不支持servlet2.4的服务器中,就需要采用其它方式了,一种最为基本的方式如下:
<img src="<%=request.getContextPath()%>/images/a.gif"/>
另外,我们还可以借助jstl来实现:
<img src="<c:url value='/images/a.gif'/>" />
另外,也可以使用portlet的相关标签,例如:
<portletAPI:encodeURI path='/images/a.gif' />
此外,还可以使用PortletResponse的encodeURL方法:
<%=portletResponse.encodeURL('/images/a.gif')%>
这里所说的网络资源是指图片、js、css等文件资源,对于资源的获取,在servlet2.4规范下的服务器中,我们喜欢的方式为(例如获取图片资源images/a.gif):
但是在不支持servlet2.4的服务器中,就需要采用其它方式了,一种最为基本的方式如下:
<img src="${pageContext.request.contextPath}/images/a.gif"/>
<img src="<%=request.getContextPath()%>/images/a.gif"/>
另外,我们还可以借助jstl来实现:
<img src="<c:url value='/images/a.gif'/>" />
另外,也可以使用portlet的相关标签,例如:
<portletAPI:encodeURI path='/images/a.gif' />
这里所说的网络资源是指图片、js、css等文件资源,对于资源的获取,在servlet2.4规范下的服务器中,我们喜欢的方式为(例如获取图片资源images/a.gif):
<img src="${pageContext.request.contextPath}/images/a.gif"/>
但是在不支持servlet2.4的服务器中,就需要采用其它方式了,一种最为基本的方式如下:
<img src="<%=request.getContextPath()%>/images/a.gif"/>
另外,我们还可以借助jstl来实现:
<img src="<c:url value='/images/a.gif'/>" />
另外,也可以使用portlet的相关标签,例如:
<portletAPI:encodeURI path='/images/a.gif' />
此外,还可以使用PortletResponse的encodeURL方法:
<%=portletResponse.encodeURL('/images/a.gif')%>
此外,还可以使用PortletResponse的encodeURL方法:
<%=portletResponse.encodeURL('/images/a.gif')%>