DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> AJAX入門 >> AJAX詳解 >> 使用異步Servlet擴展AJAX應用程序
使用異步Servlet擴展AJAX應用程序
編輯:AJAX詳解     
<br />  作為Web應用程序模型的AJAX的出現使服務器端的面貌發生了巨大的變化。<table border="0" cellspacing="0" cellpadding="0" align="left" style="margin-top:10px;margin-right:7px;margin-bottom:3px;margin-left:0px"><tr><td><span id="ad_pcdog_big"></span></td></tr></table>用戶對著Web頁面填寫表單並單擊提交按鈕轉到下一個鏈接的典型Web使用模式現在正在轉變為更先進的客戶端Javascript以及功能更豐富的用戶界面,只要對表單進行操作,比如單擊一個復選框、按下一個鍵或將鼠標移到一個選項卡上,該用戶界面就會不斷地與服務器交互。 <br /><br />  考慮一下從客戶端傳輸到服務器的數據量有多大。從可用性的角度來看,用戶在一個薄客戶端浏覽器上獲得了富用戶界面,無需安裝任何東西。但是,當在服務器端擴展這些應用程序時就要付出代價了。AJAX應用程序的典型容量規劃數可能會是標准Web應用程序的3到4倍。<br /><br />  有人可能會問:這對WebLogic Server有何影響?每個發送給WebLogic的HTTP請求都要使用一個執行線程。根據AJAX編程的性質以及許多短期的請求會以輪詢的形式不斷發送的情況,該行為模式可能造成大量客戶端請求不斷沖擊服務器的局面。多年來,WebLogic都將這一問題考慮在內,並構建了一個相當棒的特性,即FutureResponseServlet。該范型構建於異步servlet理念的基礎之上。從版本6.1開始,該功能就允許開發人員提供真正異步的來自服務器的通知,而無需對事件進行客戶端輪訓並在服務器端使用執行線程。在9.x之前,BEA還不急於公開該類。<br /><br />  如何在現實中利用該類呢?我們來看一個例子。假定業務需求是要構建一個基於Web的應用程序,該應用程序以近乎實時的方式向服務器發送數據而無需刷新浏覽器。這樣的應用程序可以向服務器提交一個需要花很長時間處理的請求,而仍然能夠接收到關於其狀態的異步事件並監聽事件。從技術角度來看,這有許多實現方法。其中一種方法就是使用一個與Java Servlet通信的Java Applet來獲得異步信息。這是一種不錯的方法,但是對於用戶來說有些不太方便,因為他們必須下載一個JVM,還要下載一個applet到浏覽器。此外,還必須維護一個從客戶端到服務器的持久性套接字連接,以便接收異步消息。設想一下,如果有1000個用戶使用該applet,那麼就有1000個執行線程幾乎是在空等著發送事件通知到客戶端。當然了,還有其它方法,比如從applet或AJAX應用程序構建輪詢機制來定期檢查新數據。而如果不經常接收到數據,那麼輪詢就顯得無用了,而且還浪費了服務器資源,占用了執行線程。反之,服務器可以定期輪詢,將事件傳播回客戶端,並維護套接字線程,而無需使用持久性執行線程。這非常類似於Java NIO的運行方式。理想情況下,我們都希望構建一個從服務器“異步”接收事件通知而無需在服務器端使用持久性執行線程的應用程序,不管它是一個applet還是一個基於AJAX的薄Web應用程序。<br /><br />  此問題的一種解決方案是創建一個擴展FutureResponseServlet類的servlet。浏覽器建立了到FutureResponseServlet類的單一連接,並在另一個線程中將它自身注冊為一個監聽程序。只要在服務器端接收到一個事件,線程就向客戶端通知該事件。服務器與客戶端保持異步,無需使用持久性執行線程。該模型可擴展用於多個並發用戶的情況。<br /><br />  本文並不打算介紹如何構建AJAX應用程序。這方面的文章已經有很多了。本文的重點在於討論表示層(比如AJax、applet或者任何前端應用程序)的異步處理的重要性。清單1展示了一個例子。<br /><br /><TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1><TR><TD>import java.io.IOException; <br />import java.io.PrintWriter; <br />import java.util.Date; <br />import java.util.Stack; <br />import javax.servlet.ServletException; <br />import Javax.servlet.http.HttpServletRequest; <br />import weblogic.servlet.FutureResponseServlet; <br />import weblogic.servlet.FutureServletResponse; <br />// An AsynchronousServlet that handles HTTP requests from a "separate" thread and <br />// not the execute thread used to invoke this servlet. <br />public class AsynchronousServerResponseServlet extends FutureResponseServlet { <br /><br />private final Notifier notifier; <br /><br />public AsynchronousServerResponseServlet() { <br /> this.notifier = new Notifier(); <br /> this.notifier.start(); <br />} <br /><br />public void service(HttpServletRequest request, FutureServletResponse response) throws IOException,ServletException { <br /> // push this client's request to a buffer and return immediately. <br /> // asynchronous processing occurs in the run method of the Notifier Thread <br /> notifier.poll(request, response); <br />} <br /><br />class Notifier extends Thread { <br /> private static Stack clients = new Stack(); <br /> void poll (HttpServletRequest request, FutureServletResponse response) { <br />  clients.push(new Client(request, response)); <br /> } <br /><br />public void run() { <br /> while (!clients.empty()) { <br />  Client client = null; <br />  try{ <br />   client = (Client) clients.pop(); <br />   PrintWriter pw = client.response.getWriter(); <br />   for(int j = 0; j < 10; j++) { <br />    pw.println("Time is:" + new Date() + ""); <br />    pw.flush();<br />   } <br />   pw.close(); <br />  } <br />  catch(Throwable t) { <br />   t.printStackTrace(); <br />  } <br />  finally { <br />   try { <br />    client.response.send(); <br />   } <br />   catch(IOException ioe) { <br />    ioe.printStackTrace(); <br />   } <br />  } <br /> } <br />} <br />} <br /><br />// inner class that holds o-n to the clients http request and response <br />class Client { <br /> private HttpServletRequest request; <br /> private FutureServletResponse response; <br /> private Client(HttpServletRequest request, FutureServletResponse response) { <br />  this.request = request; <br />  this.response = response; <br /> } <br />} </TD></TR></TABLE><br />  可以看出,該例子非常簡單。AsynchronousServerResponseServlet類擴展了FutureResponseServlet,並重寫了service方法。只使用一個線程(即Notifier類)來處理所有的客戶端連接響應。對於每個HTTP請求,servlet向NotifIEr線程注冊套接字連接,然後返回。異步事件被交付給客戶端,而持久性套接字連接被維持。<br /><br />  單個線程可管理多個客戶端連接!run()方法可用於根據某種消息選擇條件回調事件到客戶端。該例子只執行了一個服務器端的push操作,有些過分簡單了。線程池可被用於某些類型的事件處理。<br /><br />  總而言之,在處理長期運行的任務時,FutureResponseServlet是一個好特性,它允許開發人員提高性能,在獨立的線程中處理響應,並將開銷降至最低。在構建異步應用程序時,該方法支持可伸縮性。
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved