Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 278|回复: 0

[AJAX学习]用XMLHttpRequest和struts实现AJAX

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-12 23:48:35 | 显示全部楼层 |阅读模式
    大约五年前我曾参与一个web应用的开发,该应用的一个主要需求是要提供类似window胖客户端的外观和操作方式。
    先不讨论为什么当初这个项目不直接使用 window胖客户端,而把这个难题带到了web开发中,事实是在五年前还没
    有多少这样的东西(基于web的胖客户端)存在。
              作为对这一课题研究的结果,我偶然发现了一些用于实现上述需求的非典型技术和方法。使用这些技术实现的web应用,
    直到现在很多人还不能相信它们是基于web的,然后事实上你确实是通过浏览器来访问它们。
             让我没想到的是,几年后的今天我所实现的那种东西又出现另一种实现方式,它就是AJAX。AJAX是Adaptive Path的人们
    发明的一个名词,全称是Asynchronous javascript + XML。
            这说明了一件事情,提炼你曾经拥有的好主意是致富的一个好方法。如果当初我意识到我所作的是一件很特别的东西......我跑题了
       
      
       
      
          Google正在使用这项技术,许多其它的组织也是。但它究竟是个什么东西呢?概括地说,AJAX不是一项技术,只是一种考虑问题的方法,这个方法整合了多种技术且基于这样一种考虑:为每一个客户请求构造一张全新的web页面是低效的且应该避免的。 举个例子,假设你再一张web页面上放了两个SELECT元素,你想让第二个SELECT元素的内容随着第一个的内容变化而变化,这是
    实际开发中很常见的一个问题而且有多种解决方案。 AJAX对此问题的解决方法是:只重画页面的一小部分,在这里是第二个SELECT。 AJAX基于一种称为XMLHttpRequest的组件。讨 厌Microsoft的人要开始叫嚷了,因为这是Microsoft的东西。不错,Microsoft有些东西做得挺好,而且先于其他人做了。 Microsoft最初实现XMLHttpRequest是在Windows下的IE 5中,其实现方式是ActiveX对象(好吧, 他们做得不完全对!)。Monilla项目在Mozilla 1.0中实现了一个本地版本,还有Netscape 7。其他的还有Apple的Safari 1.2, Opera 7.60,Firefox等,有提供了类似的功能。 好,让我们切开这块蛋糕看看它的实现。 XMLHttpRequest是一个客户端组件,需要在Javascript脚本中实例化后才能使用。幸运的事,这样做非常简单。在IE中,
    实现代码如下:
      var req = new ActiveXObject("Microsoft.XMLHTTP");  对其他的浏览器,使用:  var req = new XMLHttpRequest();  你当然想在代码中实现一些判断逻辑,有很多方法可以做到这点,但是我倾向于简单的方案,比如只是检查一下某个对象是否存在:  var req;  if (window.XMLHttpRequest) { // Non-IE browsers       req = new XMLHttpRequest();  } else if (window.ActiveXObject) { // IE       req = new ActiveXObject("Microsoft.XMLHTTP");  }  不管你怎么实现,上面的代码执行之后,你会发现变量req现在指向了一个XMLHttpRequest对象,这个对象有一组属性
    和方法,列举如下: Property                                  Description   onreadystatechange                  Event handler for an event that fires at every state change  readyState                                Status: 0 = uninitialized 1 = loading 2 = loaded 3 = interactive 4 = complete  responseText                            Data returned from server in string form responseXML                           

      DOM
    -compatible document object of data returned status                                       HTTP status code (i.e., 200, 404, 500, etc.) statusText                                String message associated with the status code   Method                                    Description   abort()                                      Stops the current request getAllResponseHeaders()          Returns all headers (name and value) as a string getResponseHeader("<headerName>")                 Returns the value of the specified header open("

      ", "URL"[,
      specified URL.  
      asyncFlag
      [, "
      
       "[,
      "<
      password>"]]])
         


      Opens a connection and retrieves response


       
       send(content)                           Transmits request (can include postable string or

      DOM
      object data) setRequestHeader("<name>", "
      
       ")
                         Assigns values to the specifed header
         继续介绍之前,我强烈建议你运行本文末尾给出的那个web应用。如果你还没有下载示例应用,请参见本文末尾给出的链接,
    下载并安装到你的Servlet引擎 中。示例应用是以展开目录的结构形式发布的,所以只要解压后拷贝解压出的目录就可以工作。
    比如,如果你使用Tomcat,只要把xhrstruts目录拷 贝到

      webapps下就可以了。完成之后,启动服务器即可。
      该应用可以通过http://localhost:8080/xhrstruts (将8080换成你的服务器所监听的端口)来访 问。  它展示了几种不同的应
    用场景:一个可排序的table,一个可以改变另一个下拉框内容的下拉框(如上文所述),一个RSS feed 解析器。正像本文标
    题中说明的那样,该示例基于struts。尽管AJAX可以完全独立于struts和任何其他的后端技术,但我使用Java,而且使用 struts,
    所以...... web应用中的所有例子都在代码头部的标签中包含有一段代码,尽管每个都有所不同,总体是出自相同的基础代码,如下:

      
       
       
         
         var req;
           var which;
          
           function retrieveURL(url) {
             if (window.XMLHttpRequest) { // Non-IE browsers
               req = new XMLHttpRequest();
               req.onreadystatechange = processStateChange;
               try {
                 req.open("GET", url, true);
               } catch (e) {
                 alert(e);
               }
               req.send(null);
             } else if (window.ActiveXObject) { // IE
               req = new ActiveXObject("Microsoft.XMLHTTP");
               if (req) {
                 req.onreadystatechange = processStateChange;
                 req.open("GET", url, true);
                 req.send();
               }
             }
           }
          
           function processStateChange() {
             if (req.readyState == 4) { // Complete
               if (req.status == 200) { // OK response
                 document.getElementById("urlContent").innerHTML = req.responseText;
               } else {
                 alert("Problem: " + req.statusText);
               }
             }
           }
         
       
      
    这 段代码逻辑很简单。你可以调用retieveURL()方法,传入你想访问的URL,该方法根据浏览器类型实例化相应的XMLHttpRequest对象,开启一个对指定URL的请求。请留意这里的try...catch语句块,加入这段代码是因为有些浏览器(比如Firefox)不允许使用XMLHttpRequest从一个域到另一个域发送请求,换句话说,如果你从www.omnytex.com/test.htm页面请求 www.cnn.com,该 类浏览器是不允许的,但是,访问www.omnytext.com/whatever.htm是可以的。IE允许这种跨域访问 但是需要用户验证。 有一行代码很重要:req.onreadystatechange = processStateChange, 这行代码设定了一个事件处理器。当request的状态发生变化时,processStateChange()方法将被调用。然后,你可以检查 XMLHttpRequest对象的状态进行后续处理。上面的列表中列出了所有可能的值。 这里我们关心的是请求完成之后,下面要做的事就是检查收到的 HTTP响应代码,除200(HTTP OK)外的任何代码都预示着需要显示错 误信息。 在这个例子中,如果响应接收完成且没有异常,我们就把接收到的代码插入urlContent span,然后最终效果就显示在页面上。 语法上讲,这就是所有XMLHttpRequest的使用方法! 另一个更有趣的例子是web应用中的第二个,动态排序table。下面是完整的页面代码: <code>  <html><head><title>Example 2</title> <script>    var req;
        var which;    function retrieveURL(url) {      if (window.XMLHttpRequest) { // Non-IE browsers        req = new XMLHttpRequest();        req.onreadystatechange = processStateChange;        try {          req.open("
       
        GET
       ", url, true);        } catch (e) {          alert(e);        }        req.send(null);      } else if (window.ActiveXObject) { // IE        req = new ActiveXObject("Microsoft.XMLHTTP");        if (req) {          req.onreadystatechange = processStateChange;          req.open("
       
        GET
       ", url, true);          req.send();        }      }    }    function processStateChange() {      if (req.readyState == 4) { // Complete        if (req.status == 200) { // OK response          document.getElementById("theTable").innerHTML = req.responseText;        } else {          alert("Problem: " + req.statusText);        }      }    }  </script> </head> <body onLoad="retrieveURL("example2RenderTable.do");">  <h1>Example 2</h1> Dynamic table.<hr> <p align="right"><a href="home.do">Return home</a></p><br> This example shows how a table can be built and displayed on-the-fly by showing sorting of a table based on clicks on the table headers. <br><br> <span id="theTable"></span> <br> </body> </html>  

      
       
       
         
         </code>
         
       
      
    请 注意中几乎相同的代码。这里我们实际请求的是一个Struts的Action,该action返回绘制table的HTML脚本。还有其他方法
    可以达到相 同的效果而无需在Action中产生HTML,但这是最快捷而且工作良好的。当页面最初载入的时候我们发送请求到
    | Action得到一个最初的table, 点击任何列标题可以将该table排序并重新绘制。 我们再来看另外一个例子,RSS feed 解析器: <code>

      
       
       
         
         <html><head><title>Example 6</title></head>
          <script>
            var req;
            var which;
            function retrieveURL(url) {
              if (url != "") {
                if (window.XMLHttpRequest) { // Non-IE browsers
                  req = new XMLHttpRequest();
                 req.onreadystatechange = processStateChange;
                 try {
                   req.open("
          
            GET
           ", url, true);
                } catch (e) {
                   alert(e);
                 }
                 req.send(null);
               } else if (window.ActiveXObject) { // IE
                req = new ActiveXObject("Microsoft.XMLHTTP");
                if (req) {
                    req.onreadystatechange = processStateChange;
                  req.open("
          
            GET
           ", url, true);
                 req.send();
                }
                }   }}
          function processStateChange() {
           if (req.readyState == 4) { // Complete
                if (req.status == 200) { // OK response
                  // We"re going to get a list of all tags in the returned XML with the
                  // names title, link and description.  Everything else is ignored.
                  // For each that we find, we"ll constuct a simple bit of HTML for
                // it and build up the HTML to display.  When we hit a title,
                  // link or description element that isn"t there, we"re done.
                  xml = req.responseXML;
                  i = 0;
                  html = "";
                  while (i >= 0) {
                    t = xml.getElementsByTagName("title");
                    l = xml.getElementsByTagName("link");
                    d = xml.getElementsByTagName("description");
                    if (t != null && l != null && d != null) {
                      t = t.firstChild.data;
                      l = l.firstChild.data;
                      d = d.firstChild.data;
                      html += "<a href="" + l + "">" + t + "</a><br>" + d + "<br><br>";
                      i++;
                    } else {
                      i = -1;
                    }
                  }
                  document.getElementById("rssData").innerHTML = html;
                } else {
                  alert("Problem: " + req.statusText);
                }
              }
            }
          </script>
         <body>
         <h1>Example 6</h1>
         RSS example.<hr>
          <p align="right"><a href="home.do">Return home</a></p><br>
          This example is a more real-world example.  It retrieves an RSS feed from one
         of  three user-selected sources, parses the feed and displays the headlines
         in  clickable form.  This demonstrates retrieving XML from a server and
         dealing  with it on the client.
          <br><br>
          <b>Note that the RSS feed XML is actually stored as files within this
         webapp .  That is because some browsers will not allow you to retrieve
         content  with XMLHttpRequest outside the domain of the document trying to
         do  the call.  Some browsers will allow it with a warning though.</b>
          <br><br>
          <form name="rssForm">
            <select name="rssFeed" onChange="retrieveURL(this.value);">
              <option value=""></option>
              <option value="cnn_rss.xml">CNN Top Stories</option>
              <option value="slashdot_rss.xml">Slashdot</option>
              <option value="dans_rss.xml">Dan"s Data</option>
            </select>
          </form>
          <hr><br>
          <span id="rssData"></span>
          <br>
          </body>
          </html>
         </code>
         
       
      
    首 先要注意的是RSS feed XML文件实际上是包含在web应用中的本地文件。一个真正实用使用XMLHttpRequest的RSS
    阅读器是不可能实现的因为要涉及到跨域处理。然 而,一个可行的方法是写一个Action从真正的URL处得到feed然后将
    之返回给请求页面,参见示例7。除了需要一个Action作为代理来得到 RSS feed外,页面上代码还是相同的。 上面的例子跟其它的类似,除了在事件处理器中的XML解析代码。这只是一个简化的例子,我们只是简单地忽略了除标
    题之外的其他标签。在一个真实的例子中(比如一个请求复杂XML的应用),解析代码会变得复杂,但这个我留给读者
    作为练习。 让我们以一个在请求中提交数据的例子做结,中的脚本如下:

      
       
       
         
         var req;
           var which;
          
           function submitData() {
             // Construct a CSV string from the entries.  Make sure all fields are
             // filled in first.
             f = document.theForm.firstName.value;
             m = document.theForm.middleName.value;
             l = document.theForm.lastName.value;
             a = document.theForm.age.value;
             if (f == "" || m == "" || l == "" || a == "") {
               alert("Please fill in all fields first");
               return false;
             }
             csv = f + "," + m + "," + l + "," + a;
             // Ok, so now we retrieve the response as in all the other examples,
             // except that now we append the CSV onto the URL as a query string,
             // being sure to escape it first.
             retrieveURL("example5Submit.do?csv=" + escape(csv));
           }
          
           function retrieveURL(url) {
             if (window.XMLHttpRequest) { // Non-IE browsers
               req = new XMLHttpRequest();
               req.onreadystatechange = processStateChange;
               try {
                 req.open("GET", url, true);
               } catch (e) {
                 alert(e);
               }
               req.send(null);
             } else if (window.ActiveXObject) { // IE
               req = new ActiveXObject("Microsoft.XMLHTTP");
               if (req) {
                 req.onreadystatechange = processStateChange;
                 req.open("GET", url, true);
                 req.send();
               }
             }
           }
          
           function processStateChange() {
             if (req.readyState == 4) { // Complete
               if (req.status == 200) { // OK response
                 document.getElementById("theResponse").innerHTML = req.responseText;
               } else {
                 alert("Problem: " + req.statusText);
               }
             }
           }
         
       
      
    在 这个例子中,我们只是简单地用用户的输入创建了一个以逗号分割的字符串。你当然可以创建一个XML文档然后提交,
    事实上那是更常见的情况。但是这正是我不 想那样做的一部分原因:我想告诉读者你并不一定非要使用XMLHttpRequest
    对象来传输XML。就本例而言,除了将一个CSV字符串添加到URL 之外并没有做任何事情。在网上有不计其数的例子演示
    了如何创建XML文档并使用XMLHttpRequest.send()方法提交,我强烈推荐你阅读相 关文档,当然,如果你使用这种方法的话。 我希望这篇简短的文章和附加的例子可以 给你一个好的研究XMLHttpRequest对象的起点。在结束之前我还想说AJAX概念
    本身并不强制你使用XMLHttpRequest对象,你可以 使用其他方法得到相同的效果,比如代替XMLHttpRequest的隐藏frame,
    这正是我在本文开头提到的在五年前的那个项目中采用的方法。然而, XMLHttpRequest的确使得AJAX概念更容易实现,
    而且更标准。请参见Google研究这种技术的强大之处。 但 是,我提醒所有认为全部的web应用都应该用这种方法开发的人,我不认为这是web开发的不二法门。在某些情况下它是一
    个好的方案,但在其他情况下不是。 如果获得尽可能多的浏览者是你的目标,你最好放弃这种方案。如果一个用户取消了浏览
    器的脚本解释功能(而你的网站除了这又没有其他出彩的地方),这就不是 一个好的情况。还有其他AJAX不适用之处,但是你
    完全可以把它当成你工具箱中的一个普通工具:它适合某些工作,不适合其他工作。毕竟,你不能指望用一个 胶水枪钉钉子吧?
    到此为止,我希望本文已经带给了你进一步思考的食粮,尽情享用吧!

      
      
       
       

         
       

         
       
      
      

    源码下载:http://file.javaxxz.com/2014/10/12/234834093.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-22 21:08 , Processed in 0.399033 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表