我的Blog我做主^_^

          走向一條通往JAVA的不歸路...

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            64 隨筆 :: 68 文章 :: 77 評論 :: 0 Trackbacks
          作者:Sunil Patil; observer
          原文地址: http://www.onjava.com/pub/a/onjava/2005/10/19/challenging-java-dominance.html
          中文地址: http://www.matrix.org.cn/resource/article/44/44029_Portlet.html
          關鍵詞: Portlet Java


          Portlets
          “Portlets是一種Web組件-就像servlets-是專為將合成頁面里的內容聚集在一起而設計的。通常請求一個portal頁面會引發(fā)多個portlets被調用。每個portlet都會生成標記段,并與別的portlets生成的標記段組合在一起嵌入到portal頁面的標記內。”(摘自Portlet規(guī)范,JSR 168)

          本文探討了以下內容:
          1.????????Portal頁面的元素
          2.????????Portal是什么?
          3.????????Portlets是什么?
          4.????????開發(fā)“Hello World” Portlet
          5.????????在Pluto上部署HelloWorld Portlet
          6.????????如何創(chuàng)建Portal頁面
          7.????????結束語
          8.????????資源


            Portlet規(guī)范將portlet定義為一種“基于Java技術的web組件,由處理請求和生成動態(tài)內容的portlet容器管理”。這段話聽起來是不是有些費解?本文將說明portlets是什么以及能用它們做什么。


          圖1顯示了在訪問一個portal服務器時瀏覽器中頁面的樣子。

          image
          圖1 典型的portal服務器的頁面(點擊查看原圖)

            如果仔細查看瀏覽器里的頁面,就會看到頁面是由不同的“窗口”組成的。一個窗口用于刷新天氣,另一個用于新聞,還有一個用于刷新股價,等等。這里的每一個窗口都代表了一個portlets。如果看得再仔細些,還會發(fā)現(xiàn)每個窗口都有一個標題條和一些按鈕,包括最小化和最大化按鈕。

            在系統(tǒng)里,這些窗口是相互獨立開發(fā)、各不同的應用。新聞portlet的開發(fā)者創(chuàng)建應用并打包成war格式的文件,隨后portal服務器的管理員在服務器上部署該war文件并創(chuàng)建頁面,接下來每個用戶會選擇在他的頁面里有哪些應用。例如,如果用戶對股價不感興趣而對體育感興趣,他可以用“體育”窗口替換“股價”窗口。

            Portlet技術需要學習許多新概念,本文不可能全都涵蓋,因此本文分為兩部分。在第一部分里我們詳細說明portals和portlets,并開發(fā)一個簡單的“Hello World”portlet;在第二部分我們將探討一些高級主題。

            我們將用Apache的Pluto服務器(Portlet API 1.0規(guī)范的參考實現(xiàn))來測試我們的示例portlets,我們還會花些時間探討如何安裝和使用Pluto服務器。

          Portal頁面的元素

          圖2顯示了Portal頁面的各種元素。

          image
          圖2 portal頁面的元素

            每個portlet頁面由一個或多個portlet窗口組成,每個portlet窗口又分為兩部分:一個是外觀,它決定了portlet窗口的標題條、控制和邊界的樣式;另一個是portlet段,它由portlet應用填充。

            Portal服務器決定了portal頁面的整體觀感,像標識、標題條顏色、控制圖標等。通過修改幾個JSP和css模板文件就可以改變portal的整個觀感。我們將在“如何創(chuàng)建portal頁面”部分對此做深入討論。

          Portal是什么?

            在了解portlet之前有必要先了解portal。在Portlet規(guī)范里是這樣講的:“portal是一種web應用,通常用來提供個性化、單次登錄、聚集各個信息源的內容,并作為信息系統(tǒng)表現(xiàn)層的宿主。聚集是指將來自各個信息源的內容集成到一個web頁面里的活動”。

            Portal的功能可以分為三個主要方面:
          1.????????Portlet容器:Portlet容器與servlet容器非常類似,所有的portlet都部署在portlet容器里,portlet容器控制portlet的生命周期并為其提供必要的資源和環(huán)境信息。Portlet容器負責初始化和銷毀portlets,向portlets傳送用戶請求并合成響應。
          2.????????內容聚集:Portlet規(guī)范中規(guī)定portal的主要工作之一是聚集由各種portlet應用生成的內容,我們將在“如何創(chuàng)建Portal頁面”部分對此做進一步討論。
          3.????????公共服務:portlet服務器的一個強項是它所提供的一套公共服務。這些服務并不是portlet規(guī)范所要求的,但portal的商業(yè)實現(xiàn)版本提供了豐富的公共服務以有別于它們的競爭者。在大部分實現(xiàn)中都有望找到的幾個公共服務有:
          ???????? o 單次登錄:只需登錄portal服務器一次就可以訪問所有其它的應用,這意味著你無需再分別登錄每一個應用。例如一旦我登錄了我的intranet網站,我就能訪問mail應用、IM消息應用和其它的intranet應用,不必再分別登錄這些應用。
            Portal服務器會為你分配一個通行證庫。你只需要在mail應用里設定一次用戶名和密碼,這些信息將以加密的方式存儲在通行證庫中。在你已登錄到intranet網站并要訪問mail應用的時候,portal服務器會從通行證庫中讀取你的通行證替你登錄到mail服務器上。你對其它應用的訪問也將照此處理。
          ??????????o個性化:個性化服務的基本實現(xiàn)使用戶能從兩方面?zhèn)€性化她的頁面:第一,用戶可以根據她的自身喜好決定標題條的顏色和控制圖標。第二,用戶可以決定在她的頁面上有哪些portlets。例如,如果我是個體育迷,我可能會用一個能提供我鐘愛球隊最新信息的portlet來取代股票和新聞portlets。
          ??????  一些在個性化服務方面領先的商業(yè)實現(xiàn)版本允許你建立為用戶顯示什么樣的應用所依據的標準(如收入和興趣)。在這種情況下,可以設定一些像“對任何收入為X的用戶顯示饋贈商品的portlet”和“對任何收入為X的用戶顯示打折商品的portlet”這樣的商業(yè)規(guī)則。

            ??????此外還有一些公共服務,比如機器翻譯,是由portal服務器將portlet生成的內容翻譯為用戶要求的語言。大部分的商業(yè)portal服務器都支持手持設備訪問并具有針對不同的瀏覽終端生成不同內容的能力。

          Portlets是什么?

            與servlets類似,portlets是部署在容器內用來生成動態(tài)內容的web組件。從技術角度講portlet是一個實現(xiàn)了javax.portlet.Portlet接口的類,它被打包成war文件格式部署到portlet容器里。

            Portlets在以下方面與servlets相似:
          1.????????portlets由特定的容器管理。
          2.????????portlets生成動態(tài)內容。
          3.????????portlet的生命周期由容器管理。
          4.????????portlets通過請求/響應模式與web客戶端交互。

            Portlets在以下方面與servlets相異:
          1.????????portlets只能生成標記段,而不是整個文檔。
          2.????????portlets沒有可供直接訪問的URL地址。不過你還是能夠讓別人通過URL訪問到portlet,你可以把包含該portlet的頁面的URL發(fā)給他。
          3.????????portlets不能隨意地生成內容,這是因為portlet生成的內容最終要成為portal頁面的一部分。如果portal服務器要求的是html/text類型,那么所有的portlets都應生成html/text類型的內容。再比方說,如果portal服務器要求的是WML類型,那么所有的portlets都應生成WML類型的內容。

            portlets還提供了一些附加的功能:
          1.????????設置參數(shù)的持久化存儲:portlets提供了一個PortletPreferences對象用來保存用戶的設置參數(shù)。這些參數(shù)被存入一個持久化數(shù)據庫,這樣服務器重啟后數(shù)據依然有效。開發(fā)者不必關心這些數(shù)據存儲的具體實現(xiàn)機制。
          2.????????請求處理:portlets提供了更為細粒度的請求處理。對于用戶在portlet上動作時向該portlet發(fā)出的請求(一種稱為活躍期的狀態(tài)),或者因用戶在其它portlet上動作而引發(fā)的刷新頁面請求,Portal服務器提供了兩種不同的回調方法來處理。
          3.????????Portlet模式:portlets用模式的概念來表示用戶在做什么。在使用mail應用的時候,你可能會用它來讀信、寫信或檢查信件――這些都是mail應用的預定功能,Portlets通常以VIEW模式提供這些功能。但還有一些活動,像指定刷新時間或(重新)設置用戶名和密碼,這些活動允許用戶定制應用的行為,因此它們用的是EDIT模式。Mail應用的幫助功能用的是HELP模式。

            如果仔細想想其實這里面并沒有什么新東西,它們反而大部分都是普通的業(yè)務需求。Portlet規(guī)范的作用在于它提供了一個抽象層,這才是它對所有與之相關的人-最終用戶、開發(fā)者和管理員-的價值所在。

            作為一個開發(fā)者,我會將所有與VIEW模式有關的業(yè)務邏輯放入doView()方法,將與應用配置有關的業(yè)務邏輯放入doEdit()方法,將與幫助有關的邏輯放入doHelp()方法

            這就簡化了管理員對portlet應用的訪問控制管理,因為他只需改變portlet的訪問權限就能決定用戶能做什么。例如,如果mail應用的一個用戶能夠在EDIT模式下設定用戶名和密碼,那么就可以斷定他具有EDIT模式訪問權限。

            不妨考慮這樣一種情形:我是一個intranet網站的管理員,我的公司買了一個能顯示新聞信息的第三方portlet應用,該應用允許用戶指定跟蹤新聞更新的URL地址,我想借助它為用戶顯示公司的內部新聞。另一個需求是我不想讓用戶通過該應用來跟蹤任何其它的新聞信息來源。作為管理員,我可以為所有的用戶指定一個用于內部新聞更新的URL地址,同時通過改變portlet應用的部署描述符來取消其它人修改該地址的權限。

            由于所有的portlet應用都具有相似的UI界面,因此采用portlets可使網站對最終用戶更具吸引力。如果她想閱讀任何一個應用的幫助信息,她可以點擊幫助按鈕;她也知道點擊編輯按鈕能讓她進入應用的配置屏。標準化的用戶界面使你的portlet應用更引人。

          4.????????窗口狀態(tài):窗口狀態(tài)決定了portal頁面上留給portlet生成內容的空間。如果點擊最大化按鈕,portlet將占據整個屏幕,成為用戶唯一可用的portlet;而在最小化狀態(tài),portlet只顯示為標題條。作為開發(fā)者應當根據可用空間的大小來定做內容。

          5.????????用戶信息:通常portlets向發(fā)出請求的用戶提供個性化的內容,為了能更加行之有效,portlets需要訪問用戶的屬性信息,如姓名、email、電話等。Portlet API為此提供了用戶屬性的概念,開發(fā)者能夠用標準的方式訪問這些屬性,并由管理員負責在這些屬性與真實的用戶信息數(shù)據庫(通常是LDAP服務器)之間建立映射關系。

            我們將在本文的第二部分深入討論這些特點-請求處理、用戶信息和portlet模式。

          開發(fā)"Hello World" Portlet

            現(xiàn)在我們就來開發(fā)一個簡單的HelloWorld portlet。
          1.????????創(chuàng)建一個名為HelloWorld的web項目,它與通常的servlet項目類似,有一個/WEB-INF/web.xml文件作為項目的部署描述符。

          2.????????在build path里加入portlet-api-1.0.jar文件,該jar文件是Pluto發(fā)行包的一部分。

          3.????????在Source文件夾中按如下內容創(chuàng)建HelloWorld.java文件:
          				public class HelloWorld extends GenericPortlet{
          ??protected void doView(RenderRequest request,
          ??RenderResponse response) throws
          ??PortletException, IOException {
          ????????response.setContentType("text/html");
          ????????response.getWriter().println("Hello Portlet");
          ????????}
          }


            每個portlet都要實現(xiàn)Portlet接口,該接口為portlet定義了生命周期方法。由于不想覆蓋所有這些方法,我們只對GenericPortlet類進行擴展,它是一個實現(xiàn)了Portlet接口的適配器類。GenericPortlet類提供了所有生命周期方法的默認實現(xiàn),所以我們只需實現(xiàn)我們所需要的方法。

            我們在 HelloWorld portlet里要做的只是顯示“Hello Portlet”,所以我們將覆蓋GenericPortlet類的doView()方法,該方法以PortletRequest 和 PortletResponse作為參數(shù)。在doView()方法中首先調用response.setContentType()以通知portlet容器該portlet將要生成何種類型的內容-如果不這樣做就會導致IllegalStateException異常。一旦設置了內容的類型,就可以從response對象中獲得PrintWriter并開始寫入。

          4.????????每個portlet應用在/WEB-INF文件夾中都有一個portlet.xml文件,它是portlet應用的部署描述符。按以下內容創(chuàng)建portlet.xml文件:
          				<portlet>
          ??<description>HelloWorldDescription
          ????????</description>
          ????<portlet-name>HelloWorld
          ????????</portlet-name>
          ????<display-name>Hello World
          ????????</display-name>

          ????<portlet-class>com.test.HelloWorld
          ????????</portlet-class>
          ????<expiration-cache>-1
          ????????</expiration-cache>
          ????????<supports>
          ??????????<mime-type>text/html</mime-type>
          ??????<portlet-mode>VIEW
          ??????????</portlet-mode>
          ????????</supports>
          ????<supported-locale>en
          ????????</supported-locale>

          ????????<portlet-info>
          ??????????<title>Hello World</title>
          ??????????<short-title>Hello World
          ??????????</short-title>
          ??????????<keywords>Hello,pluto</keywords>
          ??????</portlet-info>
          </portlet>


            <portlet-name>元素聲明了portlet的名字,<portlet-class>元素指定了portlet的全限定類名,<expiration-cache>元素以秒為單位指定了內容超期的時間。這里面有一點需要注意:你在portlet上的某些動作可能會導致內容刷新,這與緩存時間無關。
            <supports>元素指定對于給定的<mime-type>有哪些模式可供支持。在示例中我們假定HelloWorld只能生成text/html類型的內容,且只有view模式可支持該內容類型。如果要增加對其它內容類型的支持,需要添加新的<support>元素并指定支持該MIME類型的模式有哪些。通常portlet對于text/html類型有VIEW、EDIT和HELP模式可供支持,而對于WML MIME類型則只有VIEW模式。
            還可以用<supported-locale>元素來指定portlet支持哪些本地化。<title>元素用來指定portlet的標題。如果要對標題做國際化處理,可以用元素<resource-bundle>指定資源(比例properties文件)的文件名。在這種情況下,容器將根據用戶所在的地區(qū)從適當?shù)膒roperties文件中選擇標題。

          5.????????每個portlet應用都是一個web應用,因此除了portlet.xml文件之外還需要有web.xml文件。
          				<web-app>
          ??<display-name>Hello World Portlet
          ??</display-name>
          ??<welcome-file-list
          ????<welcome-file>index.jsp
          ????????</welcome-file>
          ??</welcome-file-list>
          </web-app>


          6.????????接下來將這些文件進行編譯并打包為war文件。你可以自己完成這些工作,或者下載帶有build.xml 的示例代碼(參見“資源”部分)來創(chuàng)建war文件。
          在Pluto上部署HelloWorld Portlet

            Pluto尚處于開發(fā)階段的早期,因此還沒有一套易于使用的管理工具。為了能使用Pluto服務器,需要將編譯和源代碼兩個版本都下載。需要注意的是以下說明是針對Windows平臺的,Unix用戶通過修改斜杠符號和執(zhí)行sh shell腳本(不是bat批命令文件)會得到類似的結果。

          1.????????創(chuàng)建一個文件夾,比如C:\PlutoInstallation。
          2.????????從Pluto的網站下載pluto-1.0.1-rc1.zip和pluto-src-1.0.1-rc1.zip。
          3.????????將pluto-1.0.1-rc1.zip解壓到C:\PlutoInstallation.文件夾,它應被解壓到C:\PlutoInstallation\pluto-1.0.1-rc1文件夾下。
          4.????????執(zhí)行C:\PlutoInstallation\pluto-1.0.1-rc1\bin\startup.bat啟動Pluto,現(xiàn)在可以通過地址http://localhost:8080/pluto/portal訪問Pluto服務器。
          5.????????將pluto-src-1.0.1-rc1.zip解壓到C:\PlutoInstallation\PlutoSrc文件夾。
          6.????????進入C:\PlutoInstallation\PlutoSrc文件夾,執(zhí)行maven distribute:all.,編譯并下載運行常規(guī)管理任務所必需的相關資源文件。現(xiàn)在可以將HelloWorldPortlet.war作為portlet進行安裝了。
          7.????????首先將HelloWorldPortlet.war文件拷貝到C:\PlutoInstallation\portlets目錄,如果沒這個目錄就創(chuàng)建它。
          8.????????將C:\PlutoInstallation\plutosrc\build.properties.sample更名為build.properties。
          9.????????編輯build.properties,將maven.tomcat.home指向Pluto編譯版的安裝位置,在本例中應改為maven.tomcat.home=C:/PlutoInstallation/pluto-1.0.1-rc1。
          10.????????為了安裝portlet,進入C:\plutoInstallation\plutosrc\deploy文件夾,執(zhí)行maven deploy -Ddeploy=c:\PlutoInstallation\portlets\HelloWorldPortlet.war,應能看到“build successful”信息。
          11.????????在C:\PlutoInstallation\pluto-1.0.1-rc1\webapps文件夾下,應該有一個HelloWorldPortlet文件夾。
          12.????????現(xiàn)在進入C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\HelloWorld\WEB-INF\ folder文件夾,打開portlet的web.xml文件,你會發(fā)現(xiàn)里面自動多了幾行,如下所示:
          				<servlet>
          ??<servlet-name>HelloWorld</servlet-name>
          ???? <display-name>HelloWorld Wrapper</display-name>
          ??????<description>Automated generated
          ??????Portlet Wrapper</description>
          ??????<servlet-class>org.apache.pluto.core.PortletServlet
          ??????</servlet-class>
          ??????<init-param>
          ???????? <param-name>portlet-class</param-name>
          ???????? <param-value>com.test.HelloWorld
          ???????? </param-value>
          ??????</init-param>
          ??????<init-param>
          ???????? <param-name>portlet-guid</param-name>
          ???????? <param-value>HelloPluto.HelloWorld
          ???????? </param-value>
          ??????</init-param>
          </servlet>

          13.????????接下來我們將該portlet加到頁面里。進入C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\pluto\WEB-INF\data文件夾,可以看到有兩個XML文件:pageregistry.xml和portletentityregistry.xml。
          14.????????portletentityregistry.xml包含了portlet的定義,在該文件中加入以下幾行:
          				 <application id="5">
          ?? <definition-id>HelloWorld</definition-id>
          ???? <portlet id="1">
          ?????? <definition-id>HelloWorld.HelloWorld</definition-id>
          ???? </portlet>
          </application>

            應用的<definition-id>應為web應用所在文件夾的名字,portlet的<definition-id>應與web.xml中生成的portlet-guid相一致。
          15.????????pageregistry.xml定義了頁面中包含了哪些portlets,對該文件做如下改動:
          				??<fragment name="p2" type="portlet">
          ????<property name="portlet" value="5.1"/>
          </fragment>

          16.????????執(zhí)行shutdown命令和startup命令重啟Pluto服務器,返回到地址http://localhost:8080/pluto/portal并點擊“Test Link”-此時頁面中將出現(xiàn)我們的

          HelloWorld portlet。

          圖3的右側顯示了HelloWorld portlet看上去的樣子。

          image
          圖3 portlet的屏幕截圖

          如何創(chuàng)建Portal頁面

          圖4顯示了portal容器如何將分離的portlets組裝為頁面。

          image
          圖4 創(chuàng)建Portal頁面

            大部分的portal服務器基本上都是部署于應用服務器上的web應用,通過servlet來處理訪問portal服務器的請求。查看一下Pluto的安裝目錄就會發(fā)現(xiàn)Pluto不過是一個部署于Tomcat服務器上的一個普通web應用,再看看C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\pluto\WEB-INF\web.xml會發(fā)現(xiàn)所有發(fā)往Pluto服務器的請求都被映射到org.apache.pluto.portalImpl.Servlet上。

            在本文開始部分“Portal頁面的元素”中,我們提到portal頁面由兩部分組成。一部分是由頁面中的portlets生成的內容,另一部分是由portal服務器生成的內容。

            在Pluto里,只要用戶發(fā)出請求,就會由servlet進行控制,根據用戶所請求的頁面來確定需要顯示的portlets的列表。一旦生成了列表,servlet就將控制轉給這些portlets線程并收集由它們生成的內容。

            對于由portal服務器生成的內容(像portal網站的觀感及每個portlet的外觀和控制之類)則取決于C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\pluto\WEB-INF\aggregation文件夾下的JSP文件。RootFragment.jsp是主JSP文件,它決定了整體的觀感和對齊方式;它還包含了Heads以定義在生成的頁面中的<HEAD>標簽里的內容。TabNavigation.jsp用來選擇在banner中該顯示什么(默認情況下在banner顯示列表中也包擴了pluto.png圖片)。TabNavigation.jsp用來確定portal網站的導航方案。這意味著只需改動該文件夾下少量的幾個JSP文件,就能改變整個portal網站的觀感。

            Pluto根據pageregistry.xml中的設置確定頁面中有多少行,并用RowFragment.jsp去填充。ColumnFragment.jsp用來填充每個欄目。PortletFragmentHeader.jsp用來填充每個portlet的頁頭,像標題條及最大化和最小化控制。footer.jsp用來填充JSP的頁腳。如果去看一下portal頁面的HTML代碼就會發(fā)現(xiàn)每個portlet窗口無非都是嵌入<TD>標簽的內容塊。

          結束語

            任何一種新技術要想獲得成功都應具備以下條件:首先,它能提升現(xiàn)有技術;其次,它能解決現(xiàn)有技術遇到的普遍問題;再次,它能提供多于一個的抽象層(有人說,每抽象出一層,問題就解決一半)。

            由于portlet與現(xiàn)有的應用服務器架構兼容,這對Portlet API來說是一次發(fā)展servlet技術的好機會。你可以從portlet里調用EJB,或者用它啟動和參與由應用服務器控制的全局性事務。換句話說,在以商業(yè)邏輯為核心的領域里,portlet完全可以做得和servlet一樣好。

            Portlets提供了一個抽象層,現(xiàn)在你不必再擔心客戶端使用了什么樣的HTTP方法,也不必自己編寫程序去捕獲像點擊按鈕這樣的客戶端事件。最后但絕不是最次要的一點是,portlets以提供像單次登錄、個性化等服務的方式解決了servlets不能解決的大部分問題。

          資源
          ·
          本文的示例代碼
          ·JSR 168的首頁:http://www.jcp.org/en/jsr/detail?id=168
          ·Pluto的首頁:http://portals.apache.org/pluto/
          ·onjava.com:
          onjava.com
          ·Matrix-Java開發(fā)者社區(qū): http://www.matrix.org.cn


          Sunil Patil從事J2EE技術工作已有5年,他感興趣的領域包括對象關系映射工具、UI框架以及portals。


          posted on 2007-03-09 08:37 java_蟈蟈 閱讀(291) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網站導航:
           
          主站蜘蛛池模板: 洛南县| 榕江县| 万源市| 江孜县| 成都市| 浦东新区| 两当县| 西平县| 巴塘县| 瑞丽市| 自贡市| 临沭县| 浦江县| 托克托县| 仪征市| 于田县| 衡南县| 牙克石市| 渭南市| 弋阳县| 集安市| 松潘县| 喀喇沁旗| 个旧市| 文水县| 枝江市| 崇信县| 吉安市| 玉树县| 巴彦淖尔市| 叶城县| 永济市| 新田县| 丹江口市| 井陉县| 启东市| 荃湾区| 高邑县| 玉屏| 柯坪县| 北流市|