专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > XML/SOAP

二使用XMLHttpRequest对象

发布时间:2010-05-20 14:01:29 文章来源:www.iduyao.cn 采编人员:星星草
2使用XMLHttpRequest对象
在使用XMLHttpRequest对象发送请求和处理响应之前,必须先使用javascript创建一个XMLHttpRequest对象。前面已经讲解如何在IE浏览器和非IE浏览器中创建XMLHttpRequest对象。


1XMLhttpRequest对象的方法和属性
abort()。停止当前请求,重新设置请求对象XMLHttpRequest的状态.


getResponseHeader("String"),返回指定首部的串值


open("method","url"),建立对服务器的调用,method参数可以是GET,POST或PUT。url参数可以是相对URL或绝对URL。这个方法还包括3个可选参数。


send(content),向服务器发送请求


setRequestHeader("header","value"),把指定首部设置为所提供的值。在设置任何首部之前必须先调用open().


下面详细介绍这些方法
void open(string method,string url,boolean,asynch,string username,string password),这个方法建立对服务器的调用。这是初始化一个请求的纯脚本方法。它有两个必要的参数,还有3个可选参数。要提供调用特定方法GET,POST,PUT;还要提供所调用资源的URL。另外还可以传递一个Boolean值,指示这个调用是异步还同步,默认为true表示异步。某些情况下这个参数设置为false也是有用的,必须在持久存储页面之前可以先验证用户的输入。最后两个参数允许指定一个特定的额用户名和密码。


void send(content),这个方法具体相服务器发出请求,如果请求声明为异步的,这个方法就会立即返回,否则它会等待直到接收到响应为止。可选参数可以是DOM对象的实例,输入流或串。传入这个方法的内容作为请求体的一部分发送。


void setRequestHeader(string header,string value),这个方法为Http请求中的一个给定的首部设置值。它有两个参数,第一个串表示要设置的首部,第二个串表示要在首部中放置的值。需要说明,这个方法在调用open()之后才能调用。


string getAllResponseHeader(),它返回一个串,其中包含Http请求的所有响应首部,首部包括Content-Length,Date和URI


string getResponseHeader(string header),这个方法与getAllResponseHeaders()是对应的,不过它有一个参数表示你希望得到的指定首部值,并且把这个作为串返回。


XMLHttpRequest属性
Onreadystatechange,每个状态改变时,都会出发这个事件处理器。通常会调用一个JavaScript函数。


readyState,请求的状态。有5个可取值:0=未初始化,1=正在加载,2=已加载,3=交互中,4=完成


responseText,服务器的响应,表示为一个串。


responseXML,服务器的响应,表示为XML,这个对象可以解析为一个DOM对象(用于解析服务器返回的xml串)。如:
xmlHttp.responseXML.getElementsByTagName("message")[0].firstChild.data;


Status,服务器的HTTP状态码(200对应正常,404对应Not Found(未找到),受到保护或者禁止访问的 403 和 401 ,405 表示不允许使用诸如发送 HEAD 请求之类不可接受的请求方法,而 407 则表示需要进行代理认证等)


statusText,HTTP状态的相应文本(OK或者Not Found(未找到)等等)


2处理服务器响应
XMLHttpRequest对象提供了两个可以用来访问服务器响应的属性。第一个属性responseText将响应提供为一个串,第二属性responseXML将相应提供为一个XML对象。一些简单的用例很合适按简单文本来获取响应,如将响应显示在警告框中,或响应指示指示成功还是失败的词。


如果结合html元素的innerHTML属性,responseText属性会变得非常有用。这是一个简单的串,表示一组开始标记和结束标记之间的内容。通过结合使用responseText和innerHTML,服务器就能生产或生成HTML内容。
例如:我们可以使用innerHTML属性将下面xml文件的内容显示在HTML中。
<?xml version="1.0"?>
<table border="1">
<tbody>
<tr>
<th>Activity Name</th>
<th>Location</th>
<th>Time</th>
</tr>
<tr>
<td>Watersking></td>
<td>Dock #1</td>
<td>9:00 AM</td>
</tr>
</tbody>
</table>


在这个jsp文件中上面的xml,通过responseText和innerHTML被解析成为一个表格。
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<html>
<head>
<title>一个简单的例子</title>
<script type="text/javascript" language="javascript">
    var xmlHttp = false;
    function makeRequest(url) {


        xmlHttp = false;


        if (window.XMLHttpRequest) { // Mozilla, Safari,...
            xmlHttp = new XMLHttpRequest();
            if (xmlHttp.overrideMimeType) {
                xmlHttp.overrideMimeType('text/xml');
            }
        } else if (window.ActiveXObject) { // IE
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {}
            }
        }


        if (!xmlHttp) {
            alert('Giving up :( Cannot create an XMLHTTP instance');
            return false;
        }
        xmlHttp.onreadystatechange = alertContents;
        xmlHttp.open('GET', url, true);
        xmlHttp.send(null);


    }


    function alertContents() {


        if (xmlHttp.readyState == 4) {
            if (xmlHttp.status == 200) {
               document.getElementById("results").innerHTML+=xmlHttp.responseText;
            } else {
                alert('There was a problem with the request.');
            }
        }


    }
</script>
</head>
<body>
<span
    style="cursor: pointer; text-decoration: underline"
    onclick="makeRequest('innerHTML.xml')" id="results">
        Make a request
</span>
</body>
</html>


3W3c DOM和javascript
DOM是面向Html和xml文档的API,为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。
用于处理XML文档的DOM元素属性
childNodes,返回当前所有子元素的数组。
firstChild,返回当前的第一个下级子元素。
lastChild,返回当前元素的最后一个子元素。
nextSibling,返回紧跟在当前元素后面的元素。
previousSibling,返回紧邻当前元素之前的元素。
nodeValue,指定表示元素值的读/写属性。
parentNode,返回元素的父节点。


<response><passed>passtest</passed></response>
例:getElementsByTagName("passed")[0].firstChild.data;将返回passtest。


用于遍历XML文档的DOM元素方法
getElementById(id),获取指定唯一ID属性值文档中的元素。
getElementsByTagName(name),返回当前元素中所有指定标记名的子元素的数组。
hasChildNodes(),返回一个布尔值,指示元素是否有子元素。
getAttribute(name),返回元素的属性值,属性由name指定。


下面的一个例子将在javascript显示parseXML.xml中的内容。
parseXML.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<states>
<north>
<state>Minnesota</state>
<state>Iowa</state>
<state>North Dakata</state>
</north>
<south>
<state>Texas</state>
<state>OKlahoma</state>
<state>Louisana</state>
</south>
<east>
<state>New York</state>
<state>North Carolina</state>
<state>Massachusetts</state>
</east>
<west>
<state>California</state>
<state>Oregon</state>
<state>Nevada</state>
</west>
</states>


我们将在parseXML.jsp中显示parseXML.xml中所有state标记的值。
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
<script language="javascript">
var xmlHttp=false;
function createXMLHttpRequest(){
if (window.XMLHttpRequest) { // Mozilla, Safari,...
            xmlHttp= new XMLHttpRequest();
            if (xmlHttp.overrideMimeType) {
                xmlHttp.overrideMimeType('text/xml');
            }
        } else if (window.ActiveXObject) { // IE
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {}
            }
        }


        if (!xmlHttp) {
            alert('Giving up :( Cannot create an XMLHTTP instance');
            return false;
        }


}


function startRequest(){
createXmlHttpRequest();
xmlHttp.onreadystatechange=handleStateChange;
xmlHttp.open("GET","parsetXML.xml",true);
xmlHttp.send(null);
}


function handStateChange(){
if(xmlHttp.readyState==4){
if(xmlHttp.status==200){
listAllStates();
}
}
}


function listAllStates(){
//xmlHttp.responseXML得到服务器的响应,表示为XML,这个对象可以解析为一个DOM对象
var xmlDoc=xmlHttp.responseXML;
//返回所有是state标记名的元素数组
var allStates=xmlDoc.getElementsByTagName("state");
outputList("All States in Document",allStates);
}


function outputList(title,states){
var out=title;
var currentState=null;
for(var i=0;i<states.length;i++){
currentState=states[i];
out=out+"n"+currentState.childNodes[0].nodeValue;
}
alert(out);
}
</script>
</head>
<body>
<form>
<input type="button" value="view all Listed States" onClick="startRequest()"/>
</form>
</body>
</html>


4Web浏览器中动态创建内容
HTML动态创建内容时所用的W3C DOM属性和方法
属性:
childNodes,返回当前元素所有子元素的数组
 
firstChild,返回当前元素的第一个下级子元素
 
lastChild,返回当前元素的最后一个子元素
 
nextSibling,返回紧跟在当前元素后面的元素
 
nodeValue,指定表示元素值的读/写属性
 
parentNode,返回元素的父节点
 
previousSibling,返回紧邻当前元素之前的元素
 


方法:
document.createElement(tagName),文档对象上的createElement方法可以创建由tagName指定的元素。如果以串div作为方法参数就会生成一个div元素。


document.createTextNode(text),文档对象的createTextNode方法会创建一个包含静态文本的节点。


<element>.appendChild(childNode),appendChild方法将指定的节点增加到当前元素的子节点列表。例如可以增减一个option元素作为select元素的子节点。


<element>.getAttribute(name),<element>.setAttribute(name,value)这些方法分别获得和设置元素中name属性的值。


<element>.insertBefore(newNode,targetNode),这个方法将节点newNode作为当前元素的子节点插到targetNode)元素前面。


<element>.removeAttribute(name),这个方法从元素中所以删除属性name


<element>.replaceChild(childNode),这个方法从元素中删除子元素childNode


<element>.replaceChild(newNode,oldNode),这个方法将节点oldNode替换为节点newNode


<element>.hasChildnodes(),这个方法返回一个布尔值,指示元素是否有子元素。


<element>.removeChild(childNode),这个方法从元素中删除子childNode
 


IE的W3C Dom和javascript实现最受限制,例如,如果使用appendChild将<tr>元素直接增加到<table>中,则在IE中这一行并不出现,但在其他浏览器中却会显示出来。对此解决办法是将<tr>元素增加到表的<tbody>元素中,这种办法在所有浏览中都能正确工作。另外在IE中不能使用setAttribute设置style属性,最能保证浏览器兼容的技术不是<element>.setAttribute("style","font-weight:bold;")而是 <element>.style.cssText="font-weight:bold;"


5发送请求参数
大多数情况下,向服务器发送一个请求而没有任何请求参数是没有什么意义的,如果没有请求参数,服务器就得不到上下文数据,也无法根据上下文数据为客户创建个性化响应。要想充分发挥Ajax技术的强大功能,这要求你向服务器发送一些上下文数据。


*****************************
Ajax的Get和Post的区别
GET方式可以传送简单的数据,但是大小一般限制在1KB之下。
GET方法把值作为名/值对放在请求URL中传递。资源URL的最后有一个问号?,问号后面就是名/值对。名/值对采用name=value的形式,各个名/值对之间用与号&分隔。例如:
http://localhost/yourApp?firstName=Adam&middleName=Chirstopher
使用get方式需要注意:
对于get请求(或凡涉及到url传递参数的),被传递的参数都要先经encodeURIComponent方法处理.例:var url = "update.php?username=" +encodeURIComponent(username) + "&content=" +encodeURIComponent(content)+"&id=1" 




POST方法传输的数据量大,可以达到2M。
POST方法向服务器发送命名参数时,与采用GET方法几乎是一样的。类似于GET方法,POST方法会把参数编码为名/值对,形式为name=value,每个名/值对之间也用与号&分隔。这个方法的主要区别在于,POST方法将参数串放在请求体中发送,而GET方法是将参数追加到URL中发送。POST方法参数将在Send()方法中发送,例: xmlHttp.send(name); 如果是get方式,直接 xmlHttp.send(null);
使用Post方式需注意:
设置header的Context-Type为application/x-www-form-urlencode确保服务器知道实体中有参数变量.通常使用XmlHttpRequest对象的SetRequestHeader("Context-Type","application/x-www-form-urlencoded;")。例:
xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");


注: encodeURIComponent返回一个包含了 charstring 内容的新的 String 对象(Unicode 格式), 所有空格、标点、重音符号以及其他非 ASCII 字符都用 %xx 编码代替,其中 xx 等于表示该字符的十六进制数。例如,空格返回的是 "%20"。字符的值大于 255 的用 %uxxxx 格式存储。参见JavaScript 的 encodeURIComponent()方法.(application/x-www-form-urlencoded同encodeURIComponent做法一样)


关于application/x-www-form-urlencoded:
form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application /x-www-form-urlencoded。 当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1& amp;name2=value2...),然后把这个字串append到url后面,用?分割,加载这个新的url。 当action为post时候,浏览器把form数据封装到http body中,然后发送到server。 如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。 但是如果有type=file的话,就要用到multipart/form-data了


HTML使用规约理论上推荐采用GET方法,从这可以看出,获取数据时应当使用GET方法,如果因为存储,更新数据或发送电子邮件操作改变了数据模型的状态,这时建议使用POST方法。
*****************************


AJAX乱码问题
产生乱码的原因:
1、xtmlhttp返回的数据默认的字符编码是utf-8,如果客户端页面是gb2312或者其它编码数据就会产生乱码。解决方法:若客户端是gb2312编码,则在服务器指定输出流编码为gb2312。


2、post方法提交数据默认的字符编码是 utf-8,如果服务器端是gb2312或其他编码数据就会产生乱码
post方法提交数据默认的字符编码是utf-8,如果服务器端是gb2312或其他编码数据就会产生乱码.
解决办法:服务器端和客户端都使用utf-8编码.
gb2312:header('Content-Type:text/html;charset=GB2312');
utf8:header('Content-Type:text/html;charset=utf-8');


对于application/x-www-form-urlencoded可以顺利处理英文;在处理中文时,request.getParameter("parameter")根本取不到值参数parameter的中文值。


*******************


下面的getAndPostExample.jsp中展示了get,post方法像服务器发送数据
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<html>
<head>
<title>Sending Request Data Using GET and POST</title>
<script type="text/javascript">
var xmlHttp;
function createXMLHttpRequest(){
if (window.XMLHttpRequest) { // Mozilla, Safari,...
            xmlHttp= new XMLHttpRequest();
            if (xmlHttp.overrideMimeType) {
                xmlHttp.overrideMimeType('text/xml');
            }
        } else if (window.ActiveXObject) { // IE
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {}
            }
        }


        if (!xmlHttp) {
            alert('Giving up :( Cannot create an XMLHTTP instance');
            return false;
        }
}


function createQueryString(){
var firstName=document.getElementById("firstName").value;
var middleName=document.getElementById("middleName").value;
var birthday=document.getElementById("birthday").value;
var queryString="firstName="+firstName+"&middleName="+middleName+"&birthday="+birthday;
return queryString;
}


function doRequestUsingGET(){
createXMLHttpRequest();


var query="GetAndPostExample.do";
//因为是在struts中,url可以为GetAndPostExample.do,但是如果在Servlet中,查询串会追加到请求url中的。当然即使我们在struts中,url追加了查询串(queryString),也是可以的,只是没有必要这么麻烦。
//query=query+"?"+createQueryString();
xmlHttp.onreadystatechange=handleStateChange;
xmlHttp.open("GET",query,true);
xmlHttp.send(null);
}


function doRequestUsingPOST(){
createXMLHttpRequest();
var url="GetAndPostExample.do";
var queryString=createQueryString();


xmlHttp.open("POST",url,true);
xmlHttp.onreadystatechange=handleStateChange;
xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");
//application/x-www-form-urlencoded含义是表示客户端提交给服务器文本内容的编码方式 是URL编码,即除了标准字符外,每字节以双字节16进制前加个“%”表示


//因为是在struts中,url可以为GetAndPostExample.do,post方法时,XMLHttpRequest对象的send()方法时不用发送查询串。但是在Servlet中,send()方法要发送查询串(queryString);当然即使我们在struts中使用send()方法发送了查询串,也是可以的。只是不同这么麻烦。
//xmlHttp.send(queryString);
xmlHttp.send(null);
}


function handleStateChange(){
if(xmlHttp.readyState==4){
if(xmlHttp.status==200){
parseResults();
}}}


function parseResults(){
var reponseDiv=document.getElementById("serverResponse");
if(reponseDiv.hasChildNodes()){
reponseDiv.removeChild(reponseDiv.childNodes[0]);
}
var responseText=document.createTextNode(xmlHttp.responseText);
reponseDiv.appendChild(responseText);
}
</script>
</head>
<body>
<h1>Enter your first name,middlename,and birthday:</h1>
<form method="get">
<table><tbody>
<tr><td>First name:</td>
<td><input type="text" id="firstName"/>
</tr>
<tr>
<td>Middle name:</td>
<td><input type="text" id="middleName"/>
</tr>
<tr>
<td>Birthday:</td>
<td><input type="text" id="birthday"/>
</tr>
</tbody></table>
<input type="button" value="Send parameters using GET" onClick="doRequestUsingGET();"/>
<br/><br/>
<input type="button" value="Send parameters using POST" onclick="doRequestUsingPOST();"/>
</form>
<br/>
<h2>Server Response:</h2>
<div id="serverResponse"></div>
</body>
</html>


与getAndPostExample.jsp对应的ActionForm:
package mypack;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.*;
import javax.servlet.*;


public class GetAndPostForm extends ActionForm{
private String firstName;
private String middleName;
private String birthday;


public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName=firstName;
}
public String getMiddleName(){
return middleName;
}
public void setMiddleName(String middleName){
this.middleName=middleName;
}
public String getBirthday(){
return birthday;
}
public void setBirthday(String birthday){
this.birthday=birthday;
}
}


处理getAndPostExample.jsp表单数据的Action类:
package mypack;


import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import java.io.*;


public class GetAndPostAction extends Action{
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception{


GetAndPostForm gpf=(GetAndPostForm)form;
String firstName=gpf.getFirstName();
String middleName=gpf.getMiddleName();
String birthday=gpf.getBirthday();
String responseText="Hello"+firstName+" "+middleName+" "+birthday;


PrintWriter out=response.getWriter();
//这里输出的字符串responseText将是在javascript中的XMLHttpRequest对象responseText属性的值。
out.println(responseText);
out.close();
return null;
}
}
****************
上例中我们在一个struts实例中演示了XMLHttpRequest对象的与服务器的异步交互。我们得到,在struts中,不论为get还是post方法:
xmlHttp.open("POST",url,true)建立对服务器的调用,url就是服务器端配置的用于处理表单数据的Action(GetAndPostExample.do)。


send(null),向服务器发送请求,send()方法直接发送一个null值就可以了。不过这只是在<form>..</form>表单中并有ActionForm类与之对应,所以我们发送了null,也可以通过ActionForm类获取表单的内容;但是如果不在<form>中,则我们还是不要使用send(null)否则就得不到表单的内容。


XMLHttpRequest对象的responseText属性将收到服务器端(Action)输出的响应。


***************






87



























友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: