使用异步Servlet扩展AJAX应用程序

ajax|servlet|程序|异步

<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是一个好特性,它允许开发人员提高性能,在独立的线程中处理响应,并将开销降至最低。在构建异步应用程序时,该方法支持可伸缩性。

时间: 2024-09-13 14:24:33

使用异步Servlet扩展AJAX应用程序的相关文章

使用异步Servlet扩展AJAX应用程序--多路复用客户端套接字

作为Web应用程序模型的AJAX的出现使服务器端的面貌发生了巨大的变化.用户对着Web页面填写表单并单击提交按钮转到下一个链接的典型Web使用模式现在正在转变为更先进的客户端JavaScript以及功能更丰富的用户界面,只要对表单进行操作,比如单击一个复选框.按下一个键或将鼠标移到一个选项卡上,该用户界面就会不断地与服务器交互. 考虑一下从客户端传输到服务器的数据量有多大.从可用性的角度来看,用户在一个薄客户端浏览器上获得了富用户界面,无需安装任何东西.但是,当在服务器端扩展这些应用程序时就要付

使用Google Web Toolkit、Apache Derby和Eclipse构建Ajax应用程序 3

Ajax 中的 A 启用了 Asynchronous JavaScript + XML (Ajax) 的 Web 应用程序与传统 Web 应用程序之间的主要差别在于 Ajax 中的 A:异步.Ajax 应用程序允许浏览器更新页面的特定部分而无需完全刷新整个页面.这种简单的技巧将提供更具有交互性的用户体验,因为简单的 Web 页面现在运行得更像是桌面应用程序. 从开发人员的角度来看,这种异步行为有两个关键组件: XMLHttpRequest 对象是由浏览器定义的 JavaScript 对象,它将使

追求代码质量: 对Ajax应用程序进行单元测试

使用 GWT 更轻松地测试异步应用程序 简介: 您可能从编写 Ajax 应用程序中获得了极大乐趣,但是对它们执行单 元测试却着实让人头痛. 在本文中,Andrew Glover 着手解决 Ajax 的弱点( 其中之一),即应对异步 Web 应用程序执行单元测试的固有挑战.幸运的是, 他发现在 Google Web Toolkit 的帮助下,解决这个特殊的代码质量问题要比预 想的容易. Ajax 在近期无疑是 Web 开发界最时髦的字眼之一 -- 与 Ajax 相关的工具.框架.书籍以及 Web

GWT开发AJAX应用程序教程

一. 引言 如果你是一个Java软件和Ajax开发者,那么,Google Web Toolkit(GWT)应该已经引起你的关注. Google公司已经于2006年5月在Apache许可协议下发布了这种免费的开发工具包.GWT的设计目的是为了简化用Java语言开发Ajax应用程序.Google初始发行的beta版本可以适用于Windows和Linux平台,并许诺稍后要发行一个Mac OS X版本. 本文将探讨在Mac OS X上使用GWT和熟悉的Java工具,例如Apache Ant,Tomcat

开发保留标准浏览器功能的AJAX应用程序(3)

ajax|标准|程序|浏览器 使用碎片标识符,我们可以创建一个"Ajax-URI",其中的客户端部分和服务器端部分使用"#"隔开. JavaScript提供了window.location()函数,以便通过URI更新浏览器的历史记录和地址.此外,我们可以使用window.location.hash()直接访问碎片标识符. 在下面的代码片断中,您可以看到如何通过对选择框使用onchange事件处理程序来扩展我们的代码,该处理程序使用一个"Ajax-URI&q

ajax代理程序,自动判断字符编码

ajax|编码|程序 由于ajax在跨域的访问上有问题,目前最好的方法是做代理.写了个代理程序和心得 为了做ajax的代理,研究了下服务器端的xmlhttp并和客户端的ajax中的xmlhttp做了个比较,后台代码是asp的 服务器端的xmlhttp也就是asp小偷程序,我把代码改成了javascript. 1.在服务器端的xmlhttp.Open("GET",url,false)异步必须是关闭的,而客户端的异步是打开的,这个很好理解. 2.在服务器端的xmlhttp.Response

ajax代理程序自动判断字符编码

ajax|编码|程序 由于ajax在跨域的访问上有问题,目前最好的方法是做代理.写了个代理程序和心得. 为了做ajax的代理,研究了下服务器端的xmlhttp并和客户端的ajax中的xmlhttp做了个比较,后台代码是asp的. 服务器端的xmlhttp也就是asp小偷程序,我把代码改成了javascript. 1.在服务器端的xmlhttp.Open("GET",url,false)异步必须是关闭的,而客户端的异步是打开的,这个很好理解.2.在服务器端的xmlhttp.Respons

用事实说话!AJAX应用程序开发七宗罪

ajax|程序 AJAX bandwagon是个好去处.它带给你更快.更高效.更强动态的应用.但它也有自身的缺陷. 初一看,具备一些常识似乎就能避免这些缺陷,在一定程度上,的确如此.但从DHTML起源来看,AJAX应用程序充满了结构性差异.不论你在应用程序开发工作中掌握了多少常识,从别人犯的错误中吸取教训也是有好处的.我们称这些错误为"七宗死罪",但它们不能代表全部的错误. 事实上,在你犯这些致命过失之前,你可能首先犯了一些较轻的错误.因此我们从这里着手.这是每个人都可能犯的错误.这些

像专业人员一样开发Ajax应用程序,第1部分

使用 Prototype JavaScript 库和 script.aculo.us 目前,Web 应用程序开发几乎等同于 Ajax 开发.Ajax 不再是在特殊情况下才添加到应用程序的补充物了.它现在已经成为 Web 开发不可或缺的一部分.对于某些人而 言,用 Ajax 增强应用程序曾经是一项极具挑战的任务.处理跨浏览器限制.编写大量复杂的 JavaScript 以及熟悉其中的数字编码,这些只不过是 Ajax 开发人员所面临 的挑战的一小部分.还好,目前已经有几种开源 JavaScript 库