歡迎您光臨本站 註冊首頁
  
本文簡單列出了一些 Ajax 功能和 WebSphere® Community Edition 2.1 中包含的框架,並逐步說明了示例 Web 2.0 應用程序的開發工作,該示例應用程序使用了這些框架來簡化開發工作。

引言

Ajax(非同步 JavaScript 和 XML)術語用於表示一組支持創建富 Internet 應用程序 (Rich Internet Application) 的技術。通過使用這些技術,可以創建響應能力強且具有與桌面應用程序類似的豐富用戶界面的 Web 應用程序。這些技術允許在後台以非同步方式檢索數據,而不會影響所顯示的頁面,而且可以僅請求數據,而不用請求整個 HTML 頁面。可以使用現在的瀏覽器提供的 XmlHttpRequest 或等效對象進行此非同步後台通信。

IBM WebSphere Application Server Community Edition v2.1.x(以下稱為 Community Edition)的安裝包中提供了一些用於開發和承載支持 Ajax 的應用程序的流行框架。在本文中,我們將了解如何配置和使用其中的三個框架,即:

  • Dojo 工具包
  • Direct Web Remoting (DWR)
  • Tomcat Comet 支持

我們還將開發一個簡單的 Web 應用程序,其中使用了這些技術來提供得到改善的用戶體驗。為了遵循本文所述進行操作,您需要 WebSphere Application Server Community Edition v2.1.x。





Dojo 工具包

Dojo 是使用 JavaScript 編寫的開源 DHTML 工具集。Dojo 解決了使用 JavaScript 時的一些問題,包括處理瀏覽器特定的行為。這些行為已經通過 Dojo 工具從用戶層面抽象出來了。

另外,還提供了一組可配置小部件,可將其用於快速開發獨立於瀏覽器的動態網頁。Dojo 工具集由一組 JavaScript API 組成,包含在 WebSphere Application Server Community Edition v 2.1 中。可以通過上下文根 /dojo 訪問此工具集。Dojo 還提供了用於進行非同步 XMLHttpRequest 調用的 API,以在不刷新頁面的情況下從伺服器獲取數據。





Direct Web Remoting (DWR)

DWR 允許開發人員通過 JavaScript 代理向客戶端公開伺服器端的 Java™ 對象。它會為所有公開的 Java™ 對象創建代理,以便從客戶端調用這些對象。相應地,DWR 將在伺服器中調用對應的 Java 方法,並將響應以 JSON (JavaScript Object Notation) 格式返回到調用方腳本。

您可以配置 DWR 在後台以同步或非同步方式呼叫伺服器。因此,可以避免與普通 HTTP 請求-響應模式關聯的頁面刷新。

DWR 還提供了 Reverse Ajax,即用於將信息從伺服器以非同步方式發送到瀏覽器的機制。通過這樣,伺服器可以採用以下方式定期將響應發送到客戶端:

  • 輪詢:客戶端定期輪詢伺服器。
  • Comet:當客戶端發出請求時,伺服器將保留響應句柄,寫入內容保存在此句柄中。在這種情況下,客戶端不需要進行輪詢。
  • 合併: 多個響應組合在一起,隨客戶端作出的下一個請求的響應一起發送。




Tomcat Comet 支持

Comet 術語是 Dojo Foundation 的 Alex Russel 發明的,用於描述通過 HTTP 協議進行的事件驅動的伺服器推送機制。在普通 HTTP 通信中,客戶端始終通過打開到伺服器的連接併發送請求來發起數據傳輸。伺服器將處理此請求,在相同連接上發送響應,然後關閉連接。因此,連接的壽命相對較短。在 Comet 中,伺服器將連接保持開放狀態,會在出現相關事件時持續通過其寫入數據。Tomcat p通過 NIO 和 APR 連接器提供了此支持。BIO 連接器並不提供 Comet 支持。





創建 NIO 連接器

預設情況下,Community Edition 並不提供預安裝的 NIO 連接器。在運行使用 Comet 協議的應用程序前,我們需要從管理控制台創建新 NIO 連接器並將其啟動。我們將首先刪除在 8080 埠上運行的 BIO 連接器,然後創建在此埠運行的新 NIO 連接器。

請按照以下步驟創建 NIO 連接器:

  1. 啟動 Community Edition,並在瀏覽器中打開 https://localhost:8443/console/。
  2. 輸入用戶名 system,並輸入密碼 manager。點擊 Login,將隨即在管理控制台中打開 Welcome 頁。
  3. 在左側導航窗格中,單擊 Web Server 鏈接,以打開 Web Server Manager 頁,如圖 1 中所示:

    圖 1. Web Server Manager


  4. 刪除名為 TomcatWebConnector 的連接器。

  5. 在 Add New 部分,單擊 Tomcat NIO Connector 鏈接,將隨即打開圖 2 中所示的屏幕。

    圖 2. 添加新的 Tomcat NIO 連接器


  6. 在 uniqueName 欄位中填寫 TomcatNIOConnector 值,並點擊 Save,從而創建並啟動 NIO 連接器。您的窗口顯示應該與圖 3 類似。

    圖 3. 添加到網路偵聽器的 TomcatNIOConnector






開發 Web 應用程序

我們現在已經完成了所有準備工作,可以開始開發 Web 應用程序了。這是一個股票報價器應用程序,每 5 秒鐘將使用最新的報價進行一次更新。我們將在 Tomcat 提供的 Comet 實現上使用 DWR 的 Reverse Ajax 功能。為了顯示報價,我們將使用 Dojo 工具中提供的一個現成 Dojo 小部件,即 dojox.Grid 小部件。我們還將編寫一個 Servlet 來使用 Tomcat 中的 Comet 支持列印股票信息。

編寫 Comet Servlet

Apache Tomcat 提供了 org.apache.catalina.CometProcessor 介面,以便編寫的所有 Servlet 都能夠使用 Comet 支持。此介面定義了在我們的 Servlet 中實現的名為 public void event(CometEvent event) 的單個方法。清單 1 顯示了此 Servlet 的兩個主要方法:


清單 1:Comet Servlet
				  	public void init() throws ServletException {  	    super.init();  	    Runnable r = new Runnable() {  	        public void run() {  	            while (!stop) {                        synchronized (openConnections){  	                List<Stock> stocks = new StockService().getStocks();  		         for (HttpServletResponse response : openConnections) {  		             try {  		               PrintWriter pw = response.getWriter();  		               for (Stock stock : stocks) {  			            pw.println(stock.getSymbol() + ":"  			                + stock.getPrice());  		               }  		               pw.flush();  		             } catch (IOException e) {			  		                e.printStackTrace(System.out);  		             }                            }  		         }  		         try {  		             Thread.sleep(5000);  		         } catch (InterruptedException e) {  		             e.printStackTrace(System.out);  		         }  		     }  	         }               };  	     Thread stockThread = new Thread(r);  	     stockThread.setDaemon(true);  	     stockThread.start();  	}    	public void event(CometEvent event) throws IOException, ServletException {  		HttpServletRequest request = event.getHttpServletRequest();  		HttpServletResponse response = event.getHttpServletResponse();    		if (event.getEventType() == CometEvent.EventType.BEGIN) {                     synchronized (openConnections){  			openConnections.add(response);                     }  		} else if (event.getEventType() == CometEvent.EventType.ERROR) {                     synchronized (openConnections){  			openConnections.remove(response);                     }  		} else if (event.getEventType() == CometEvent.EventType.END) {                     synchronized (openConnections){  			openConnections.remove(response);                                }  		} else if (event.getEventType() == CometEvent.EventType.READ) {    		}            }  

在 init 方法中,我們將實例化獲取股票報價的線程,此線程還要將這些報價寫入所有正在偵聽的客戶端,即 openConnections 列表中的所有響應對象。出現四個事件(BEGIN、ERROR、END、READ)中的任意事件時,都會觸發 event 方法。我們從作為參數傳遞的 org.apache.catalina.CometEvent 對象中獲得響應。對於 BEGIN 事件,要將響應添加到集合中。對於 ERROR 和 END 事件,我們將從列表中刪除響應。

BEGIN 事件代表著該連接處理開始,因此我們要將響應添加到響應列表中。END 和 ERROR 事件代表著連接結束或出現了錯誤。有關這些事件的含義的更多信息,請參見 Apache Tomcat 文檔。

配置 DWR

應用程序硬編碼了一組要顯示的股票。股票值由 com.dev.trade.service.StockQuoteGenerator 類隨機更新。清單 2 顯示了這個類的源代碼的相關部分。


清單 2:生成股票價格的類
				  package com.dev.trade.service;    import java.util.HashSet;  import java.util.List;  import java.util.Set;  import java.util.Collections;  import com.dev.trade.bo.Stock;    public class StockQuoteGenerator {  	private StockService ss = new StockService();  	private List<Stock>  stocks = null;  	private static StockQuoteGenerator generator = new StockQuoteGenerator();  	private Set<QuoteListener>                    listeners = Collections.synchronizedSet(new HashSet<QuoteListener> ());  	private volatile boolean contextDestroyed = false;    	private StockQuoteGenerator() {                  Runnable r = new Runnable() {                      public void run() {                          try {                              while (!contextDestroyed) {                                  update(generateStockQuotes());                                  Thread.sleep(5000);                              }                          }catch (Exception e) {                              e.printStackTrace(System.out);                          }                      }                  };                  Thread t = new Thread(r);                  t.setDaemon(true);                  t.start();              }    	public static StockQuoteGenerator getInstance() {  		return generator;  	}    	public void setContextDestroyed(boolean cd) {  		this.contextDestroyed = cd;  	}    	public void addListener(QuoteListener listener) {	  	    listeners.add(listener);	  	}    	private void update(List<Stock>  stocks) {  	    for (QuoteListener listener : listeners) {  	        listener.updateStockQuotes(stocks);  	    }  	}    	private List<Stock>  generateStockQuotes() {  		stocks = ss.getStocks();		  		return stocks;  	}    }  

在 StockQuoteGenerator 類(一個單態類)的構造函數中,我們啟動了一個新線程,並向該線程分配了一個 Runnable 對象。因此,這個對象的 run 方法將繼續執行,直到將 contextDestroyed 變數設置為 true 為止。此變數僅在應用程序上下文要銷毀時才會設置為 true。為此,我們將在 web.xml 中註冊一個上下文偵聽器,即 com.dev.trade.listener.ServletContextListener。

generateStockQuotes 方法調用 StockService 的 getStocks 方法來獲取生成的股票報價。使用 addListener 方法可添加偵聽器。這些偵聽器實現 com.dev.trade.service.QuoteListener 介面以及相應的 updateStockQuotes 方法。

這些偵聽器都是 com.dev.trade.service.StockQuoteListenerImpl 的實例。此類在其構造函數中初始化 DWR 提供的 org.directwebremoting.WebContext 類的實例,然後向 StockQuoteGenerator's 偵聽器列表註冊自身。清單 3 顯示了此類的 updateStockQuotes 方法。


清單 3:向不同客戶端推送數據的代碼
				  	public void updateStockQuotes(List<Stock> stocks) {    		ScriptBuffer script = new ScriptBuffer();  		script.appendScript("updateStocks(").appendData(stocks).appendScript(  				");");			  		Collection<ScriptSession> sessions = wctx.getAllScriptSessions();                                for (ScriptSession session : sessions) {  			if(!session.isInvalidated()){  			    session.addScript(script);  			} else {  				wctx.getAllScriptSessions().remove(session);  			}  		}  	}  

此方法將 JavaScript 函數調用傳播到所有開放客戶端。將會調用函數 updateStocks 並傳遞股票值。此 JavaScript 方法實際更新我們將顯示的 Dojo 網格小部件的模型,然後調用其 update 方法,以讓網格顯示新數據。DWR 為每個開放股票報價器頁創建腳本會話。

請注意,為了使其工作,應該由執行 DWR 代碼的同一個線程調用 StockQuoteListenerImpl 類的構造函數。為此,我們將需要配置 DWR,以實例化 StockQuoteListenerImpl 的對象。對於此配置,我們將創建 dwr.xml 文件,並將其放置在應用程序的 WEB-INF 目錄中。清單 4 顯示了此文件。


清單 4:dwr.xml
				  <dwr>    <allow>      <create creator="new" javascript="Ticker" scope="application">        <param name="class" value="com.dev.trade.service.StockQuoteListenerImpl"/>      </create>      <create creator="new" javascript="StockService" scope="application">        <param name="class" value="com.dev.trade.service.StockService"/>      </create>          <convert converter="bean" match="com.dev.trade.bo.Stock"/>        </allow>  </dwr>  

請注意,StockQuoteListenerImpl 已經通過創建程序在 dwr.xml 中公開。我們將此對象的範圍設置為 application,因為每個應用程序只需要一個此對象的實例。我們向 JavaScript 公開的另一個類是 com.dev.trade.service.StockService,此類為我們提供了用於獲得股票列表的 getStocks 方法。我們還需要將 DWRServlet 添加到應用程序的 web.xml,以便初始化 DWR,並由其將所配置的上述對象的代理向 JavaScript 公開。清單 5 顯示了 web.xml 文件。


清單 5:web.xml
				  <?xml version="1.0" encoding="UTF-8"?>  <web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  <display-name>brokerage</display-name>  <listener>      <listener-class>       com.dev.trade.listener.DwrContextListener      </listener-class>  </listener>  <servlet>    <display-name>DWR Servlet</display-name>    <servlet-name>dwr-invoker</servlet-name>    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>    <init-param>       <param-name>debug</param-name>       <param-value>true</param-value>    </init-param>     <init-param>      <param-name>activeReverseAjaxEnabled</param-name>      <param-value>true</param-value>    </init-param>    <init-param>      <param-name>initApplicationScopeCreatorsAtStartup</param-name>      <param-value>true</param-value>    </init-param>    <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>    <servlet-name>dwr-invoker</servlet-name>    <url-pattern>/dwr/*</url-pattern>  </servlet-mapping>      <welcome-file-list>  	<welcome-file>/stocks.html</welcome-file>  </welcome-file-list>    </web-app>  

activeReverseAjaxEnabled 屬性設置為 true,以便 DWR 使用 Comet 來啟用 Reverse Ajax。如果設置為 false,則 DWR 將使用合併選項。

initApplicationScopeCreatorsAtStartup 用於在啟動 DWR 時初始化所有應用程序範圍內的對象。

現在,我們需要在客戶端導入兩個腳本文件:DWR 客戶端引擎和 DWR 為公開的對象 com.dev.trade.service.StockService 創建的 JavaScript 代理。清單 6 顯示了此導入對應的代碼。


清單 6:在客戶端上進行訪問
				  <script type="text/javascript" src="dwr/engine.js"></script>  <script type='text/javascript'  	src='/brokerage/dwr/interface/StockService.js'></script>  

我們還需要配置 DWR 客戶端引擎,以使用活動 Reverse Ajax,因此我們需要調用 dwr.engine.setActiveReverseAjax(true)。

我們可以調用 StockService 的 getStocks 方法,以使用 StockService.getStocks({callback:getModel,async:false}) 對要顯示的 Dojo 網格小部件進行初始填充。getModel 參數引用將調用的 JavaScript 方法,此調用的結果將作為方法參數傳遞。

清單 7 所示的方法將返回我們要顯示的 Dojo 網格的模型。


清單 7:Web Remoting
				  	function getModel(stocks) {		  		var data = new Array();  		for ( var i = 0; i < stocks.length; i++) {  			var subData = new Array();  			subData[0] = stocks[i].symbol;  			subData[1] = stocks[i].companyName  			subData[2] = stocks[i].price  			subData[3] = stocks[i].eps  			data[i] = subData;  		}  		updatedModel = new dojox.grid.data.Table(null, data);  		return updatedModel;  	}    

配置 Dojo

Community Edition 隨附了 Dojo JavaScript 庫。其中對一些管理控制台 Portlet 使用了 Dojo。Dojo 打包為在上下文根 /dojo 提供的 Web 應用程序。要在我們的 HTML 客戶端頁中使用 Dojo,我們需要使用清單 8 中所示的腳本導入 dojo.js 腳本。


清單 8:導入 dojo.js
				  <script type="text/javascript" src="/dojo/dojo/dojo.js"  	djConfig="isDebug:false, parseOnLoad: true"></script>   

導入 Dojo 腳本時,我們可以通過 dojo.require 調用導入其餘依賴項。我們要創建的 dojox.Grid 小部件需要模型和結構。其模型代表要顯示的數據,而結構代表我們將要如何進行顯示。此模型實際上是由數組組成的數組。清單 9 顯示了結構定義:


清單 9:模型定義
				  var view1 = {  		noscroll :false,  		cells : [ [ {  			name :'Symbol',  			width :'auto'  		}, {  			name :'Company Name',  			width :'auto'  		}, {  			name :'Price',  			width :'auto'  		}, {  			name :'Earnings Per Share',  			width :'auto'  		} ] ]  	};    var gridLayout = [ {  		type :'dojox.GridRowView',  		width :'20px'  	}, view1 ];    <div class="tundra" id="stock_grid" dojoType="dojox.Grid" model="updatedModel"  	structure="gridLayout" elasticView="1" defaultHeight="37em"></div>  

在此清單中,我們發現帶 id="stock_grid" 的 div 封裝了實際的網格。此結構由 gridLayout 對象定義,此對象是包含 view1 的數組。

view1 變數也是數組,其中包含提供所有列應該在網格中如何顯示的詳細信息的 cells 屬性。





構建並部署 Web 應用程序

要構建此應用程序,您將需要 Apache Maven2。安裝 Maven2 並按照以下步驟構建應用程序:

  1. 提取 ticker.zip 存檔,這將創建名為 ticker 的目錄。
  2. 打開命令 Shell,並將當前目錄更改為 ticker。
  3. 運行 mvn install。這將構建應用程序,並將輸出 WAR 文件放入 ticker 下的 target 目錄中。WAR 文件的名稱為 ticker.war。
  4. 在瀏覽器中打開 Community Edition 控制台,並導航到 Deploy New Portlet。
  5. 在 Archive 文本框中,輸入所生成 ticker.war 的路徑,並單擊 Install。




測試 Web 應用程序

  1. 在 Web 瀏覽器中打開 http://localhost:8080/ticker,以打開股票報價器,如圖 4 中所示。

    圖 4. 瀏覽器中運行的股票報價器


  2. 在 Web 瀏覽器中打開 http://localhost:8080/ticker/comet,以查看 Comet Servlet 的輸出,如圖5 中所示。

    圖 5. Comet Servlet 輸出






結束語

在本文中,我們通過管理控制台創建並配置了嵌入在 Community Edition 中的 Tomcat 實例的 NIO 連接器。我們還開發了一個 Java EE Web 應用程序,使用 DWR 的 Reverse Ajax 功能將來自伺服器的數據通過 NIO 連接器中內置的 Comet 支持推送到瀏覽器。最後,我們了解了如何實現 Tomcat 的 CometProcessor 介面來編寫公開其 Comet 功能的 Servlet。(責任編輯:A6)



[火星人 ] 為 WebSphere Application Server Community Edition 開發富 Internet 應用程序已經有683次圍觀

http://coctec.com/docs/linux/show-post-69003.html