基於事件偵聽與狀態模式轉換的Portlet開發

1.1  概念與前提 

要讀懂這節內容,並學會使用狀態模式開發Portlet,你必須具備這裏提到的幾種設計思路,並具備基本的Java開發技能。這裏我們選用的開發工具是 IBM Rational Application Developer以及Portlet Toolkit,你需要熟悉該工具,並懂得如何創建PortletPortlet所需的包、類、頁面,以及運行環境所需的.jar

1.1.1  狀態模式應用於Portlet

StateManagerPortlet是主要的Portlet並且是Portlet無關的。它用作分派器以支持駐留着Portlet代碼的操作和狀態類特定於Portlet的控制器代碼就存在於該類中。擴展Action抽象類的類實現了actionPerformed方法該類執行實現特定的操作請求行爲所必需的任何控制器功能。

實現狀態接口的類將實現一個performView方法該方法是由 StateManagerPortlet service 方法調用的。該方法還包含通常駐留在這些方法中的代碼。同樣這段代碼也是特定於它所駐留的狀態類的因此就避免了確定請求的操作帶來的所有額外的控制邏輯混亂。

應用狀態模式會使實現變得簡潔。而且當在Portlet的各模式之間切換時狀態總是被記住的。有了這種模式,你就可以輕鬆地確定想要何時以及在何處從源檢索數據還可以確定何時應該從高速緩存檢索數據。由於在門戶頁面刷新時不調用actionPerformed方法所以可以將數據訪問代碼放在操作狀態中並在那裏高速緩存它們。狀態類可以使用高速緩存中的數據以避免刷新門戶頁面時多次存取數據。

1.1.2  Portlet爲什麼使用狀態模式

考慮簡單的基於 MVC Portlet它從遠程機器上將包含一個產品下載配置參數列表的XML文件拷貝到本地(Portal系統所在的主機),檢索各項參數,並把列表呈現給用戶。在用戶選擇了某一項後將顯示詳細的視圖該視圖顯示的是被選項的詳細信息。這個詳細視圖可能涉及向數據庫再次發出請求。有編輯權限的用戶可以進入到Portlet的編輯模式,查看並修改XML文件的內容,保存後如果發現XML文件已經做了修改,則傳回遠程機器;否則,仍將文件包存在Portal本地,以免佔用系統資源。

第一步控制器必須調用業務對象來創建合適的Bean,該Bean被傳遞給JSP以用於主視圖中的顯示。第二步控制器在用戶的請求中檢索被選項的指示器然後調用業務對象來創建合適的Bean,該Bean被傳遞給不同的 JSP以用於詳細視圖中的顯示。

MVC實現中視圖組件顯然是不同的這兩種視圖需要有兩種不同的JSP可能需要訪問不同的業務模型組件來生成每個請求所需的Bean。控制器函數需要知道:

— 調用哪些業務方法

— 生成哪些Bean

— 把這些請求對象上的Bean放在哪裏

— 如何調用合適的JSP

這就是代碼變得複雜的地方。如果使用Servlet編程那麼可能選擇把它們實現爲不同的Servlet以使每個合適的Servlet 類的服務方法自然地分隔每個請求的控制器函數。如果更喜歡使用分派器方式而不是不同的Servlet實現那麼必須使用框架例如Struts來實現類似的MVC設計。

這是複雜的任務因爲不能選擇使用多個Portlet 類來實現一個 Portlet不能直接處理 Portlet類。相同的Portlet的服務方法用來處理返回給Portlet的所有HTTP請求因此需要實現控制代碼類具有如下功能。

— 確定正在請求哪個操作

— 需要進行哪些處理

— 使Portlet 處於哪狀態

— 顯示什麼內容返回給用戶

1.2  需求分析

1.2.1  Portlet功能需求

我們在Linux主機 test.cn.ibm.com上運行着一個自動下載的程序,要下載的產品列表及各產品的參數保存在 /home/isc/downLoadConfig/下,文件名爲AutodownConfig.xml。我們在Windows 2000 Server 主機Netecauto01上運行着IBM WebSphere Portal 5.1,普通用戶只能查看產品列表及配置權限,當該用戶要查看配置信息時,Portlet 能從服務器上將文件AutodownConfig.xml拷貝到本地服務器,並讀出XML文件中的內容,顯示在列表中。具有管理權限的用戶還有修改各配置信息的權限,能對產品配置信息的各項參數進行修改。修改完成後,要使該配置有效,必須將該XML文件回傳到pvcent07的存放目錄。

AutoDownLoadConfig Portlet 維護一個自動下載的產品配置列表在編輯模式下用戶可以瀏覽下載產品列表查看一個選定的下載產品的詳細信息也可以修改一個產品的配置信息。在配置模式下用戶可以設置數據訪問信息。雖然可用的數據源提供了包括配置模式在內的完整的實現但爲了滿足設計目的,我們只需注意查看和編輯模式的實現即可自動下載Portlet狀態模式示意圖如圖1-1所示。

基於事件偵聽與狀態模式轉換的Portlet開發2148.png

1-1  自動下載Portlet狀態模式示意圖

1.2.2  基於MVC模型的角度架構邏輯

1.以基於MVC架構的思路整理Portlet的邏輯

從可視的角度看,圖1-1所示的場景功能的實現至少需要如下頁面

— 主視圖頁面Main View Page顯示所有正在下載的產品列表和用來選擇一個產品以獲取更多詳細信息的選項

— 詳細信息視圖頁面Detail View Page顯示被選擇產品的詳細配置信息

— 主編輯頁面Main Edit Page顯示用戶有權限編輯的產品列表和用於修改更多信息的選項

— 修改條目頁面Modify Entry Page顯示相似的表單其中插入了現有的數據用於修改,包括修改單項參數,以及給某一參數增刪條目列表。 

在這種情況下用戶可以從主編輯頁面中選擇需編輯產品條目。修改後,沒有確認頁面或成功執行的頁面。進行條目修改處理並刷新主編輯頁面若出錯則顯示適當的消息但在正常處理時沒有與該操作關聯的視圖。

如何來改進這個實現呢?首先請記住這個應用程序表示一組應用程序操作和狀態;其次操作是實現操作接口的類這個類實際完成某個應用程序任務或操作處理。這就是目前存在於 actionListener 類的 actionPerformed 方法中的應用程序代碼的一部分只有這部分特定於單個操作事件。

狀態是實現狀態接口的類這個類表示由於應用了操作而產生的 Portlet 的效果。一般來說這個類有可視組件。

2Portlet所包含的內容

根據以上分析,我們將有下面這些操作 

— 所有產品配置信息的主列表視圖

— 顯示選定產品的配置詳細信息視圖

— 顯示所有可編輯產品的編輯視圖列表

— 顯示視圖來修改一個產品的配置信息。

— 爲產品添加一個可選的下載項或郵件。

— 爲產品刪除一個可選的下載項或郵件。

執行這些操作會產生下列狀態之一

— 主視圖

— 詳細信息視圖

— 主編輯視圖

— 添加下載產品視圖

— 修改下載產品視圖

從可視角度看下載產品列表 Portlet 的實現包括如下視圖頁面)。

1主視圖Main View顯示下載產品列表並帶有選項來選擇下載產品以查看更多的信息。

2詳細信息視圖Detail View顯示選定的下載產品的詳細信息。

3主編輯視圖Main Edit View顯示下載產品列表並帶有選項來添加、刪除和修改下載產品信息。

4添加下載產品視圖Add Contact View顯示錶單視圖來輸入新下載產品的信息。

5修改下載產品視圖Modify Contact View顯示相似的表單視圖來添加現有的下載產品的元素數據以供修改。

1.3  Portlet詳細設計

1.3.1  程序流程設計

下面以圖示的方式來介紹程序的數據流轉。

 在顯示模式下,Portlet會從遠程pvcent07.cn.ibm.com拷回XML文件,讀出並顯示所有正在下載的產品列表。單擊列表中的任意項,將顯示該項的詳細視圖。我們先來看產品下載列表,如圖1-2所示。

基於事件偵聽與狀態模式轉換的Portlet開發3443.png

1-2  產品下載列表

單擊任意產品的鏈接後,將顯示該產品的具體配置參數,如圖1-3所示。

基於事件偵聽與狀態模式轉換的Portlet開發3494.png

1-3  產品的具體配置參數

在編輯模式下,首先顯示的是用戶有權限編輯的產品配置列表,如圖1-4所示。

基於事件偵聽與狀態模式轉換的Portlet開發3551.png

1-4  用戶有權限編輯的產品配置列表

單擊任意產品的鏈接,進入到該產品的編輯界面,如圖1-5所示


基於事件偵聽與狀態模式轉換的Portlet開發3624.png

1-5  產品的編輯界面

用戶可以爲該產品添加CD介質,或者添加一個E-mail,如圖1-6所示。


基於事件偵聽與狀態模式轉換的Portlet開發3696.png

1-6  爲產品添加要下載的CD介質

當然,用戶也可以刪除要下載的CD介質或者E-mail,如圖1-7所示。

基於事件偵聽與狀態模式轉換的Portlet開發3773.png

1-7  刪除要下載的CD介質

用戶可以修改任意參數,然後單擊Save To XML”按鈕,Portlet將把這些參數保存到XML文件,並傳回到pvcent機器,如圖1-8所示。

基於事件偵聽與狀態模式轉換的Portlet開發3886.png

1-8  將修改保存到Portlet配置文件

 確認修改保存成功,如圖1-9 所示。


基於事件偵聽與狀態模式轉換的Portlet開發3950.png

1-9  確認修改保存成功

1.3.2  Actions States總體設計

1StateManagerPortlet

StateManagerPortlet是主要的PortletPortlet無關的一般包括所有特定於 Portlet 的代碼。該類被用作分派器以支持駐留着Portlet 代碼的操作和狀態類。StateManagerPortlet實現了actionPerformeddoViewdoEditdoHelpdoConfigure方法。

actionPerformed方法只是獲取操作類的當前實例然後分派到它的actionPerformed方法。類似地do方法獲取當前的狀態對象然後分派到它的perform方法。所以StateManagerPortlet 不需要知道當前Portlet實現的任何細節也沒有大量用來確定下一步處理的if和檢查。只要熟悉狀態與操作之間的流程處理就能正確地進行而不必編寫太多的、多餘的控制邏輯代碼。

2ActionClassManager

WebSphere PortalActionClassManager方法把Action類實例添加到已棄用的PortelURI中。這個API是有用的因爲可以從PortletEvent對象中檢索Action子類實例並把該實例作爲狀態轉換的一部分分派到它的actionPerformed方法中。推薦的API將使用字符串而不是Action來添加到PortletURI並且從Portlet Event 中進行檢索。ActionClassManager類提供了從給定的字符串到Action 類的實例映射。

— Action

實現這個接口的類將實現actionPerformed方法該方法執行任何操作以實現操作請求所需的函數。但是實現的函數特定於正被調用的操作事件。某個操作類的個別的actionPerformed方法僅包含該操作的代碼該方法還爲進一步的處理設置當前狀態。在這個流程中操作被調用後它進行特定於函數的工作然後爲下一次轉換設置狀態。

— InitialStateManager

該類爲支持的每個 Portlet方式提供初始狀態。

— State

一般來說Stateperform方法將調用JSP來顯示它的結果。用戶接口可能讓用戶來設置Portlet中的其他操作。JSP使操作類與頁面上的每個操作關聯。在用戶調用其中的一個操作時StateManagerPortletactionPerformed方法將調用合適的操作類實例接着發生了狀態轉換。狀態類並不負責狀態管理和轉換。

實現這個接口的類需實現perform方法該方法可被StateManagerPortletdo方法調用它包含一般駐留在這些方法中的代碼。同樣這些代碼特定於它們所在類的狀態從而降低了複雜性。

1.3.3  代碼類設計、操作類清單

我們所創建的各個類的功能分別簡單介紹如下。

1213.png

1State類功能邏輯介紹

子類1ActionClassManager

ActionClassManager負責返回一個操作子類實例該實例給出一個類標識符這個標識符是通過 addAction字符串方法添加到 PortletURI中的。我們遵循如下約定使類標識符爲全限定類名這樣我們就能夠很容易地創建一個類的實例。然而我們可以通過單獨處理操作子類實例來避免不必要的對象創建然後需要ActionClassManager爲所引用的操作子類返回單一的實例。

子類2ActionPerformed

抽象的操作類定義了兩個抽象的方法因此它的子類必須實現 actionPerformed 方法和 setState 方法。當 StateManagerPortlet 類從它的 actionPerformed 方法分派處理時操作子類的 actionPerformed 方法得到調用。

setState方法也可由 StateManagerPortlet調用確保操作子類的實現在該用戶請求的操作處理完成之後設置下一個狀態。操作類實現它自己的setState方法子類必須調用該方法來真正設置下一個狀態。這確保了操作類和狀態類知道在哪類設置和恢復下一個狀態而不需要子類知道這些機制。這些狀態跨HTTP請求並維持在每Portlet模式下。所以當用戶改變模式時控制返回到最近一次訪問的狀態。

子類3MainViewAction操作類

MainViewAction 類並不需要任何特定的操作處理。事實上我們需要將下載產品列表顯示在主視圖上。我們能夠實現在actionPerformed方法中創建恰當的下載產品列表Bean的代碼將該代碼設置在會話或請求對象裏然後將下一個狀態設置到MainViewState裏。 performView implementation繼承MainViewAction操作類,能夠簡單地調用JSP並提交來自會話或請求的Bean裏的列表內容。然而我們必須注意門戶頁面更新以防更新時調用的是PortletMainViewStateperformView方法,而非MainViewActionactionPerformed方法。所以我們不能只是將Bean放置於請求對象裏而沒有讓 performView 方法重新創建該Bean並將新的Bean放在該請求對象裏。我們可以在會話裏再次使用該Bean。但如果那樣做的話數據將會過時。如果我們在編輯模式下做了變動就需要通知該變化並在 State 方法裏刷新數據Bean。爲了簡化這種處理我們會只爲 MainViewState State 方法裏得到數據 Bean

所以 MainViewState 類裏actionPerformed方法並沒有另外處理只是簡單設置了MainViewState而已。

子類4StateManagerPortlet

actionPerformed 完成處理時控制返回到門戶容器以便其他的偵聽器通知處理程序執行。然後門戶容器通過調用 StateManagerPortlet service 方法繼續 Portlet 請求處理。

StateManagerPortlet service 方法首先試圖檢索以前執行的操作類設置的狀態類如果沒有發現狀態類引用例如最初的 Portlet 調用),那麼就使用一個助手類 InitialStateManager 來爲每Portlet 模式確定初始的狀態類。InitialStateManager 有一個一的方法叫做 getInitialState它根據 Portlet 的當前模式返回狀態對象的一個實例。對於下載產品列表 Portlet這個類將爲視圖模式返回 MainViewState 的一個實例。

State接口有一個一的方法 performView所有的狀態類都必須實現它。StateManagerPortlet service 方法調用這個方法。

子類5MainViewState

MainViewState performView 方法負責在 Contacts Bean 的列表表單中獲取下載產品列表下載產品列表保存在數據庫裏然後傳遞到 JSP 以便在主視圖中呈現出來。

子類6MainViewState

這個子類允許用戶單擊一個下載產品條目然後顯示該下載產品的詳細信息視圖。

用於這個標記的 href 使用來自Portlet標記庫中的createURI標記。該標記在URIAction中獲得參數URIAction被我們設置爲操作類中用於用戶單擊操作的事件處理方法的名稱。

子類7actionPerformed

actionPerformed類用來查看JSP上顯示的主要清單。用戶可以從主視圖頁面選擇特定的下載產品條目來獲得詳細信息。我們還添加了一個錨標記將下載產品條目的名稱作爲可點擊的鏈接顯示出來擊時StateManagerPortletactionPerformed 方法被DetailViewAction 類調用。

actionPerformed方法得到所選擇的下載產品條目的對象id並調用持久性類的代理爲該id獲取實例化的下載產品對象。這個下載產品對象放在State類的會話中用來呈現詳細信息視圖。如果該頁面由於門戶頁面刷新而得以刷新那麼該Bean就將在會話中可用既然該對象只會通過用戶使用 Portlet 來獲得更新我們就不必擔心數據過時了。

門戶頁面刷新的另一個關鍵之處是表單數據沒有被重新初始化。如果我們試圖獲得所選下載產品的對象id作爲狀態類的請求參數它在門戶頁面刷新時將不可用。因此爲了使 Portlet 能正常運行必須在剛開始時就檢索數據元素然後將其存儲在某個地方這樣在隨後的頁面刷新時它纔可以被引用。由於 actionPerformed 方法曾被調用所以這就是存放這段代碼的好地方。

actionPerformed方法中保留後端數據訪問可以確保我們在頁面刷新時對於同一數據不需要多次訪問數據庫。當然返回到數據源進行數據刷新的時間和頻率取決於Portlet的需求以及數據本身的因素。在這種情況下數據不是動態的 Portlet 頁面被刷新時應該對其進行高速緩存。

DetailViewState 被設置爲這個Portlet的下一個狀態對於Portlet其中的處理將繼續。

子類8DetailViewState

DetailViewState 簡單地調用JSP來呈現詳細信息視圖JSP 從會話中獲取下載產品 Bean。在UI交互界面中當用戶單擊OK按鈕時處理返回到主視圖繼續進行。MainViewActionactionPerformed 方法通過刪除我們在 DetailViewAction 類中設置的下載產品對象 id 來簡單地刪除會話數據。

子類9ViewProductAction

ViewProductAction類用來顯示下載產品詳細信息視圖JSP頁面。流邏輯以一種組織良好的方式進行,你不需要在Portlet使用冗的控制代碼。Portlet 的編輯和配置模式也以同樣的方法實現。

2完成Portlet實現

該應用程序的其餘部分仍遵循以上所述的開發模式。編輯模式的處理控制邏輯流和視圖模式的完全一樣。我們實現一配置模式它允許用戶指定數據源來保存下載產品數據。它將以同樣的方式實現。配置模式只有一個視圖來讓用戶訪問數據源另外有兩個類來檢驗數據源和保存數據源爲配置數據。

下面是實現狀態模式的基本步驟。

  所執行的特定模式的初始狀態類由 InitialStateManager 類提供。

狀態類的 performView方法其調用是由 StateManagerPortlet 分派的進行任何必要的應用程序邏輯處理然後調用它的 JSP

通過PortletURI上的一個參數將每個用戶的操作與在其中進行事件處理的操作子類的名稱相關聯。每個用戶操作一般都指定一個不同的操作子類該子類實現一個單一的、特定的功能。

用戶單擊一個鏈接時操作類的 actionPerformed 方法被調用由於通過 StateManagerPortlet 分派而被再次調用。執行操作邏輯並設置適當的狀態類以使處理繼續進行。

當事件處理完成後StateManagerPortletservice方法被調用並再次分派給在Action事件處理階段設置的狀態類該狀態類執行應用程序邏輯並調用它的 JSP 來呈現結果。

當用戶瀏覽整個 Portlet 操作以這種方式繼續。

3持久性代理

訪問數據庫中的持久性數據需要額外的 Portlet 組件。AbstractBroker 類提供一般的JDBC數據庫訪問功能。它能夠用來獲取數據庫的DataSourceConnection它在高速緩存中緩存DataSource從而避免重複的、高代價的JNDI查找它也提供通用代碼來執行 PreparedStatement並關閉ConnectionStatementResultSet

ContactListBroker 類繼承了 AbstractBroker它實現特定於 Portlet 需要的數據訪問方法 getContact 方法和 getContactList 方法用於保存刪除一個列表中的條目。同時它還有檢驗表 Schema 的功能這樣我們就可以檢驗用戶在配置模式下指定的數據源。

4異常處理

我們已經爲Portlet 實現了大量的異常類基本類AIMExceptionAIMWrapperExceptionAIMException 的子類。可以用 AIMWrapperException 封裝其他拋出的異常以便在 StateManagerPortletservice 方法中高效地修改顯示行爲和管理異常處理。

AIMMessageException 是一個特殊的異常它允許在終止處理時向 Portlet 生成一條報告性消息或錯誤消息。例如可以拋出一個 AIMMessage 異常用一條消息指出用戶必須先登錄。

actionPerformed方法或setState方法中拋出的異常被捕獲並且被延遲到 service 方法。管理延遲的方法是捕獲這些方法中拋出的所有異常並將異常通常封裝在一個AIMWrapperException放在請求對象上。當調用StateManagerPortletservice方法時它首先查找有沒有延遲異常如果找到了就從此處重新拋出並處理這些異常。

因此所有的Portlet應用程序異常都是在 StateManagerPortletservice方法中處理的。如果發現了異常,則在以下兩種情況中調用異常方法異常消息將在Portlet中被顯示異常消息以及相關聯的堆棧跟蹤信息將被顯示。將堆棧跟蹤信息放在 Portlet 外有助於在開發時進行調試。由於不想向實際應用的用戶顯示這種級別的詳細信息所以該行爲是可配置的。這是在部署描述符裏定義的 debugTrace參數。

5建立開發環境

如果使用WebSphere Studio來創建這個Portlet請確保下列JAR文件構建路徑是可用的以便Portlet代碼可以順利編譯。如果Studio中使用Portal Toolkit並創建Portlet應用項目那麼類路徑會自動創建。不管哪種情況,你都可以創建一個Web項目或Portlet應用項目然後導入下載中的WAR文件從而將這個Portlet應用程序載入Studio

SERVERJDK_50_PLUGINDIR/jre/lib/rt.jar

WAS_50_PLUGINDIR/lib/dynacache.jar

WAS_50_PLUGINDIR/lib/j2ee.jar

WAS_50_PLUGINDIR/lib/servletevent.jar

WAS_50_PLUGINDIR/lib/ivjejb35.jar

WAS_50_PLUGINDIR/lib/runtime.jar

WAS_50_PLUGINDIR/lib/ras.jar

WAS_50_PLUGINDIR/lib/naming.jar

WAS_50_PLUGINDIR/lib/utils.jar

WPS_V5_PLUGINDIR/portlet-api.jar

WPS_V5_PLUGINDIR/wpsportlets.jar

WPS_V5_PLUGINDIR/wps.jar

如果沒有使用 Portal Toolkit或者Studio,那麼可以在 <WAS_ROOT>/lib <WPS_ROOT>/shared/app 中找到這些文件。

Portlet部署到WebSphere Portal 環境中時所有必需的JAR文件都要同時打包進去可以不修改 Portal 中安裝 Portlet WAR 文件。

1.3.5  RAD實現Portlet

針對入門者,我們以圖示的方式,向大家介紹使用IBM提供的開發工具RADRational Application Developer)來創建、開發、調試、打包Portlet

原則上我是按照安裝從始至終的次序來截圖的,但爲了使層次更清晰,我們還是分爲以下7個步驟來分別介紹。

1.安裝RAD,創建portlet

Windows 2003 Server系統的“控制面板”高級”選項中設置”按鈕,在出現的對話框中選擇數據執行保存面板,添加...按鈕,把安裝後的rationalsdp.exeenroll.exe 添加到列表中。

打開RAD,單擊“新建”按鈕,選擇“項目”→“Portlet項目”,然後依次輸入各項參數,包括Portlet的名稱、包名、是否使用憑證保險庫等。

參數                           

Portlet 名稱                                   DownLoadConfig

Portlet 類型                                   基本Portlet

Web功能部件                使用Web圖與JSP標記庫

是否需要添加操作偵聽實例              不需要

是否需要添加憑證保險庫                 不需要

使用模式               顯示模式、編輯模式、培植模式、幫助模式

單擊“完成”按鈕,Rational開始自動創建這個Portlet,創建完成後自動打開“DownLoadConfigView.jsp”文件,如圖1-10所示。


基於事件偵聽與狀態模式轉換的Portlet開發12614.png

1-10  RAD中開發Portle


2.創建並設計所需的操作類(Actions


創建一個Action包:com.ibm.csdl.portal.download.config.actions,在這個包裏分別創建以下類,如圖1-11所示。

基於事件偵聽與狀態模式轉換的Portlet開發12742.png

1-11  創建的操作類

這些類實現了Portlet的所有操作,我們以“爲產品配置刪去一個CD或者E-mail”爲例,看一下Action實現了哪些功能。

actionPerformed方法裏,程序接收從editAProduct.jsp傳過來的參數,也就是CDsEmails兩個選擇框傳過來的值,看要刪除的是一個CD還是一個E-mail,然後從產品配置對象裏面將對應的CD或者E-mail刪除,最後寫回到XML文件中。

setState()方法裏,程序實例化一個RemoveOneCDsOrEmailState,將邏輯交給State來處理。那麼,State又如何流轉呢?看下面的State類。

3.創建並開發所需的狀態類 (States)

  創建一個State包:com.ibm.csdl.portal.download.config.actions,在這個包裏分別創建以下類,如圖1-12所示。

基於事件偵聽與狀態模式轉換的Portlet開發13151.png

1-12  創建的狀態類

這些類實現了Portlet的所有狀態模式轉換,我們以“爲產品配置刪去一個CD或者E-mail”爲例,看一下State實現了哪些功能。

RemoveOneCDsOrEmailState.java代碼清單如下:

基於事件偵聽與狀態模式轉換的Portlet開發13271.png

State類裏面只有兩個方法,其中一個方法用於獲得實例,我們就不管了;另一個方法是performView,它負責讀出XML文件裏的內容(現在已經是修改後的了),然後放入Session,調用並初始化一個新的指定的JSP文件。這個JSPSession裏面取出數據,然後初始化。

4.創建並開發所需的數據結構(Data)以及Portlet

Data類主要定義了一些數據結構,用來存放XML文件中的數據,與Portlet的開發基本上無關。

Portlet類主要用來初始化一些數據,以及根據Portlet的狀態調用相應的JSP頁面。


nls下的資源文件與瀏覽器的多語言支持相關,可以根據客戶端瀏覽器的設置,從相應的資源裏取出靜態描述文件Portlet.xml,然後在JSP文件中完成初始化的過程。

com.ibm.csdl.portal.download.config.utilities包主要處理一些異常(見圖1-13),這裏不再贅述。

基於事件偵聽與狀態模式轉換的Portlet開發13717.png

1-13  com.ibm.csdl.portal.download.config.utilities中默認帶有常見的異常處理邏輯

5.創建並開發所需的頁面(Pages

根據上面的詳細設計,我們需要創建一些頁面,如圖1-14所示。

基於事件偵聽與狀態模式轉換的Portlet開發13837.png

1-14  創建的頁面

這些頁面的功能如下。

基於事件偵聽與狀態模式轉換的Portlet開發13863.png

頁面的顯示邏輯略。我們以ViewAllTheProduct.jsp爲例,看一下Rational是怎樣給一個鏈接添加操作事件偵聽的。

ViewAllTheProduct.jsp源代碼如下:


基於事件偵聽與狀態模式轉換的Portlet開發13959.png

其實很簡單,用一個超鏈接就能添加該鏈接的操作事件偵聽,代碼如下:

基於事件偵聽與狀態模式轉換的Portlet開發13994.png

其他的類似,這裏不再贅述。

6.調試 Portlet

 假設在9.181.66.250上運行着一個Portal系統,超級管理員的用戶名和密碼都是admin,我們可以創建一個服務器用來測試Portlet,如圖1-15所示。

基於事件偵聽與狀態模式轉換的Portlet開發14108.png

1-15  RAD中創建Portal服務器用於調試Portlet

選擇服務器的類型爲WebSphere Portal,並輸入相關參數。

右擊項目名,選擇“運行”→“在服務器上運行”,如圖1-16所示。

基於事件偵聽與狀態模式轉換的Portlet開發14217.png

1-16  選擇直接在RAD中運行Portlet

 幾分鐘後,會在工作區出現瀏覽頁面,這樣就可以調試該Portlet了。

7.打包,生成產品

打包Portlet也非常簡單,右擊項目名,選擇“導出”→“WAR文件”,再選擇好存儲位置就可以了,如圖1-17所示。

基於事件偵聽與狀態模式轉換的Portlet開發14370.png

1-17  Portlet導出爲WAR包部署到Portal服務器

拿這個WAR包,就可以發佈或者更新到Portal系統上使用了。

1.4  Portlet 開發指導原則和示例實現

Portlet 開發指導原則和示例實現可以Portlet API很好的理解。然而實現複雜的流程控制超出了 API 的範圍。如果沒有定義完善的方法來解決如何最好地實現控制邏輯這一問題,你就不能夠創建這樣的Portlet它們包含有專門定位用戶請求目的的簡單合理的 代碼。

除了重複之外該代碼使Portlet更難以讀懂因爲需要進入控制邏輯以獲取Portlet正在做的實際工作。控制邏輯也容易出錯因爲它依賴於多方面情況比如,使用字符串匹配用來連接事件和偵聽器偵聽器操作和 Portlet 方法中的Action。爲了解決控制邏輯的這些問題,你可以將應用程序看Portlet的操作和狀態的集合然後通過一個定義完善的方法來進行狀態轉換這樣就可以將Portlet應用程序中冗的控制邏輯代碼刪除。

開發人員也可以選擇採用Struts框架來實現PortletStruts是一個Jakarta項目它提供一個非常流行的開放源代碼框架來建立 Web 應用程序。使用附帶了 Portal Struts Portlet FrameworkStruts框架寫成的Portlet就可以在WebSphere Portal上運行。Struts提供了值得考慮的Web應用程序其功能遠遠超過頁面導航它是進行Portlet開發的一個很好的選擇。對Struts不熟悉或者希望更直接訪問 Portlet API 的開發人員會從用於頁面導航的狀態轉換實現中獲益。這種模式和Struts框架一樣使面向MVC設計的應用程序框架得以改進。



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