溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

發(fā)布時(shí)間:2020-06-09 04:46:36 來(lái)源:網(wǎng)絡(luò) 閱讀:352 作者:鄭文平Portal 欄目:軟件技術(shù)

1.1  概念與前提 

要讀懂這節(jié)內(nèi)容,并學(xué)會(huì)使用狀態(tài)模式開(kāi)發(fā)Portlet,你必須具備這里提到的幾種設(shè)計(jì)思路,并具備基本的Java開(kāi)發(fā)技能。這里我們選用的開(kāi)發(fā)工具是 IBM Rational Application Developer以及Portlet Toolkit,你需要熟悉該工具,并懂得如何創(chuàng)建PortletPortlet所需的包、類(lèi)、頁(yè)面,以及運(yùn)行環(huán)境所需的.jar。

1.1.1  狀態(tài)模式應(yīng)用于Portlet

StateManagerPortlet是主要的Portlet類(lèi),并且是Portlet無(wú)關(guān)的。它用作分派器以支持駐留著Portlet代碼的操作和狀態(tài)類(lèi),特定于Portlet的控制器代碼就存在于該類(lèi)中。擴(kuò)展Action抽象類(lèi)的類(lèi)實(shí)現(xiàn)了actionPerformed方法,該類(lèi)執(zhí)行實(shí)現(xiàn)特定的操作請(qǐng)求行為所必需的任何控制器功能。

實(shí)現(xiàn)狀態(tài)接口的類(lèi)將實(shí)現(xiàn)一個(gè)performView方法,該方法是由 StateManagerPortlet service 方法調(diào)用的。該方法還包含通常駐留在這些方法中的代碼。同樣,這段代碼也是特定于它所駐留的狀態(tài)類(lèi)的,因此就避免了確定請(qǐng)求的操作帶來(lái)的所有額外的控制邏輯混亂。

應(yīng)用狀態(tài)模式會(huì)使實(shí)現(xiàn)變得簡(jiǎn)潔。而且,當(dāng)在Portlet的各模式之間切換時(shí),狀態(tài)總是被記住的。有了這種模式,你就可以輕松地確定想要何時(shí)以及在何處從源檢索數(shù)據(jù),還可以確定何時(shí)應(yīng)該從高速緩存檢索數(shù)據(jù)。由于在門(mén)戶(hù)頁(yè)面刷新時(shí)不調(diào)用actionPerformed方法,所以可以將數(shù)據(jù)訪問(wèn)代碼放在操作狀態(tài)中并在那里高速緩存它們。狀態(tài)類(lèi)可以使用高速緩存中的數(shù)據(jù),以避免刷新門(mén)戶(hù)頁(yè)面時(shí)多次存取數(shù)據(jù)。

1.1.2  Portlet為什么使用狀態(tài)模式

考慮簡(jiǎn)單的基于 MVC Portlet,它從遠(yuǎn)程機(jī)器上將包含一個(gè)產(chǎn)品下載配置參數(shù)列表的XML文件拷貝到本地(Portal系統(tǒng)所在的主機(jī)),檢索各項(xiàng)參數(shù),并把列表呈現(xiàn)給用戶(hù)。在用戶(hù)選擇了某一項(xiàng)后將顯示詳細(xì)的視圖,該視圖顯示的是被選項(xiàng)的詳細(xì)信息。這個(gè)詳細(xì)視圖可能涉及向數(shù)據(jù)庫(kù)再次發(fā)出請(qǐng)求。有編輯權(quán)限的用戶(hù)可以進(jìn)入到Portlet的編輯模式,查看并修改XML文件的內(nèi)容,保存后如果發(fā)現(xiàn)XML文件已經(jīng)做了修改,則傳回遠(yuǎn)程機(jī)器;否則,仍將文件包存在Portal本地,以免占用系統(tǒng)資源。

第一步,控制器必須調(diào)用業(yè)務(wù)對(duì)象來(lái)創(chuàng)建合適的Bean,該Bean被傳遞給JSP以用于主視圖中的顯示。第二步,控制器在用戶(hù)的請(qǐng)求中檢索被選項(xiàng)的指示器,然后調(diào)用業(yè)務(wù)對(duì)象來(lái)創(chuàng)建合適的Bean,該Bean被傳遞給不同的 JSP以用于詳細(xì)視圖中的顯示。

MVC實(shí)現(xiàn)中,視圖組件顯然是不同的。這兩種視圖需要有兩種不同的JSP。可能需要訪問(wèn)不同的業(yè)務(wù)模型組件來(lái)生成每個(gè)請(qǐng)求所需的Bean??刂破骱瘮?shù)需要知道:

— 調(diào)用哪些業(yè)務(wù)方法?

— 生成哪些Bean?

— 把這些請(qǐng)求對(duì)象上的Bean放在哪里?

— 如何調(diào)用合適的JSP?

這就是代碼變得復(fù)雜的地方。如果使用Servlet編程,那么可能選擇把它們實(shí)現(xiàn)為不同的Servlet,以使每個(gè)合適的Servlet 類(lèi)的服務(wù)方法自然地分隔每個(gè)請(qǐng)求的控制器函數(shù)。如果更喜歡使用分派器方式而不是不同的Servlet實(shí)現(xiàn),那么必須使用框架例如Struts來(lái)實(shí)現(xiàn)類(lèi)似的MVC設(shè)計(jì)。

這是復(fù)雜的任務(wù),因?yàn)椴荒苓x擇使用多個(gè)Portlet 類(lèi)來(lái)實(shí)現(xiàn)一個(gè) Portlet,不能直接處理 Portlet類(lèi)。相同的Portlet的服務(wù)方法用來(lái)處理返回給Portlet的所有HTTP請(qǐng)求,因此,需要實(shí)現(xiàn)控制代碼類(lèi)具有如下功能。

— 確定正在請(qǐng)求哪個(gè)操作?

— 需要進(jìn)行哪些處理?

— 使Portlet 處于哪狀態(tài)?

— 顯示什么內(nèi)容返回給用戶(hù)?

1.2  需求分析

1.2.1  Portlet功能需求

我們?cè)?/span>Linux主機(jī) test.cn.ibm.com上運(yùn)行著一個(gè)自動(dòng)下載的程序,要下載的產(chǎn)品列表及各產(chǎn)品的參數(shù)保存在 /home/isc/downLoadConfig/下,文件名為AutodownConfig.xml。我們?cè)?/span>Windows 2000 Server 主機(jī)Netecauto01上運(yùn)行著IBM WebSphere Portal 5.1,普通用戶(hù)只能查看產(chǎn)品列表及配置權(quán)限,當(dāng)該用戶(hù)要查看配置信息時(shí),Portlet 能從服務(wù)器上將文件AutodownConfig.xml拷貝到本地服務(wù)器,并讀出XML文件中的內(nèi)容,顯示在列表中。具有管理權(quán)限的用戶(hù)還有修改各配置信息的權(quán)限,能對(duì)產(chǎn)品配置信息的各項(xiàng)參數(shù)進(jìn)行修改。修改完成后,要使該配置有效,必須將該XML文件回傳到pvcent07的存放目錄。

AutoDownLoadConfig Portlet 維護(hù)一個(gè)自動(dòng)下載的產(chǎn)品配置列表,在編輯模式下,用戶(hù)可以瀏覽下載產(chǎn)品列表,查看一個(gè)選定的下載產(chǎn)品的詳細(xì)信息,也可以修改一個(gè)產(chǎn)品的配置信息。在配置模式下用戶(hù)可以設(shè)置數(shù)據(jù)訪問(wèn)信息。雖然可用的數(shù)據(jù)源提供了包括配置模式在內(nèi)的完整的實(shí)現(xiàn),但為了滿(mǎn)足設(shè)計(jì)目的,我們只需注意查看和編輯模式的實(shí)現(xiàn)即可。自動(dòng)下載Portlet狀態(tài)模式示意圖如圖1-1所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-1  自動(dòng)下載Portlet狀態(tài)模式示意圖

1.2.2  基于MVC模型的角度架構(gòu)邏輯

1.以基于MVC架構(gòu)的思路整理Portlet的邏輯

從可視的角度看,圖1-1所示的場(chǎng)景功能的實(shí)現(xiàn)至少需要如下頁(yè)面。

— 主視圖頁(yè)面Main View Page顯示所有正在下載的產(chǎn)品列表和用來(lái)選擇一個(gè)產(chǎn)品以獲取更多詳細(xì)信息的選項(xiàng)。

— 詳細(xì)信息視圖頁(yè)面Detail View Page顯示被選擇產(chǎn)品的詳細(xì)配置信息。

— 主編輯頁(yè)面Main Edit Page顯示用戶(hù)有權(quán)限編輯的產(chǎn)品列表和用于修改更多信息的選項(xiàng)。

— 修改條目頁(yè)面Modify Entry Page顯示相似的表單,其中插入了現(xiàn)有的數(shù)據(jù)用于修改,包括修改單項(xiàng)參數(shù),以及給某一參數(shù)增刪條目列表。 

在這種情況下,用戶(hù)可以從主編輯頁(yè)面中選擇需編輯產(chǎn)品條目。修改后,沒(méi)有確認(rèn)頁(yè)面或成功執(zhí)行的頁(yè)面。進(jìn)行條目修改處理并刷新主編輯頁(yè)面,若出錯(cuò),則顯示適當(dāng)?shù)南?/span>,但在正常處理時(shí),沒(méi)有與該操作關(guān)聯(lián)的視圖。

如何來(lái)改進(jìn)這個(gè)實(shí)現(xiàn)呢?首先,請(qǐng)記住這個(gè)應(yīng)用程序表示一組應(yīng)用程序操作和狀態(tài);其次操作是實(shí)現(xiàn)操作接口的類(lèi),這個(gè)類(lèi)實(shí)際完成某個(gè)應(yīng)用程序任務(wù)或操作處理。這就是目前存在于 actionListener 類(lèi)的 actionPerformed 方法中的應(yīng)用程序代碼的一部分,只有這部分特定于單個(gè)操作事件。

狀態(tài)是實(shí)現(xiàn)狀態(tài)接口的類(lèi),這個(gè)類(lèi)表示由于應(yīng)用了操作而產(chǎn)生的 Portlet 的效果。一般來(lái)說(shuō),這個(gè)類(lèi)有可視組件。

2Portlet所包含的內(nèi)容

根據(jù)以上分析,我們將有下面這些操作。 

— 所有產(chǎn)品配置信息的主列表視圖。

— 顯示選定產(chǎn)品的配置詳細(xì)信息視圖。

— 顯示所有可編輯產(chǎn)品的編輯視圖列表。

— 顯示視圖來(lái)修改一個(gè)產(chǎn)品的配置信息。

— 為產(chǎn)品添加一個(gè)可選的下載項(xiàng)或郵件。

— 為產(chǎn)品刪除一個(gè)可選的下載項(xiàng)或郵件。

執(zhí)行這些操作會(huì)產(chǎn)生下列狀態(tài)之一。

— 主視圖。

— 詳細(xì)信息視圖。

— 主編輯視圖。

— 添加下載產(chǎn)品視圖。

— 修改下載產(chǎn)品視圖。

從可視角度看,下載產(chǎn)品列表 Portlet 的實(shí)現(xiàn)包括如下視圖頁(yè)面)。

1主視圖Main View顯示下載產(chǎn)品列表,并帶有選項(xiàng)來(lái)選擇下載產(chǎn)品以查看更多的信息。

2詳細(xì)信息視圖Detail View顯示選定的下載產(chǎn)品的詳細(xì)信息。

3主編輯視圖Main Edit View顯示下載產(chǎn)品列表,并帶有選項(xiàng)來(lái)添加、刪除和修改下載產(chǎn)品信息。

4添加下載產(chǎn)品視圖Add Contact View顯示表單視圖來(lái)輸入新下載產(chǎn)品的信息。

5修改下載產(chǎn)品視圖Modify Contact View顯示相似的表單視圖來(lái)添加現(xiàn)有的下載產(chǎn)品的元素?cái)?shù)據(jù)以供修改。

1.3  Portlet詳細(xì)設(shè)計(jì)

1.3.1  程序流程設(shè)計(jì)

下面以圖示的方式來(lái)介紹程序的數(shù)據(jù)流轉(zhuǎn)。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā) 在顯示模式下,Portlet會(huì)從遠(yuǎn)程pvcent07.cn.ibm.com拷回XML文件,讀出并顯示所有正在下載的產(chǎn)品列表。單擊列表中的任意項(xiàng),將顯示該項(xiàng)的詳細(xì)視圖。我們先來(lái)看產(chǎn)品下載列表,如圖1-2所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-2  產(chǎn)品下載列表

單擊任意產(chǎn)品的鏈接后,將顯示該產(chǎn)品的具體配置參數(shù),如圖1-3所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-3  產(chǎn)品的具體配置參數(shù)

在編輯模式下,首先顯示的是用戶(hù)有權(quán)限編輯的產(chǎn)品配置列表,如圖1-4所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-4  用戶(hù)有權(quán)限編輯的產(chǎn)品配置列表

單擊任意產(chǎn)品的鏈接,進(jìn)入到該產(chǎn)品的編輯界面,如圖1-5所示。


基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-5  產(chǎn)品的編輯界面

用戶(hù)可以為該產(chǎn)品添加CD介質(zhì),或者添加一個(gè)E-mail,如圖1-6所示。


基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-6  為產(chǎn)品添加要下載的CD介質(zhì)

當(dāng)然,用戶(hù)也可以刪除要下載的CD介質(zhì)或者E-mail,如圖1-7所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-7  刪除要下載的CD介質(zhì)

用戶(hù)可以修改任意參數(shù),然后單擊Save To XML”按鈕,Portlet將把這些參數(shù)保存到XML文件,并傳回到pvcent機(jī)器,如圖1-8所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

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

 確認(rèn)修改保存成功,如圖1-9 所示。


基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-9  確認(rèn)修改保存成功

1.3.2  Actions States總體設(shè)計(jì)

1StateManagerPortlet

StateManagerPortlet是主要的Portlet類(lèi),Portlet無(wú)關(guān)的,一般包括所有特定于 Portlet 的代碼。該類(lèi)被用作分派器以支持駐留著Portlet 代碼的操作和狀態(tài)類(lèi)。StateManagerPortlet實(shí)現(xiàn)了actionPerformed、doViewdoEdit、doHelpdoConfigure方法。

actionPerformed方法只是獲取操作類(lèi)的當(dāng)前實(shí)例,然后分派到它的actionPerformed方法。類(lèi)似地,do方法獲取當(dāng)前的狀態(tài)對(duì)象,然后分派到它的perform方法。所以,StateManagerPortlet 不需要知道當(dāng)前Portlet實(shí)現(xiàn)的任何細(xì)節(jié),也沒(méi)有大量用來(lái)確定下一步處理的if和檢查。只要熟悉狀態(tài)與操作之間的流程,處理就能正確地進(jìn)行,而不必編寫(xiě)太多的、多余的控制邏輯代碼。

2ActionClassManager

WebSphere Portal,ActionClassManager方法把Action類(lèi)實(shí)例添加到已棄用的PortelURI中。這個(gè)API是有用的,因?yàn)?/span>可以從PortletEvent對(duì)象中檢索Action子類(lèi)實(shí)例,并把該實(shí)例作為狀態(tài)轉(zhuǎn)換的一部分分派到它的actionPerformed方法中。推薦的API將使用字符串而不是Action來(lái)添加到PortletURI,并且從Portlet Event 中進(jìn)行檢索。ActionClassManager類(lèi)提供了從給定的字符串到Action 類(lèi)的實(shí)例映射。

— Action

實(shí)現(xiàn)這個(gè)接口的類(lèi)將實(shí)現(xiàn)actionPerformed方法,該方法執(zhí)行任何操作以實(shí)現(xiàn)操作請(qǐng)求所需的函數(shù)。但是,實(shí)現(xiàn)的函數(shù)特定于正被調(diào)用的操作事件。某個(gè)操作類(lèi)的個(gè)別的actionPerformed方法僅包含該操作的代碼該方法還為進(jìn)一步的處理設(shè)置當(dāng)前狀態(tài)。在這個(gè)流程中,操作被調(diào)用后,它進(jìn)行特定于函數(shù)的工作,然后為下一次轉(zhuǎn)換設(shè)置狀態(tài)。

— InitialStateManager

該類(lèi)為支持的每個(gè) Portlet方式提供初始狀態(tài)。

— State

一般來(lái)說(shuō),Stateperform方法將調(diào)用JSP來(lái)顯示它的結(jié)果。用戶(hù)接口可能讓用戶(hù)來(lái)設(shè)置Portlet中的其他操作。JSP使操作類(lèi)與頁(yè)面上的每個(gè)操作關(guān)聯(lián)。在用戶(hù)調(diào)用其中的一個(gè)操作時(shí),StateManagerPortletactionPerformed方法將調(diào)用合適的操作類(lèi)實(shí)例,接著發(fā)生了狀態(tài)轉(zhuǎn)換。狀態(tài)類(lèi)并不負(fù)責(zé)狀態(tài)管理和轉(zhuǎn)換。

實(shí)現(xiàn)這個(gè)接口的類(lèi)需實(shí)現(xiàn)perform方法,該方法可被StateManagerPortletdo方法調(diào)用,它包含一般駐留在這些方法中的代碼。同樣,這些代碼特定于它們所在類(lèi)的狀態(tài),從而降低了復(fù)雜性。

1.3.3  代碼類(lèi)設(shè)計(jì)、操作類(lèi)清單

我們所創(chuàng)建的各個(gè)類(lèi)的功能分別簡(jiǎn)單介紹如下。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1State類(lèi)功能邏輯介紹

子類(lèi)1ActionClassManager類(lèi)

ActionClassManager類(lèi)負(fù)責(zé)返回一個(gè)操作子類(lèi)實(shí)例,該實(shí)例給出一個(gè)類(lèi)標(biāo)識(shí)符,這個(gè)標(biāo)識(shí)符是通過(guò) addAction字符串方法添加到 PortletURI中的。我們遵循如下約定使類(lèi)標(biāo)識(shí)符為全限定類(lèi)名這樣我們就能夠很容易地創(chuàng)建一個(gè)類(lèi)的實(shí)例。然而,我們可以通過(guò)單獨(dú)處理操作子類(lèi)實(shí)例來(lái)避免不必要的對(duì)象創(chuàng)建,然后需要ActionClassManager為所引用的操作子類(lèi)返回單一的實(shí)例。

子類(lèi)2ActionPerformed類(lèi)

抽象的操作類(lèi)定義了兩個(gè)抽象的方法,因此它的子類(lèi)必須實(shí)現(xiàn) actionPerformed 方法和 setState 方法。當(dāng) StateManagerPortlet 類(lèi)從它的 actionPerformed 方法分派處理時(shí),操作子類(lèi)的 actionPerformed 方法得到調(diào)用。

setState方法也可由 StateManagerPortlet調(diào)用,確保操作子類(lèi)的實(shí)現(xiàn)在該用戶(hù)請(qǐng)求的操作處理完成之后設(shè)置下一個(gè)狀態(tài)。操作類(lèi)實(shí)現(xiàn)它自己的setState方法,子類(lèi)必須調(diào)用該方法來(lái)真正設(shè)置下一個(gè)狀態(tài)。這確保了操作類(lèi)和狀態(tài)類(lèi)知道在哪個(gè)類(lèi)設(shè)置和恢復(fù)下一個(gè)狀態(tài),而不需要子類(lèi)知道這些機(jī)制。這些狀態(tài)跨HTTP請(qǐng)求,并維持在每Portlet模式下。所以,當(dāng)用戶(hù)改變模式時(shí),控制返回到最近一次訪問(wèn)的狀態(tài)。

子類(lèi)3MainViewAction操作類(lèi)

MainViewAction 類(lèi)并不需要任何特定的操作處理。事實(shí)上,我們需要將下載產(chǎn)品列表顯示在主視圖上。我們能夠?qū)崿F(xiàn)在actionPerformed方法中創(chuàng)建恰當(dāng)?shù)南螺d產(chǎn)品列表Bean的代碼,將該代碼設(shè)置在會(huì)話(huà)或請(qǐng)求對(duì)象里,然后將下一個(gè)狀態(tài)設(shè)置到MainViewState里。類(lèi) performView implementation繼承MainViewAction操作類(lèi),能夠簡(jiǎn)單地調(diào)用JSP并提交來(lái)自會(huì)話(huà)或請(qǐng)求的Bean里的列表內(nèi)容。然而,我們必須注意門(mén)戶(hù)頁(yè)面更新,以防更新時(shí)調(diào)用的是PortletMainViewState、performView方法,而非MainViewActionactionPerformed方法。所以,我們不能只是將Bean放置于請(qǐng)求對(duì)象里,而沒(méi)有讓 performView 方法重新創(chuàng)建該Bean,并將新的Bean放在該請(qǐng)求對(duì)象里。我們可以在會(huì)話(huà)里再次使用該Bean。但如果那樣做的話(huà),數(shù)據(jù)將會(huì)過(guò)時(shí)。如果我們?cè)诰庉嬆J较伦隽俗儎?dòng),就需要通知該變化,并在 State 方法里刷新數(shù)據(jù)Bean。為了簡(jiǎn)化這種處理,我們會(huì)只為 MainViewState State 方法里得到數(shù)據(jù) Bean。

所以, MainViewState 類(lèi)里,actionPerformed方法并沒(méi)有另外處理,只是簡(jiǎn)單設(shè)置了MainViewState而已。

子類(lèi)4StateManagerPortlet類(lèi)

當(dāng)actionPerformed 完成處理時(shí),控制返回到門(mén)戶(hù)容器,以便其他的偵聽(tīng)器通知處理程序執(zhí)行。然后,門(mén)戶(hù)容器通過(guò)調(diào)用 StateManagerPortlet service 方法繼續(xù) Portlet 請(qǐng)求處理。

StateManagerPortlet service 方法首先試圖檢索以前執(zhí)行的操作類(lèi)設(shè)置的狀態(tài)類(lèi),如果沒(méi)有發(fā)現(xiàn)狀態(tài)類(lèi)引用例如,最初的 Portlet 調(diào)用),那么就使用一個(gè)助手類(lèi) InitialStateManager 來(lái)為每Portlet 模式確定初始的狀態(tài)類(lèi)。InitialStateManager 有一個(gè)一的方法叫做 getInitialState,它根據(jù) Portlet 的當(dāng)前模式返回狀態(tài)對(duì)象的一個(gè)實(shí)例。對(duì)于下載產(chǎn)品列表 Portlet,這個(gè)類(lèi)將為視圖模式返回 MainViewState 的一個(gè)實(shí)例。

State接口有一個(gè)一的方法 performView,所有的狀態(tài)類(lèi)都必須實(shí)現(xiàn)它。StateManagerPortlet service 方法調(diào)用這個(gè)方法。

子類(lèi)5MainViewState 類(lèi)

MainViewState performView 方法負(fù)責(zé)在 Contacts Bean 的列表表單中獲取下載產(chǎn)品列表,下載產(chǎn)品列表保存在數(shù)據(jù)庫(kù)里,然后傳遞到 JSP 以便在主視圖中呈現(xiàn)出來(lái)。

子類(lèi)6MainViewState 類(lèi)

這個(gè)子類(lèi)允許用戶(hù)單擊一個(gè)下載產(chǎn)品條目,然后顯示該下載產(chǎn)品的詳細(xì)信息視圖。

用于這個(gè)標(biāo)記的 href 使用來(lái)自Portlet標(biāo)記庫(kù)中的createURI標(biāo)記。該標(biāo)記在URIAction中獲得參數(shù),URIAction被我們?cè)O(shè)置為操作類(lèi)中用于用戶(hù)單擊操作的事件處理方法的名稱(chēng)。

子類(lèi)7actionPerformed

actionPerformed類(lèi)用來(lái)查看JSP上顯示的主要清單。用戶(hù)可以從主視圖頁(yè)面選擇特定的下載產(chǎn)品條目來(lái)獲得詳細(xì)信息。我們還添加了一個(gè)錨標(biāo)記將下載產(chǎn)品條目的名稱(chēng)作為可點(diǎn)擊的鏈接顯示出來(lái),當(dāng)點(diǎn)擊時(shí),StateManagerPortletactionPerformed 方法被DetailViewAction 類(lèi)調(diào)用。

actionPerformed方法得到所選擇的下載產(chǎn)品條目的對(duì)象id,并調(diào)用持久性類(lèi)的代理為該id獲取實(shí)例化的下載產(chǎn)品對(duì)象。這個(gè)下載產(chǎn)品對(duì)象放在State類(lèi)的會(huì)話(huà)中,用來(lái)呈現(xiàn)詳細(xì)信息視圖。如果該頁(yè)面由于門(mén)戶(hù)頁(yè)面刷新而得以刷新,那么該Bean就將在會(huì)話(huà)中可用,既然該對(duì)象只會(huì)通過(guò)用戶(hù)使用 Portlet 來(lái)獲得更新,我們就不必?fù)?dān)心數(shù)據(jù)過(guò)時(shí)了。

門(mén)戶(hù)頁(yè)面刷新的另一個(gè)關(guān)鍵之處是表單數(shù)據(jù)沒(méi)有被重新初始化。如果我們?cè)噲D獲得所選下載產(chǎn)品的對(duì)象id作為狀態(tài)類(lèi)的請(qǐng)求參數(shù),它在門(mén)戶(hù)頁(yè)面刷新時(shí)將不可用。因此,為了使 Portlet 能正常運(yùn)行,必須在剛開(kāi)始時(shí)就檢索數(shù)據(jù)元素,然后將其存儲(chǔ)在某個(gè)地方,這樣在隨后的頁(yè)面刷新時(shí)它才可以被引用。由于 actionPerformed 方法曾被調(diào)用,所以這就是存放這段代碼的好地方。

actionPerformed方法中保留后端數(shù)據(jù)訪問(wèn),可以確保我們?cè)陧?yè)面刷新時(shí)對(duì)于同一數(shù)據(jù)不需要多次訪問(wèn)數(shù)據(jù)庫(kù)。當(dāng)然,返回到數(shù)據(jù)源進(jìn)行數(shù)據(jù)刷新的時(shí)間和頻率取決于Portlet的需求,以及數(shù)據(jù)本身的因素。在這種情況下,數(shù)據(jù)不是動(dòng)態(tài)的,當(dāng) Portlet 頁(yè)面被刷新時(shí),應(yīng)該對(duì)其進(jìn)行高速緩存。

,DetailViewState 被設(shè)置為這個(gè)Portlet的下一個(gè)狀態(tài),對(duì)于Portlet,其中的處理將繼續(xù)。

子類(lèi)8DetailViewState 類(lèi)

DetailViewState 簡(jiǎn)單地調(diào)用JSP來(lái)呈現(xiàn)詳細(xì)信息視圖,JSP 從會(huì)話(huà)中獲取下載產(chǎn)品 Bean。在UI交互界面中,當(dāng)用戶(hù)單擊OK按鈕時(shí),處理返回到主視圖繼續(xù)進(jìn)行。MainViewActionactionPerformed 方法通過(guò)刪除我們?cè)?DetailViewAction 類(lèi)中設(shè)置的下載產(chǎn)品對(duì)象 id 來(lái)簡(jiǎn)單地刪除會(huì)話(huà)數(shù)據(jù)。

子類(lèi)9ViewProductAction類(lèi)

ViewProductAction類(lèi)用來(lái)顯示下載產(chǎn)品詳細(xì)信息視圖JSP頁(yè)面。流邏輯以一種組織良好的方式進(jìn)行,你不需要在Portlet使用冗的控制代碼。Portlet 的編輯和配置模式也以同樣的方法實(shí)現(xiàn)。

2完成Portlet實(shí)現(xiàn)

該應(yīng)用程序的其余部分仍遵循以上所述的開(kāi)發(fā)模式。編輯模式的處理控制邏輯流和視圖模式的完全一樣。我們實(shí)現(xiàn)一配置模式,它允許用戶(hù)指定數(shù)據(jù)源來(lái)保存下載產(chǎn)品數(shù)據(jù)。它將以同樣的方式實(shí)現(xiàn)。配置模式只有一個(gè)視圖來(lái)讓用戶(hù)訪問(wèn)數(shù)據(jù)源,另外有兩個(gè)類(lèi)來(lái)檢驗(yàn)數(shù)據(jù)源和保存數(shù)據(jù)源為配置數(shù)據(jù)。

下面是實(shí)現(xiàn)狀態(tài)模式的基本步驟。

  所執(zhí)行的特定模式的初始狀態(tài)類(lèi)由 InitialStateManager 類(lèi)提供。

狀態(tài)類(lèi)的 performView方法其調(diào)用是由 StateManagerPortlet 分派的進(jìn)行任何必要的應(yīng)用程序邏輯處理,然后調(diào)用它的 JSP。

通過(guò)PortletURI上的一個(gè)參數(shù)將每個(gè)用戶(hù)的操作與在其中進(jìn)行事件處理的操作子類(lèi)的名稱(chēng)相關(guān)聯(lián)。每個(gè)用戶(hù)操作一般都指定一個(gè)不同的操作子類(lèi),該子類(lèi)實(shí)現(xiàn)一個(gè)單一的、特定的功能。

當(dāng)用戶(hù)單擊一個(gè)鏈接時(shí),操作類(lèi)的 actionPerformed 方法被調(diào)用由于通過(guò) StateManagerPortlet 分派而被再次調(diào)用。執(zhí)行操作邏輯,并設(shè)置適當(dāng)?shù)臓顟B(tài)類(lèi)以使處理繼續(xù)進(jìn)行。

當(dāng)事件處理完成后,StateManagerPortletservice方法被調(diào)用,并再次分派給在Action事件處理階段設(shè)置的狀態(tài)類(lèi),該狀態(tài)類(lèi)執(zhí)行應(yīng)用程序邏輯并調(diào)用它的 JSP 來(lái)呈現(xiàn)結(jié)果。

當(dāng)用戶(hù)瀏覽整個(gè) Portlet 時(shí),操作以這種方式繼續(xù)。

3持久性代理

訪問(wèn)數(shù)據(jù)庫(kù)中的持久性數(shù)據(jù)需要額外的 Portlet 組件。AbstractBroker 類(lèi)提供一般的JDBC數(shù)據(jù)庫(kù)訪問(wèn)功能。它能夠用來(lái)獲取數(shù)據(jù)庫(kù)的DataSourceConnection;它在高速緩存中緩存DataSource從而避免重復(fù)的、高代價(jià)的JNDI查找;它也提供通用代碼來(lái)執(zhí)行 PreparedStatement,并關(guān)閉Connection、StatementResultSet。

ContactListBroker 類(lèi)繼承了 AbstractBroker,它實(shí)現(xiàn)特定于 Portlet 需要的數(shù)據(jù)訪問(wèn)方法, getContact 方法和 getContactList 方法,用于保存刪除一個(gè)列表中的條目。同時(shí)它還有檢驗(yàn)表 Schema 的功能,這樣我們就可以檢驗(yàn)用戶(hù)在配置模式下指定的數(shù)據(jù)源。

4異常處理

我們已經(jīng)為Portlet 實(shí)現(xiàn)了大量的異常類(lèi),基本類(lèi)AIMException,AIMWrapperExceptionAIMException 的子類(lèi)。可以用 AIMWrapperException 封裝其他拋出的異常,以便在 StateManagerPortletservice 方法中高效地修改顯示行為和管理異常處理。

AIMMessageException 是一個(gè)特殊的異常,它允許在終止處理時(shí)向 Portlet 生成一條報(bào)告性消息或錯(cuò)誤消息。例如,可以?huà)伋鲆粋€(gè) AIMMessage 異常,用一條消息指出用戶(hù)必須先登錄。

actionPerformed方法或setState方法中拋出的異常被捕獲,并且被延遲到 service 方法。管理延遲的方法是捕獲這些方法中拋出的所有異常,并將異常通常封裝在一個(gè)AIMWrapperException放在請(qǐng)求對(duì)象上。當(dāng)調(diào)用StateManagerPortletservice方法時(shí),它首先查找有沒(méi)有延遲異常如果找到了,就從此處重新拋出并處理這些異常。

因此,所有的Portlet應(yīng)用程序異常都是在 StateManagerPortletservice方法中處理的。如果發(fā)現(xiàn)了異常,則在以下兩種情況中調(diào)用異常方法異常消息將在Portlet中被顯示;異常消息以及相關(guān)聯(lián)的堆棧跟蹤信息將被顯示。將堆棧跟蹤信息放在 Portlet 外有助于在開(kāi)發(fā)時(shí)進(jìn)行調(diào)試。由于不想向?qū)嶋H應(yīng)用的用戶(hù)顯示這種級(jí)別的詳細(xì)信息,所以該行為是可配置的。這是在部署描述符里定義的 debugTrace參數(shù)。

5建立開(kāi)發(fā)環(huán)境

如果使用WebSphere Studio來(lái)創(chuàng)建這個(gè)Portlet,請(qǐng)確保下列JAR文件構(gòu)建路徑是可用的,以便Portlet代碼可以順利編譯。如果Studio中使用Portal Toolkit并創(chuàng)建Portlet應(yīng)用項(xiàng)目,那么類(lèi)路徑會(huì)自動(dòng)創(chuàng)建。不管哪種情況,你都可以創(chuàng)建一個(gè)Web項(xiàng)目或Portlet應(yīng)用項(xiàng)目,然后導(dǎo)入下載中的WAR文件,從而將這個(gè)Portlet應(yīng)用程序載入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

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

當(dāng)Portlet部署到WebSphere Portal 環(huán)境中時(shí),所有必需的JAR文件都要同時(shí)打包進(jìn)去。可以不修改, Portal 中安裝 Portlet WAR 文件。

1.3.5  RAD實(shí)現(xiàn)Portlet

針對(duì)入門(mén)者,我們以圖示的方式,向大家介紹使用IBM提供的開(kāi)發(fā)工具RADRational Application Developer)來(lái)創(chuàng)建、開(kāi)發(fā)、調(diào)試、打包Portlet。

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

1.安裝RAD,創(chuàng)建portlet

Windows 2003 Server系統(tǒng)的“控制面板”高級(jí)”選項(xiàng)中,設(shè)置”按鈕,在出現(xiàn)的對(duì)話(huà)框中選擇數(shù)據(jù)執(zhí)行保存面板,添加...按鈕,把安裝后的rationalsdp.exeenroll.exe 添加到列表中。

打開(kāi)RAD,單擊“新建”按鈕,選擇“項(xiàng)目”→“Portlet項(xiàng)目”,然后依次輸入各項(xiàng)參數(shù),包括Portlet的名稱(chēng)、包名、是否使用憑證保險(xiǎn)庫(kù)等。

參數(shù)                           

Portlet 名稱(chēng)                                   DownLoadConfig

Portlet 類(lèi)型                                   基本Portlet

Web功能部件                使用Web圖與JSP標(biāo)記庫(kù)

是否需要添加操作偵聽(tīng)實(shí)例              不需要

是否需要添加憑證保險(xiǎn)庫(kù)                 不需要

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

單擊“完成”按鈕,Rational開(kāi)始自動(dòng)創(chuàng)建這個(gè)Portlet,創(chuàng)建完成后自動(dòng)打開(kāi)“DownLoadConfigView.jsp”文件,如圖1-10所示。


基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-10  RAD中開(kāi)發(fā)Portle


2.創(chuàng)建并設(shè)計(jì)所需的操作類(lèi)(Actions


創(chuàng)建一個(gè)Action包:com.ibm.csdl.portal.download.config.actions,在這個(gè)包里分別創(chuàng)建以下類(lèi),如圖1-11所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-11  創(chuàng)建的操作類(lèi)

這些類(lèi)實(shí)現(xiàn)了Portlet的所有操作,我們以“為產(chǎn)品配置刪去一個(gè)CD或者E-mail”為例,看一下Action實(shí)現(xiàn)了哪些功能。

actionPerformed方法里,程序接收從editAProduct.jsp傳過(guò)來(lái)的參數(shù),也就是CDsEmails兩個(gè)選擇框傳過(guò)來(lái)的值,看要?jiǎng)h除的是一個(gè)CD還是一個(gè)E-mail,然后從產(chǎn)品配置對(duì)象里面將對(duì)應(yīng)的CD或者E-mail刪除,最后寫(xiě)回到XML文件中。

setState()方法里,程序?qū)嵗粋€(gè)RemoveOneCDsOrEmailState,將邏輯交給State來(lái)處理。那么,State又如何流轉(zhuǎn)呢?看下面的State類(lèi)。

3.創(chuàng)建并開(kāi)發(fā)所需的狀態(tài)類(lèi) (States)

  創(chuàng)建一個(gè)State包:com.ibm.csdl.portal.download.config.actions,在這個(gè)包里分別創(chuàng)建以下類(lèi),如圖1-12所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-12  創(chuàng)建的狀態(tài)類(lèi)

這些類(lèi)實(shí)現(xiàn)了Portlet的所有狀態(tài)模式轉(zhuǎn)換,我們以“為產(chǎn)品配置刪去一個(gè)CD或者E-mail”為例,看一下State實(shí)現(xiàn)了哪些功能。

RemoveOneCDsOrEmailState.java代碼清單如下:

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

State類(lèi)里面只有兩個(gè)方法,其中一個(gè)方法用于獲得實(shí)例,我們就不管了;另一個(gè)方法是performView,它負(fù)責(zé)讀出XML文件里的內(nèi)容(現(xiàn)在已經(jīng)是修改后的了),然后放入Session,調(diào)用并初始化一個(gè)新的指定的JSP文件。這個(gè)JSPSession里面取出數(shù)據(jù),然后初始化。

4.創(chuàng)建并開(kāi)發(fā)所需的數(shù)據(jù)結(jié)構(gòu)(Data)以及Portlet類(lèi)

Data類(lèi)主要定義了一些數(shù)據(jù)結(jié)構(gòu),用來(lái)存放XML文件中的數(shù)據(jù),與Portlet的開(kāi)發(fā)基本上無(wú)關(guān)。

Portlet類(lèi)主要用來(lái)初始化一些數(shù)據(jù),以及根據(jù)Portlet的狀態(tài)調(diào)用相應(yīng)的JSP頁(yè)面。


nls下的資源文件與瀏覽器的多語(yǔ)言支持相關(guān),可以根據(jù)客戶(hù)端瀏覽器的設(shè)置,從相應(yīng)的資源里取出靜態(tài)描述文件Portlet.xml,然后在JSP文件中完成初始化的過(guò)程。

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

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-13  com.ibm.csdl.portal.download.config.utilities中默認(rèn)帶有常見(jiàn)的異常處理邏輯

5.創(chuàng)建并開(kāi)發(fā)所需的頁(yè)面(Pages

根據(jù)上面的詳細(xì)設(shè)計(jì),我們需要?jiǎng)?chuàng)建一些頁(yè)面,如圖1-14所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-14  創(chuàng)建的頁(yè)面

這些頁(yè)面的功能如下。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

頁(yè)面的顯示邏輯略。我們以ViewAllTheProduct.jsp為例,看一下Rational是怎樣給一個(gè)鏈接添加操作事件偵聽(tīng)的。

ViewAllTheProduct.jsp源代碼如下:


基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

其實(shí)很簡(jiǎn)單,用一個(gè)超鏈接就能添加該鏈接的操作事件偵聽(tīng),代碼如下:

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

其他的類(lèi)似,這里不再贅述。

6.調(diào)試 Portlet

 假設(shè)在9.181.66.250上運(yùn)行著一個(gè)Portal系統(tǒng),超級(jí)管理員的用戶(hù)名和密碼都是admin,我們可以創(chuàng)建一個(gè)服務(wù)器用來(lái)測(cè)試Portlet,如圖1-15所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-15  RAD中創(chuàng)建Portal服務(wù)器用于調(diào)試Portlet

選擇服務(wù)器的類(lèi)型為WebSphere Portal,并輸入相關(guān)參數(shù)。

右擊項(xiàng)目名,選擇“運(yùn)行”→“在服務(wù)器上運(yùn)行”,如圖1-16所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-16  選擇直接在RAD中運(yùn)行Portlet

 幾分鐘后,會(huì)在工作區(qū)出現(xiàn)瀏覽頁(yè)面,這樣就可以調(diào)試該Portlet了。

7.打包,生成產(chǎn)品

打包Portlet也非常簡(jiǎn)單,右擊項(xiàng)目名,選擇“導(dǎo)出”→“WAR文件”,再選擇好存儲(chǔ)位置就可以了,如圖1-17所示。

基于事件偵聽(tīng)與狀態(tài)模式轉(zhuǎn)換的Portlet開(kāi)發(fā)

1-17  Portlet導(dǎo)出為WAR包部署到Portal服務(wù)器

拿這個(gè)WAR包,就可以發(fā)布或者更新到Portal系統(tǒng)上使用了。

1.4  Portlet 開(kāi)發(fā)指導(dǎo)原則和示例實(shí)現(xiàn)

Portlet 開(kāi)發(fā)指導(dǎo)原則和示例實(shí)現(xiàn)可以對(duì)Portlet API很好的理解。然而,實(shí)現(xiàn)復(fù)雜的流程控制超出了 API 的范圍。如果沒(méi)有定義完善的方法來(lái)解決如何最好地實(shí)現(xiàn)控制邏輯這一問(wèn)題,你就不能夠創(chuàng)建這樣的Portlet它們包含有專(zhuān)門(mén)定位用戶(hù)請(qǐng)求目的的簡(jiǎn)單合理的 代碼。

除了重復(fù)之外,該代碼使Portlet更難以讀懂,因?yàn)?/span>需要進(jìn)入控制邏輯以獲取Portlet正在做的實(shí)際工作??刂七壿嬕踩菀壮鲥e(cuò),因?yàn)樗蕾?lài)于多方面情況,比如,使用字符串匹配用來(lái)連接事件和偵聽(tīng)器,偵聽(tīng)器操作和 Portlet 方法中的Action。為了解決控制邏輯的這些問(wèn)題,你可以將應(yīng)用程序看Portlet的操作和狀態(tài)的集合,然后通過(guò)一個(gè)定義完善的方法來(lái)進(jìn)行狀態(tài)轉(zhuǎn)換,這樣就可以將Portlet應(yīng)用程序中冗的控制邏輯代碼刪除。

開(kāi)發(fā)人員也可以選擇采用Struts框架來(lái)實(shí)現(xiàn)Portlet。Struts是一個(gè)Jakarta項(xiàng)目,它提供一個(gè)非常流行的開(kāi)放源代碼框架來(lái)建立 Web 應(yīng)用程序。使用附帶了 Portal Struts Portlet Framework,Struts框架寫(xiě)成的Portlet就可以在WebSphere Portal上運(yùn)行。Struts提供了值得考慮的Web應(yīng)用程序,其功能遠(yuǎn)遠(yuǎn)超過(guò)頁(yè)面導(dǎo)航,它是進(jìn)行Portlet開(kāi)發(fā)的一個(gè)很好的選擇。對(duì)Struts不熟悉或者希望更直接訪問(wèn) Portlet API 的開(kāi)發(fā)人員會(huì)從用于頁(yè)面導(dǎo)航的狀態(tài)轉(zhuǎn)換實(shí)現(xiàn)中獲益。這種模式和Struts框架一樣,使面向MVC設(shè)計(jì)的應(yīng)用程序框架得以改進(jìn)。



向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI