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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章