3.2 发送请求参数(四)


3.2.1 请求参数作为XML发送

  与几年前相比,当前浏览器上JavaScript的兼容性有了长足的进步,已经不可同日而语,再加上越来越成熟的JavaScript开发工具和技术,你可以决定把Web浏览器作为开发平台。并不只是依赖于浏览器来看待模型—视图—控制器模式中的视图,还可以用JavaScript实现部分业务模型。可以使用Ajax技术把模型中的变化持久存储到后台服务器。如果模型放在浏览器上,模型的变化可以一齐传递到服务器,从而减少对服务器的远程调用次数,还可能提高性能。

  如果只是使用一个包含名/值对的简单查询串,这可能不够健壮,不足以向服务器传递大量复杂的模型变化。更好的解决方案是将模型的变化作为XML发送到服务器。怎么向服务器发送XML呢?

  可以把XML作为请求体的一部分发送到服务器,这与POST请求中将查询串作为请求体的一部分进行发送异曲同工。服务器可以从请求体读到XML,并加以处理。

  下面的例子展示了对于一个Ajax请求如何向服务器发送XML。图3-5显示了这个页面,其中有一个简单的选择框,用户可以选择宠物的类型。这是一个相当简化的例子,但是由此可以了解如何向服务器发送XML。

                                           

                                        图3-5 选择框中选中的项将作为XML发送到服务器

  代码清单3-9显示了postingXML.html。

  代码清单3-9 postingXML.html

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <title>Sending an XML Request</title>
  <script type="text/javascript">
  var xmlHttp;
  function createXMLHttpRequest() {
  if (window.ActiveXObject) {
  xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
  else if (window.XMLHttpRequest) {
  xmlHttp = new XMLHttpRequest();
  }
  }
  function createXML() {
  var xml = "<pets>";
  var options = document.getElementById("petTypes").childNodes;
  var option = null;
  for(var i = 0; i < options.length; i++) {
  option = options[i];
  if(option.selected) {
  xml = xml + "<type>" + option.value + "</type>";
  }
  }
  xml = xml + "</pets>";
  return xml;
  }
  function sendPetTypes() {
  createXMLHttpRequest();
  var xml = createXML();
  var url = "PostingXMLExample?timeStamp=" + new Date().getTime();
  xmlHttp.open("POST", url, true);
  xmlHttp.onreadystatechange = handleStateChange;
  xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;");
  xmlHttp.send(xml);
  }
  function handleStateChange() {
  if(xmlHttp.readyState == 4) {
  if(xmlHttp.status == 200) {
  parseResults();
  }
  }
  }
  function parseResults() {
  var responseDiv = document.getElementById("serverResponse");
  if(responseDiv.hasChildNodes()) {
  responseDiv.removeChild(responseDiv.childNodes[0]);
  }
  var responseText = document.createTextNode(xmlHttp.responseText);
  responseDiv.appendChild(responseText);
  }
  </script>
  </head>
  <body>
  <h1>Select the types of pets in your home:</h1>
  <form action="#">
  <select id="petTypes" size="6" multiple="true">
  <option value="cats">Cats</option>
  <option value="dogs">Dogs</option>
  <option value="fish">Fish</option>
  <option value="birds">Birds</option>
  <option value="hamsters">Hamsters</option>
  <option value="rabbits">Rabbits</option>
  </select>
  <br/><br/>
  <input type="button" value="Submit Pets" onclick="sendPetTypes();"/>
  </form>
  <h2>Server Response:</h2>
  <div id="serverResponse"></div>
  </body>
  </html>

这个例子与前面的POST例子基本上是一样的。区别在于,不是发送由名/值对组成的查询串,而是向服务器发送XML串。

  点击表单上的Submit Pets(提交宠物)按钮将调用sendPetTypes函数。类似于前面的例子,这个函数首先创建XMLHttpRequest对象的一个实例,然后调用名为createXML的辅助函数,它根据所选的宠物类型建立XML串。

  函数createXML使用document.getElementbyId方法获得select元素的引用,然后迭代处理所有option子元素,对于选中的每个option元素依据所选宠物类型创建XML标记,并逐个追加到XML中。循环结束时,要在返回到调用函数(sendPetTypes)之前向XML串追加结束pets标记。

  一旦得到了XML串,sendPetTypes函数继续为请求准备XMLHttpObject,然后把XML串指定为send()方法的参数,从而将XML发送到服务器。

  在createXML方法中,为什么结束标记中斜线前面有一个反斜线?

  SGML规约(HTML就是从SGML发展来的)中提供了一个技巧,利用这个技巧可以识别出script元素中的结束标记,但是其他内容(如开始标记和注释)则不能识别。使用反斜线可以避免把串解析为标记。即使没有反斜线,大多数浏览器也能安全地处理,但是根据严格的XHTML标准,应该使用反斜线。

  聪明的读者可能注意到,根据XMLHttpRequest对象的文档,send()方法可以将串和XML文档对象实例作为参数。那么,这个例子为什么使用串连接来创建XML,而不是直接创建文档和元素对象呢?遗憾的是,对于从头构建文档对象,目前还没有跨浏览器的技术。IE通过ActiveX对象提供这个功能,Mozilla浏览器则通过本地JavaScript对象来提供,其他浏览器可能根本不支持,也可能通过其他途径来支持这个功能。

  读取XML的服务器端代码如代码清单3-10所示,这个代码稍有些复杂。在此使用了Java servlet来读取请求,并解析XML串,不过你也可以使用其他的服务器端技术。

 

本文作者:
« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3