<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    kapok

    垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      455 隨筆 :: 0 文章 :: 76 評論 :: 0 Trackbacks
    http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0312_hepper/hepper.html?ca=dwcn-newsletter-wsdd

    級別: 中級

    Stefan Hepper
    架構師,Websphere Portal Server Development, IBM
    2004 年 2 月

    本文詳細說明了 Java TMJava TMStandardization Request for the Java Portlet 規范(以下稱為 JSR 168)和 IBM WebSphere Portal Version 5.0 支持的 IBM Portlet API之間的相似點和不同點。文中解釋了 JSR 168 的一些基本概念和特征,并將它們與 IBM Portlet API 進行了比較,并且為兩個 Portlet 編程接口中的每一個都提供了一個示例 Portlet。本文是為那些對 Java 編程、Servlet 或Portlet 編程有良好理解并具備 portal 方面的基本知識的 Portlet 開發人員和 Portal 架構師準備的。

    引言

    隨著越來越多的企業Portal 的出現,不同的廠商已經創建了各種用于 Portal 組件的 API(稱為 Portlet)。存在多種不兼容的接口產生了應用程序提供者、Portal 消費者和Portal 服務器廠商之間的問題。Java Community Process(JCP)定義的Java Portlet 規范(JSR 168)提供了 Portlet 和 Portal之間的互操作性的標準。它將及時解決這些問題。

    本文檔的目的是比較 JSR 168 和 WebSpherePortal V5.0 Portlet API,并且給出了一些示例。

    重要:為了給顧客和合作伙伴提供一個方便的移植窗口,WebSphere Portal的下一個版本仍將支持 IBM Portlet API。

    JSR168 簡介

    Java Standardization Request 168(JSR 168)定義了一個Portlet規范,包括 Portlet 容器和 portlet 之間的合約。JSR 168 是由Java Community Process(JCP)定義的。JSR 168 是由 IBM 和 Sun共同領導的,并且有一個很大的 Expect Group以幫助創建目前可用的最終版本。這個專家組由 Apache Software Foundation、Art Technology Group Inc.(ATG)、BEA、Boeing、Borland、Citrix Systems、Fujitsu、Hitachi、IBM、Novell、Oracle、SAP、SAS Institute、Sun、Sybase、Tibco和 Vignette 組成。關于這個 JSR 的更多信息可以在 http://jcp.org/en/jsr/detail?id=168上找到。

    重要:在本分析中提供的信息不承擔任何性質的保證之責。本分析旨在為讀者提供一個指示性的工具。

    JSR 168定義

    這部分提供了基本的 JSR 168定義,目的是幫助您理解 JSR 168 如何融入整個 Portal體系結構中。

    Portal 和 Portlet 容器

    portal是一個 Web應用程序,它通常提供不同來源的個性化、單點登錄的內容集合,并且托管不同后端系統的表示層。

    Portal的主要任務是將不同的應用程序集合到一個頁面,這個頁面的外觀是Portal 用戶共有的。Portal也可以有復雜的個性化特征,這些特征能夠給用戶提供自定義內容。Portal頁可以有不同的 Portlet 集,以便為不同的用戶創建內容。

    圖1展示了 Portal 的體系結構,比如一個由 WebSphere Portal 提供服務的Portal。客戶端請求由 PortalWeb 應用程序進行處理,它為當前用戶檢索當前頁上的 Portlet。然后,Portal Web應用程序為每個 Portlet 調用 Portlet 容器來通過 Container Invoker API 檢索它的內容。Portlet 容器通過 Portlet API 調用Portlet。Container Provider Service Provider Interface(SPI)允許 portlet 容器通過Portal 檢索信息。

    圖 1. 基本的 Portal 體系結構
    基本的 Portal 體系結構

    Portlet 容器運行 Portlet,給它們提供所需的運行時環境,并且管理它們的生命周期。它為Portlet 首選項項提供持久性存儲,這使得能夠為不同的用戶生成自定義輸出。

    Portal 頁和 Portlet

    圖2展示了基本的 Portal 頁組件。Portal 頁表示一個完整的標記文檔并且聚集若干 Portlet 窗口;也就是說,它將不同的應用程序用戶界面組合到一個統一的表示中去。Portal 頁使用戶能夠通過登錄對話框向 Portal 驗證自己的身份以便訪問個性化的 Portal 視圖。大部分 Portal 頁包括一些導航機制以允許用戶導航到其他的 Portal 頁。

    圖 2:Portal 頁
    Portal 頁

    Portlet 窗口包括:

    • 標題欄,帶有 Portlet 的標題
    • 修飾,包括用于更改 Portlet 的窗口狀態的按鈕(比如最大化或最小化 Portlet)和用于更改 Portlet 的模式的按鈕(比如顯示幫助或編輯預定義的 Portlet 設置)
    • 由 Portlet 產生的內容(也稱為一個標記段)。

    圖 3在不同的瀏覽器上展示了一個 Portlet 窗口。如您所見,該 portlet 產生的標記段并不局限于 HTML,而可以是任何標記。

    圖 3:在 HTML 瀏覽器(頂部)和 WML 瀏覽器(底部)中顯示的 Portlet
    在 HTML 瀏覽器(頂部)和 WML 瀏覽器(底部)中顯示的 Portlet

    Portlet 生命周期

    基本的 portlet 生命周期必須:

    1. 初始化,使用初始化類初始化 Portlet 并將其放入服務中。
    2. 處理請求,處理不同種類的動作并呈現內容。
    3. 完成,使用銷毀類除去 Portlet。

    Portlet 基于用戶與 Portlet 或 Portal頁的交互來接收請求。請求處理分為兩個階段:

    1. 動作處理

      如果用戶單擊 Portlet上的鏈接,就會觸發動作。動作處理必須在頁面上的任何Portlet 呈現開始之前結束。在動作階段,Portlet可以改變 Portlet 的狀態。

    2. 呈現內容

      在呈現階段,Portlet 會產生要發送回客戶端的標記。呈現不應該改變任何狀態。它允許一個頁面重新刷新而不需要改變Portlet  的狀態。一個頁面上的所有 Portlet的呈現都可以并行執行。

    圖 4描述從客戶端到 Portlet的請求流,并且更詳細地展示了動作和呈現階段。在這個示例中,Portlet A接收了一個動作。在該動作執行之后,頁面(A、B、C)上的所有Portlet 的呈現方法都被調用。

    圖 4. 從客戶端到 Portlet 的請求流
    從客戶端到 Portlet 的請求流

    Portlet 模式

    Portlet執行不同的任務并根據它們的當前函數來創建內容。Portlet模式指示 Portlet 何時將執行函數。Portlet模式指定 Portlet應該執行哪一類任務和應該生成什么樣的內容。當調用 Portlet時,Portlet 容器提供當前對 Portlet 的請求的模式。在處理動作請求時,Portlet可以程序化地改變它們的 Portlet 模式。

    JSR 168 定義了三類 Portlet 模式:

    1. 必須支持的模式(語義同上)

      Edit
      顯示一個或多個視圖以讓用戶自定義個性化的 Portletsettings.Help
      Help
      顯示幫助視圖。
      View
      顯示 Portlet 輸出。

    2. 可選擇的客戶模式

      About
      顯示 Portlet 的目的、來源、版本和其他信息。
      Config
      顯示一個或多個配置視圖以讓管理員配置對所有用戶有效的Portlet 設置。
      Edit_defaults
      設置可修改的首選項的缺省值,這些首選項通常可以在EDIT 屏幕中進行更改。
      Preview
      呈現輸出而不需要后端連接或特定于用戶的可用數據。
      Print
      顯示適于打印的視圖。

    3. 特定于 Portal 廠商的模式

      這些模式只適用于特定的廠商Portal。

    窗口狀態

    窗口狀態是分配給 Portlet 生成的 Portal 頁面空間的指示器。Portlet容器提供當前的窗口狀態給 Portlet,而 Portlet 通過窗口狀態來決定它應該呈現多少信息。然而,在處理動作請求時,Portlet也可以程序化地改變它們的窗口狀態。

    JSR 168 定義了如下窗口狀態:

    Normal
    Portlet 與其他 Portlet共享空間,在產生它的輸出時應該對考慮這種狀態。
    Maximized
    與處于正常的窗口狀態相比,窗口有更真實的狀態來提供它的輸出。
    Minimized
    Portlet 應該只呈現最小的輸出或沒有輸出。

    除了這些窗口狀態之外,JSR 168 允許 Portal 定義自定義窗口狀態。

    數據模式

    JSR 168為 Portlet定義了不同的機制以訪問瞬態數據和持久性數據。

    Portlet 可以設置和獲取下列作用域內的瞬態數據:

    請求 請求有附加的數據,比如請求參數和屬性,與Servlet類似。請求可以包含一些特性,以允許進行擴展;也可以包含從Portal 傳送到 Portlet 的客戶端頭字段(反之亦然)。
    會話 Portlet可以將數據存儲在具有全局作用域的會話中,以讓 Web應用程序中的其他組件訪問這些數據;也可以將數據存儲在Portlet作用域中,這個作用域是 Portlet 私有的。
    上下文 Portlet可以將數據存儲在 Web 應用程序上下文中,與 Servlet類似。

    Portlet 可以訪問這些作用域內的持久性數據:

    每個  Portlet Portlet可以將配置和個人數據存儲在 Portlet引用中,以允許 Portlet 創建個性化的輸出。Portlet可以定義允許用戶在編輯模式下更改那些數據(例如股票報價)以及哪些數據是只能由管理員在配置模式下進行更改的配置設置(例如股票報價服務器)。
    每個用戶 Portlet可以讀取用戶概要信息來針對用戶調整它的輸出(例如顯示用戶所在城市的天氣情況)。

    Portlet 應用程序

    所有資源、Portlet 和配置描述符一起打包成一個 Web應用程序檔案文件(WAR)。有兩個配置描述符:

    • 所有不是 Portlet 的 Web 應用程序資源必須在 web.xml配置描述符中指定。
    • 所有 Portlet 和 Portlet 相關的設置必須在 portlet.xmldeployment 描述符中指定。

    比較 JSR 168 與 IBM Portlet API

    這一部分大概地比較了 JSR 168 Portlet API 與 IBM Portlet API。首先講解了一些相似的概念,接著說明了兩者之間的不同之處。

    相似點

    下列概念在 JSR 168和 IBM Portlet API 中是非常相似的。

    特征 相似點 不同點
    Portlet 模式 兩者都支持基本的 Portlet 模式:Edit、Help 和 View。 這種配置模式在 JSR 168中是可選的。IBM Portlet API 不支持其他可選的 JSR 168模式(About、Edit_defaults、Preview、Print)。
    窗口狀態 支持如下窗口狀態:Maximized、Normal和 Minimized。 Solo 窗口狀態只有 IBM Portlet API支持。
    Portlet 生命周期 生命周期是相同的:初始化、處理請求、毀壞。 沒有
    請求處理 請求處理分為處理用戶動作的動作階段和產生標記的呈現階段。 沒有
    URL 編碼 兩者都支持創建指向 Portlet或資源的 URL。 沒有
    包含 Servlet/JSP Servlet 和 JSP 可以包括在 Portlet中。 沒有
    Portlet 會話 Portlet可以存儲瞬態信息,這些信息應該都在會話中的請求內。 沒有
    Portlet 應用程序打包 兩者都通過附加的部署描述符(名為 portlet.xml )來將 Portlet 應用程序打包成 WAR文件。 portlet.xml 格式有所不同。
    基于到期時間的緩存 Portlet可以支持基于到期時間的緩存。 API使用不同的機制來實現這一功能。
    IBM Portlet API使用輪詢機制,在這種機制中, Portal 查詢 Portlet以獲取標記的有效時間,而在 JSR 168 中,Portlet可以將到期時間附加到創建的每個標記上。在用戶之間共享緩存條目只有在IBM Portlet API 中才是可能的。

    不同點

    JSR168 和 IBM Portlet API 在以下幾個方面有所不同。

    特征 IBM Portlet API JSR 168
    Portlet 應用程序實體 使您可以通過部署描述符將抽象的Portlet 應用程序及其不同的實例定義為具體的 Portlet應用程序。這允許重用抽象的 Portlet應用程序的設置,而只重寫對于每個具體的 Portlet應用程序惟一的部分。 該部署描述符緊跟在 web.xml 部署描述符之后,它定義一個應用程序及其 Portlet定義。
    Portlet 實體 Web 部署描述符中的每個 Portlet配置都有一個 Portlet 對象實例。根據 Flyweight模式,可以有許多 PortletSettings 對象來參數化相同的 Portlet對象(基于每個請求)。 PortletSettings 中的改變會應用到這個具體的 Portlet 中的所有 Portlet實例。用戶也可以具體 Portlet的個人視圖,它是通過使用自定義輸出的 PortletData 呈現的。 PortletSettingsPortletData 合并成一個名為 PortletPreferences 的對象。
    請求/響應對象 Portlet在呈現調用中接收到的請求/響應對象與動作調用接收到的相同。 在 JSR 168中,有兩個不同的對象。

    JSR 168 獨有的特征

    這些項只適用于 JSR 168。

    特征 描述
    呈現參數 呈現參數允許 Portlet存儲它的導航狀態。
    呈現參數在隨后的呈現請求中保持不變,而只是在Portlet接收到一個新的動作時才發生改變。這啟用了書簽功能,并且解決了瀏覽器后退按鈕問題。
    全局 HttpSession 作用域 Portlets 不僅可以存儲具有 Portlet可見性的數據,而且可以存儲具有整個 Web 應用程序可見性的數據。
    重定向 Portlet可以重定向到動作階段中的其他 Web 資源。

    IBM Portlet API 獨有的特征

    以下概念只適用于 IBM?Portlet API。

    特征 描述
    事件 事件可以在?Portlet之間發送。
    附加的生命周期偵聽器 除了動作和呈現之外,生命周期偵聽器(比如首頁)也不適用于 JSR168 的第一個版本。
    Portlet 菜單 讓 Portlet可以提供內容到菜單欄,以便通過 Portal頁使導航更加容易。
    基于無效時間的緩存 讓 Portlet可以顯式使緩存的內容無效。

    示例 Portlet

    這一部分展示一個 HelloWorld Portlet,在兩個 API的每一個中都有它的實現。其主要的不同之處突出顯示在第二個Portlet 中。

    這兩個示例 Portlet 實現了相同的功能:

    • 將 JSP 用于呈現輸出
    • 根據特定于用戶的數據自定義 Portlet 輸出
    • 處理動作以允許用戶改變這些動作

    這個示例展示了一個個性化的 HelloWorld Portlet。它通過名稱識別用戶,并且允許用戶進入編輯模式以設置一個新的名稱。在 action方法(在 IBM Portlet API 中稱為 actionPerformed ,而在 JSR 168中稱為 processAction )中,Portlet持久化存儲用戶輸入的新用戶名。

    清單 1. IBM Portlet API 示例 Portlet

    首先看一看通過 IBM Portlet API 實現的 Portlet。

    
    
    public class HelloWorld extends AbstractPortlet implements ActionListener
    {
      public void doView (PortletRequest request, PortletResponse response)
       throws PortletException, IOException
        {
       //Get the user's name to display from persistent storage
       PortletData portletData = request.getData();
       String stringToDisplay=(String)portletData.getAttribute("userName");
    
       if (stringToDisplay == null) {
           stringToDisplay = defaultString;    // set default string
       }
    
       // Add the display string to the portlet request to make it 
       // accessible by the view JSP
       request.setAttribute("userName", stringToDisplay);
    
       // Get a context for the current session for invoking the JSP
       PortletContext context = getPortletConfig().getContext();
       context.include(viewJSP, request, response);
        }
    
        public void doEdit(PortletRequest portletRequest, 
            PortletResponse portletResponse )
          throws PortletException, IOException
        {
       // Create the cancel return URI for the edit page
       PortletURI cancelURI = portletResponse.createReturnURI();
       // Preserve the Cancel URI in the request to make it 
       // accessible by the edit JSP
       portletRequest.setAttribute("cancelURI", cancelURI.toString());
    
       // Create the save URI for the edit page
       PortletURI saveURI = portletResponse.createReturnURI();
       // For the "Save" button the return URI must include the "Save" action
       //    so the Action Listener for this portlet will be invoked       
       SimpleActionHelper.
       addSimplePortletAction(getPortletConfig().getContext(), saveURI, "save");
    
       // Preserve the Save URI in the request to make it accessible by 
       // the edit JSP
       portletRequest.setAttribute("saveURI", saveURI.toString());
    
       //Get the user's name to display from persistent storage
       String stringToDisplay = (String) 
            portletRequest.getData().getAttribute("userName");
       if (stringToDisplay == null) {
           stringToDisplay = defaultString;    // none found, set default string
       }
    
       // Add the display string to the request to make it accessible by the 
       // edit JSP as an inital value of the input field on the edit form
       portletRequest.setAttribute("userName", stringToDisplay);
    
       // Get a context for the current session for invoking the JSP
       PortletContext context = getPortletConfig().getContext();
       context.include(editJSP, portletRequest, portletResponse);
        }
        
    public void actionPerformed(ActionEvent event) {
        String action = 
        SimpleActionHelper.getActionString(getPortletConfig().getContext(),
                event);
        HelloWorld helloPortlet = (HelloWorld)event.getPortlet();
        PortletLog log = helloPortlet.getPortletLog();
    
        // If this is a save action, then see if the user specified a name
        if ( action!=null ) {
          if ( action.equals("save") ) {
           PortletRequest request = event.getRequest();
           PortletData portData = request.getData();
           String userName = request.getParameter("userName");
           try {
           // Save the name specified by the user
             if ( userName != null ) {
             portData.setAttribute("userName", userName);
             portData.store();
          }
          } catch ( AccessDeniedException ade ) {
          } catch ( IOException ioe ) {
           log.error( "
            
              Couldn't write the user date to 
    persistence because an I/O Error occurred.
            " );
          }
         }
        }
      }
    }     
    
                                    
          
    清單 2. JSR 示例Portlet

    現在,看一看已修改為使用 JSR 168 的同一 Portlet。更改過的文本用粗體標記。

    
    public class HelloWorld extends 
            GenericPortlet
    {
      public void doView (
            RenderRequest request, 
            RenderResponse response)
       throws PortletException, IOException
       {
       //Get the user's name to display from persistent storage
       Portlet
            Preferences portletData = request.get
            Preferences();  String stringToDisplay = (String) portletData.get
            Value("userName",
            defaultString);
    
       // Add the display string to the portlet request to make it 
       // accessible by the view JSP
       request.setAttribute("userName", stringToDisplay);
    
       // Get a context for the current session for invoking the JSP
       
            PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(viewJSP);      
       rd.include(request, response);
    
        }
        public void doEdit(
            RenderRequest portletRequest, 
            
            RenderResponse portletResponse )
          throws PortletException, IOException
        {
       // Create the cancel URI for the edit page
       PortletUR
            L cancelURI = portletResponse.create
            ActionUR
            L();
    
       // Preserve the Cancel URI in the request to make it 
       // accessible by the edit JSP
       portletRequest.setAttribute("cancelURI", cancelURI.toString());
    
       // Create the save URI for the edit page
       PortletUR
            L saveURI = portletResponse.create
            ActionUR
            L();
    
       // For the "Save" button the return URI must include the "Save" action
       // so the Action Listener for this portlet will be invoked
       
            saveURI.setParameter("action", "save");
    
       // Preserve the Save URI in the request to make it accessible by 
       // the edit JSP
       portletRequest.setAttribute("saveURI", saveURI.toString());
    
       //Get the user's name to display from persistent storage
       String stringToDisplay = portletRequest.get
            Preferences().get
            Value("userName", 
                                 
            defaultString);
    
       // Add the display string to the request to make it accessible by the edit JSP
       // as an inital value of the input field on the edit form
       portletRequest.setAttribute("userName", stringToDisplay);
    
           // Get a context for the current session for invoking the JSP
       
            PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(editJSP);
       rd.include(portletRequest, portletResponse);
        }
    
      public void 
            processAction(ActionRequest request, ActionResponse response) 
        throws PortletException, IOException 
      {
        String action = 
            request.getParameter("action");
    
      // If this is a save action, then see if the user specified a name
      if ( action!=null ) {
          if ( action.equals("save") ) {
       Portlet
            Preferences portData = request.get
            Preferences();
       String userName = request.getParameter("userName");
       // Save the name specified by the user
       if ( userName != null ) {
         portData.setAttribute("userName", userName);
         portData.store();
       }
      }  
                                    
          

    IBM Portlet API 版本的 Portlet 的主要區別在于:

    1. 請求分配器使用

      JSR 168 和 IBM Portlet API之間的請求分配器使用略有不同。JSR 168使用相同的機制以從上下文中取得一個請求分配器作為 servlet API 的參數。JSR168使用相同的機制從帶有路徑的上下文中獲取請求分配器,以作為與Servlet API 一樣的參數。

    2. 持久性 Portlet 數據

      JSR 168 的持久性數據 PortletPreferences 有一個類似于 JDK 1.4 Preferences 的API,并且允許為 get方法指定缺省值。不再需要檢查零返回值并且顯式設置缺省值的代碼。JSR168 只允許 String 和 String 數組作為首選項的值;IBMPortlet API 可以支持任意對象。

    3. 動作處理

      在 JSR 168 中的動作處理被簡化,并且不需要創建特定的動作對象被創建。自動創建動作 URL會觸發調用 processAction 方法。

    結束語

    由于 JSR 168 的定義,最終有了一個標準的 Portlet API,它提供獨立于 Portal 廠商的編程 Portlet,并且使您可以在不同的 Portal 上不加改變地運行相同的 Portlet。

    JSR 168 的概念與 IBM Portlet API 有密切的聯系。與 IBM Portlet API 相比,JSR 168的功能是有限的,因為它是 Portlet 規范的 第一個版本。熟悉 IBM Portlet API 的開發人員應該能夠毫無困難地盡快學會使用JSR 168 API。

    參考資料

    關于作者
    作者:Stefan HepperStefan Hepper 是位于德國的 IBM  Boeblingen 實驗室 WebSphere Portal 組的一名軟件架構師。它負責 Java 標準并且是 JSR 168 的兩位規范領導者之一。他在國際會議上做過演說,出版過論文,申請過專利并且是 Pervasing Computing(Addison-Wesley 2001)一書的合著者。
    posted on 2005-04-22 13:21 笨笨 閱讀(462) 評論(0)  編輯  收藏 所屬分類: J2EEALLWeblogic Portal
    主站蜘蛛池模板: MM1313亚洲国产精品| 亚洲国产最大av| 国产免费MV大全视频网站| 亚洲免费无码在线| 国产无遮挡色视频免费观看性色 | 免费人成网上在线观看| 国产免费午夜a无码v视频| 狠狠入ady亚洲精品| 免费在线看片网站| 国产精品福利片免费看| 亚洲亚洲人成综合网络| 成人久久免费网站| 亚洲国产女人aaa毛片在线| 91禁漫免费进入| 亚洲午夜无码毛片av久久京东热| 女人被男人桶得好爽免费视频| 亚洲精品无码久久久久秋霞 | 亚洲hairy多毛pics大全| 国产精品麻豆免费版| 一级毛片正片免费视频手机看| 国产国拍精品亚洲AV片| 最近免费中文字幕MV在线视频3 | 日韩精品成人无码专区免费| 亚洲日韩精品国产一区二区三区| 国产高清在线精品免费软件| 性生大片视频免费观看一级 | 亚洲综合无码AV一区二区| 精品国产污污免费网站| 亚洲国产精品乱码在线观看97| 成人免费一级毛片在线播放视频| a毛看片免费观看视频| 亚洲AV乱码久久精品蜜桃| 男女超爽刺激视频免费播放 | 亚洲一区二区三区首页| 免费无码AV电影在线观看| 美景之屋4在线未删减免费| 亚洲另类激情综合偷自拍图| 91香蕉成人免费网站| 一级黄色免费网站| 亚洲另类春色国产精品| 国产精品亚洲αv天堂无码|