ajax框架,juery的实现xml,中文乱码与跨域访问

来源:互联网 发布:淘宝论坛推广方法 编辑:程序博客网 时间:2024/06/05 16:27

1、AJAX框架

jquery:属于纯粹的前台框架,比较轻量级,JavaScript语言
prototype:与jquery类似,历史比较久

dojo:页面端框架
ext:重量级页面端框架,多用于内网系统。夸张成桌面 

dwr:JavaScript调用java,不提供页面效果


[java] view plain copy
  1. //用户名校验的方法  
  2. //这个方法将使用XMLHTTPRequest对象来进行AJAX的异步数据交互  
  3. var xmlhttp;  
  4. function verify(){  
  5.     //1、使用dom的方式获取文本框中的值  
  6.     //document.getElementById("username")是dom中获取元素节点的一种方法,一个元素节点对应HTML中的一个标签,如<input>  
  7.     //.value可以获取一个元素节点的value属性值  
  8.     var username = document.getElementById("username").value;  
  9.   
  10.     //2、创建XMLHttpRequest对象  
  11.     //这是XMLHttpRequest对象五步使用中最复杂的一步(不同浏览器的差异)  
  12.   
  13.     if (window.XMLHttpRequest){  
  14.         //针对FireFox,Mozillar,Opera,Safari,IE7,IE8  
  15.         xmlhttp = new XMLHttpRequest();  
  16.         //针对某些特定版本的mozillar浏览器的BUG进行修正,不要加()  
  17.         if (xmlhttp.overrideMimeType){  
  18.             xmlhttp.overrideMimeType("text/xml");  
  19.         }  
  20.     }else if (window.ActiveXObject){  
  21.         //针对IE6,IE5.5,IE5  
  22.         //两个可以用于创建XMLHttpRequest对象的空间名称,保存在一个js的数组中  
  23.         //排在前面的版本较新  
  24.         var activexName = ["MSXML2.XMLHTTP","Microsoft.XMLHTTP"];  
  25.         for (var i =0;i<activexName.length;i++){  
  26.             try{  
  27.                 //去除一个空间名进行创建,如果创建成功就终止循环  
  28.                 //如果创建失败,会抛出异常,然后可以继续循环,继续尝试创建  
  29.                 xmlhttp = new ActiveXObject(activexName[i]);  
  30.                 break;  
  31.             }catch(e){  
  32.             }  
  33.         }  
  34.     }  
  35.   
  36.     //确认XMLHttpRequest对象创建成功  
  37.     if (!xmlhttp){  
  38.         alert("XMLHttpRequest对象创建失败!!");  
  39.         return;  
  40.     }else{  
  41.         alert(xmlhttp);  
  42.     }  
  43.   
  44.     //2.注册回调函数  
  45.     //注册回调函数时,只需要函数名,不要加()  
  46.     //我们需要将函数名注册,如果加上(),就会把函数的返回值注册上,这是错误的  
  47.     xmlhttp.onreadystatechange = callback;  
  48.   
  49.     //3.设置连接信息()共5个参数  
  50.     //第一个参数表示http的请求方式,支持所有http的请求方式,主要使用get和post  
  51.     //第二个参数表示请求的url地址,get方式请求的参数也在url中  
  52.     //第三个参数表示采用异步还是同步方式交互,true表示异步,false同步  
  53.     xmlhttp.open("GET","AjaxServletDemo1?username="+username,true);  
  54.   
  55.     //4.发送数据,开始和服务器端进行交互  
  56.     //同步方式下,数据回来后才继续执行send后面的代码  
  57.     //异步方式,send后继续执行  
  58.     xmlhttp.send(null);  
  59. }  
  60.   
  61. //回调函数  
  62. function callback(){  
  63.     //5.接收响应数据  
  64.     //判断对象的状态是否交互完成  
  65.     if (xmlhttp.readyState == 4){  
  66.         //判断http的交互是否成功  
  67.         if (xmlhttp.status == 200){  
  68.             //获取服务器端返回的数据  
  69.             //获取服务器端输出的纯文本数据  
  70.             var responseText = xmlhttp.responseText;  
  71.             //将数据显示在页面上  
  72.             //通过dom的方式找到div标签对应的元素节点  
  73.             var spanNod = document.getElementById("result");  
  74.             spanNod.innerHTML = responseText;  
  75.         }  
  76.     }  
  77. }  


XMLHttpRequest对象的属性:

属性

说明

readyState

readyState一改变,回调函数就调用

表示XMLHttpRequest对象的状态:

0:未初始化。对象已创建,未调用open

1open方法成功调用,但Send方法未调用;

2send方法已经调用,尚未开始接受数据;

3:正在接受数据。Http响应头信息已经接受,但尚未接收完成;

4:完成,即响应数据接受完成。

Onreadystatechange

请求状态改变的事件触发器(readyState变化时会调用这个属性上注册的JavaScript函数)。

responseText

服务器响应的文本内容

responseXML

服务器响应的XML内容对应的DOM对象

Status

服务器返回的http状态码。200表示“成功”,404表示“未找到”,500表示“服务器内部错误”等。

statusText

服务器返回状态的文本信息。



方法

说明

Open(string method,

string url,

boolean asynch,

String username,

string password)

指定和服务器端交互的HTTP方法,URL地址,即其他请求信息;

Method:表示http请求方法,一般使用"GET","POST".

url:表示请求的服务器的地址;

asynch:表示是否采用异步方法,true为异步,false为同步;

后边两个可以不指定,usernamepassword分别表示用户名和密码,提供http认证机制需要的用户名和密码。

Send(content)

向服务器发出请求,如果采用异步方式,该方法会立即返回。

content可以指定为null表示不发送数据,其内容可以是DOM对象,输入流或字符串。

SetRequestHeader(

String header,String Value)

设置HTTP请求中的指定头部header的值为value.

此方法需在open方法以后调用,一般在post方式中使用。

getAllResponseHeaders()

返回包含Http的所有响应头信息,其中相应头包括Content-length,date,uri等内容。

返回值是一个字符串,包含所有头信息,其中每个键名和键值用冒号分开,每一组键之间用CRLF(回车加换行符)来分隔!

getResponseHeader(String header)

返回HTTP响应头中指定的键名header对应的值

Abort()

停止当前http请求。对应的XMLHttpRequest对象会复位到未初始化的状态。


2、XMLHttpRequest的XML交互

服务器端:
[java] view plain copy
  1. package seu.xinci.servlet;  
  2.   
  3. import javax.servlet.ServletException;  
  4. import javax.servlet.annotation.WebServlet;  
  5. import javax.servlet.http.HttpServlet;  
  6. import javax.servlet.http.HttpServletRequest;  
  7. import javax.servlet.http.HttpServletResponse;  
  8. import java.io.IOException;  
  9. import java.io.PrintWriter;  
  10.   
  11. /** 
  12.  * Created by Administrator on 2016-3-6. 
  13.  * 返回xml数据 
  14.  */  
  15. @WebServlet(name = "AjaxServletDemo2",urlPatterns = {"/AjaxServletDemo2"})  
  16. public class AjaxServletDemo2 extends HttpServlet {  
  17.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  18.         doGet(request, response);  
  19.     }  
  20.   
  21.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  22.         //修改点1——text/html->text/xml  
  23.         response.setContentType("text/xml;charset=UTF-8");  
  24.   
  25.         String username = request.getParameter("username");  
  26.         PrintWriter out = response.getWriter();  
  27.   
  28.         //修改点2——返回的数据需要拼装成xml格式,即加上标签  
  29.         StringBuilder sb = new StringBuilder();  
  30.         sb.append("<message>");  
  31.         if (username == null || username.trim().equals("")){  
  32.             sb.append("用户名不能为空").append("</message>");  
  33.         }else {  
  34.             if (username.equals("aaa")){  
  35.                 sb.append("该用户已存在,不能进行注册").append("</message>");  
  36.             }else {  
  37.                 sb.append("该用户名可以注册").append("</message>");  
  38.             }  
  39.         }  
  40.         out.write(sb.toString());  
  41.     }  
  42. }  


js:
[java] view plain copy
  1. //用户名校验的方法  
  2. //这个方法将使用XMLHTTPRequest对象来进行AJAX的异步数据交互  
  3. var xmlhttp;  
  4. function verify(){  
  5.     //1、使用dom的方式获取文本框中的值  
  6.     //document.getElementById("username")是dom中获取元素节点的一种方法,一个元素节点对应HTML中的一个标签,如<input>  
  7.     //.value可以获取一个元素节点的value属性值  
  8.     var username = document.getElementById("username").value;  
  9.   
  10.     //2、创建XMLHttpRequest对象  
  11.     //这是XMLHttpRequest对象五步使用中最复杂的一步(不同浏览器的差异)  
  12.   
  13.     if (window.XMLHttpRequest){  
  14.         //针对FireFox,Mozillar,Opera,Safari,IE7,IE8  
  15.         xmlhttp = new XMLHttpRequest();  
  16.         //针对某些特定版本的mozillar浏览器的BUG进行修正,不要加()  
  17.         if (xmlhttp.overrideMimeType){  
  18.             xmlhttp.overrideMimeType("text/xml");  
  19.         }  
  20.     }else if (window.ActiveXObject){  
  21.         //针对IE6,IE5.5,IE5  
  22.         //两个可以用于创建XMLHttpRequest对象的空间名称,保存在一个js的数组中  
  23.         //排在前面的版本较新  
  24.         var activexName = ["MSXML2.XMLHTTP","Microsoft.XMLHTTP"];  
  25.         for (var i =0;i<activexName.length;i++){  
  26.             try{  
  27.                 //去除一个空间名进行创建,如果创建成功就终止循环  
  28.                 //如果创建失败,会抛出异常,然后可以继续循环,继续尝试创建  
  29.                 xmlhttp = new ActiveXObject(activexName[i]);  
  30.                 break;  
  31.             }catch(e){  
  32.             }  
  33.         }  
  34.     }  
  35.   
  36.     //确认XMLHttpRequest对象创建成功  
  37.     if (!xmlhttp){  
  38.         alert("XMLHttpRequest对象创建失败!!");  
  39.         return;  
  40.     }else{  
  41.         alert(xmlhttp);  
  42.     }  
  43.   
  44.     //2.注册回调函数  
  45.     //注册回调函数时,只需要函数名,不要加()  
  46.     //我们需要将函数名注册,如果加上(),就会把函数的返回值注册上,这是错误的  
  47.     xmlhttp.onreadystatechange = callback;  
  48.   
  49.     //3.设置连接信息()共5个参数  
  50.     //第一个参数表示http的请求方式,支持所有http的请求方式,主要使用get和post  
  51.     //第二个参数表示请求的url地址,get方式请求的参数也在url中  
  52.     //第三个参数表示采用异步还是同步方式交互,true表示异步,false同步  
  53.   
  54.     //GET方式  
  55.     //xmlhttp.open("GET","AjaxServletDemo1?username="+username,true);  
  56.   
  57.     //POST方式  
  58.     xmlhttp.open("POST","AjaxServletDemo2",true);  
  59.   
  60.     //POST方式需要自己设置http的请求头  
  61.     xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");  
  62.   
  63.     //4.发送数据,开始和服务器端进行交互  
  64.     //同步方式下,数据回来后才继续执行send后面的代码  
  65.     //异步方式,send后继续执行  
  66.   
  67.     //GET方式  
  68.     //xmlhttp.send(null);  
  69.   
  70.     //POST方式  
  71.     xmlhttp.send("username="+username);  
  72. }  
  73.   
  74. //回调函数  
  75. function callback(){  
  76.     //5.接收响应数据  
  77.     //判断对象的状态是否交互完成  
  78.     if (xmlhttp.readyState == 4){  
  79.         //判断http的交互是否成功  
  80.         if (xmlhttp.status == 200){  
  81.             //获取服务器端返回的数据  
  82.             //使用responseXML的方式来接收XML数据对象的DOM对象  
  83.             var domObj = xmlhttp.responseXML;  
  84.             if (domObj) {  
  85.   
  86.                 //获取标签节点  
  87.                 //<message>123123123</message>  
  88.                 //dom中利用getElementsByTagName可以根据标签名来获取元素节点,返回的是一个数组  
  89.                 var Nodes = domObj.getElementsByTagName("message");  
  90.   
  91.                 if (Nodes.length > 0) { //获取message节点中的文本内容  
  92.                     //message标签中的文本在dom中是message标签所对应的元素节点的字节点,firstChild可以获取到当前节点的第一个子节点  
  93.                     //通过以下方式就可以获取到文本内容所对应的节点  
  94.                     var textNode = Nodes[0].firstChild;  
  95.                     //对于文本节点来说,可以通过nodeValue的方式返回文本节点的文本内容  
  96.                     var responseMessage = textNode.nodeValue;  
  97.   
  98.   
  99.                     //将数据显示在页面上  
  100.                     //通过dom的方式找到div标签对应的元素节点  
  101.                     var spanNod = document.getElementById("result");  
  102.                     spanNod.innerHTML = responseMessage;  
  103.                 } else {  
  104.                     alert("xml数据错误" + xmlhttp.responseText);  
  105.                 }  
  106.             } else {  
  107.                 alert("解析对象失败");  
  108.             }  
  109.         }  
  110.     }  
  111. }  

GET和POST的区别

“GET”和“POST”的一个重要区别在于,“GET”方式传递给服务器的信息一般以后缀参数方式存在于URL地址中,而URL的长度通常都有限制,这也就限制了“GET”方式传递给服务器的内容大小
而“POST”方式传递给服务器的信息并不位于URL地址中,所以没有大小限制。
通常我们在服务器端的Servlet中,doGet和doPost做的是一样的工作,因此由于POST传递信息没有大小限制,我们实际应用中比较多的会使用POST。 
[java] view plain copy
  1. xmlhttp.open("GET","AJAXServer?name=" + encodeURI(encodeURI(name)),true);  
  2. xmlhttp.send(null);  

[java] view plain copy
  1. xmlhttp.open("POST","AJAXServer",true);  
  2. xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");  
  3. xmlhttp.send("name=" + encodeURI(encodeURI(name)));  

每次readyState变化时onreadystatechange属性对应的函数都会被调用。
之前我们曾经说过onreadystatechange属性设置回调函数是为了在接收到响应数据后对响应数据进行处理,之所以这样说是因为我们通常只关心收到响应数据以后时的工作,也就是readyState=4时的状态,因此我们的回调函数中也用readyState==4来做判断。 

status和statusText属性:
它的值是http的状态码,我们通常只在status=200时才进行响应数据处理,但也可根据具体情况在status为其他值时做一些处理。
statusText属性一般用于status不为200时显示详细的http错误状态信息 

responseText与responseXML属性:
无论服务器端返回的是XML还是普通的文本内容,html内容,都可以使用responseText属性来获得服务器端的返回值。
当服务器端返回的不是XML内容是,不同的浏览器在获取responseXML属性值时略有不同,IE仍然会获取到一个DOM对象,只不过内容是空的,而FireFox获取到的则是一个null 

需要注意的内容
  • 1.不同浏览器下XMLHttpRequest对象的不同的建立方式 
  • 2.设置回调函数时不要加括号
  • 3. open方法三个参数含义,此外还需要注意GET方式和POST方式服务器端地址的不同写法 
  • 4. GET方式和POST方式send的参数的不同之处,以及POST方式下send之前需要设置请求头信息的工作 
  • 5.如何判断正确的响应数据已经返回,此外还要注意如何获取响应数据内容。 

4、Jquery的XML交互

[java] view plain copy
  1. function verify(){  
  2.     var username = $("#username").val();  
  3.   
  4.     $.ajax({  
  5.         type:"POST",                //http请求方式  
  6.         url:"AjaxServletDemo2",     //服务器端url地址  
  7.         data:"username="+username,  //发送给服务器端的数据  
  8.         dataType:"xml",             //告诉jquery数据返回形式  
  9.         success:callback            //定义交互完成。回调函数的名字  
  10.     })  
  11. }  
  12.   
  13. function callback(data){  
  14.     //需要将dom对象转换成jquery对象  
  15.     var jqueryObj = $(data);  
  16.     //获取message节点  
  17.     var message = jqueryObj.children();  
  18.     //获取文本内容  
  19.     var text = message.text();  
  20.   
  21.     var resultObj = $("#result");  
  22.     resultObj.html(text);  
  23.   
  24. }  

5、浏览器缓存问题

IE:若url地址未变,则读取缓存信息。
给URL地址增加时间戳,骗过浏览器
[java] view plain copy
  1. function verify() {  
  2.     //解决中文乱麻问题的方法1,页面端发出的数据作一次encodeURI,服务器段使用new String(old.getBytes("iso8859-1"),"UTF-8");  
  3.     //解决中文乱麻问题的方法2,页面端发出的数据作两次encodeURI,服务器段使用URLDecoder.decode(old,"UTF-8")  
  4.     var url = "AJAXServer?name=" + encodeURI(encodeURI($("#userName").val()));  
  5.     url = convertURL(url);  
  6.     $.get(url,null,function(data){  
  7.         $("#result").html(data);  
  8. });  
  9. }  
  10.   
  11. //给url地址增加时间戳,骗过浏览器,不读取缓存  
  12. function convertURL(url) {  
  13.     //获取时间戳  
  14.     var timstamp = (new Date()).valueOf();  
  15.     //将时间戳信息拼接到url上  
  16.     //url = "AJAXServer"  
  17.     if (url.indexOf("?") >= 0) {  
  18.         url = url + "&t=" + timstamp;  
  19.     } else {  
  20.         url = url + "?t=" + timstamp;  
  21.     }  
  22.     return url;  
  23. }  
换验证码!!

6、中文乱码与跨域调用

中文乱码问题:编码统一问题
1、本页面编码
2、发送内容的编码        jquery中利用encodeURL  内部默认使用的是UTF-8
3、接收信息的编码        request.setCharacterEncoding("UTF-8")
4、返回数据的编码        response.setContentType("text/html;charset=UTF-8")

跨域访问:

XMLHttpRequest的一个特殊安全问题:
IE:访问跨域页面时会给出提示,用户确认后会访问
Mozilla FireFox及其他:不允许访问跨域页面


如何解决跨域访问:



浏览器端:
在浏览器端的代码中,我们需要在调用open方法之前判断一下要连接的地址是不是以http开头的,如果是则认为要访问的是跨域的资源,首先将当前url中的”?”变成”&”,这是因为将要连接的地址改为”Proxy?url=” + url以后,如果原来url地址中有参数的话,新的url地址中就会有两个“?”这会导致服务器端解析参数错误,”url=”之后的内容表示本来要访问的跨域资源的地址。
[java] view plain copy
  1. function convertURL(url){  
  2.     if(url.substring(0,7) == "http://"){  
  3.       url = url.replace("?","&");  
  4.       url = "Proxy?url=" + url;  
  5. }  
  6.     return url;  
  7. }  

代理端:
[java] view plain copy
  1. import java.io.BufferedReader;  
  2. import java.io.InputStreamReader;  
  3. import java.io.PrintWriter;  
  4. import java.io.OutputStreamWriter;  
  5. import java.net.*;  
  6. import java.util.Enumeration;  
  7.   
  8. public class Proxy extends javax.servlet.http.HttpServlet {  
  9.     protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)  
  10.             throws javax.servlet.ServletException, java.io.IOException  {  
  11.         response.setContentType("text/html;charset=GB2312");  
  12.         String url = request.getParameter("url");  
  13.         StringBuffer param = new StringBuffer();  
  14.         Enumeration enu = request.getParameterNames();  
  15.         int total = 0;  
  16.         while(enu.hasMoreElements()){  
  17.             String name = (String)enu.nextElement();  
  18.             if(!name.equals("url")){  
  19.                 if(total == 0){  
  20.                     param.append(name).append("=").append(URLEncoder.encode(request.getParameter(name),"UTF-8"));  
  21.                 } else{  
  22.                     param.append("&").append(name).append("=").append(URLEncoder.encode(request.getParameter(name),"UTF-8"));  
  23.                 }  
  24.                 total++;  
  25.   
  26.             }  
  27.         }  
  28.         PrintWriter out = response.getWriter();  
  29.         if(url != null){  
  30.             URL connect = new URL(url.toString());  
  31.             URLConnection connection = connect.openConnection();  
  32.             connection.setDoOutput(true);  
  33.             OutputStreamWriter paramout = new OutputStreamWriter(connection.getOutputStream());  
  34.             paramout.write(param.toString());  
  35.             paramout.flush();  
  36.             BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"GB2312"));  
  37.             String line;  
  38.             while((line = reader.readLine()) != null){  
  39.                out.println(line);  
  40.             }  
  41.             paramout.close();  
  42.             reader.close();  
  43.         }  
  44.   
  45.     }  
  46.     protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {  
  47.         response.setContentType("text/html;charset=GB2312");  
  48.         StringBuffer url = new StringBuffer();  
  49.         url.append(request.getParameter("url"));  
  50.         Enumeration enu = request.getParameterNames();  
  51.         int total = 0;  
  52.         while(enu.hasMoreElements()){  
  53.             String name = (String)enu.nextElement();  
  54.             if(!name.equals("url")){  
  55.                 if(total == 0){  
  56.                     url.append("?").append(name).append("=").append(URLEncoder.encode(request.getParameter(name),"UTF-8"));  
  57.                 } else{  
  58.                     url.append("&").append(name).append("=").append(URLEncoder.encode(request.getParameter(name),"UTF-8"));  
  59.                 }  
  60.                 total++;  
  61.   
  62.             }  
  63.         }  
  64.         PrintWriter out = response.getWriter();  
  65.         if(url != null){  
  66.              URL connect = new URL(url.toString());  
  67.              BufferedReader reader = new BufferedReader(new InputStreamReader(connect.openStream(),"GB2312"));  
  68.              String line;  
  69.              while((line = reader.readLine()) != null){  
  70.                 out.println(line);  
  71.              }  
  72.              reader.close();  
  73.         }  
  74.   
  75.         http://www.sohu.com/index.html?name=123&id=000  
  76.         Proxy?url=http://www.sohu.com/index.html&name=123&id=000  
  77.   
  78.         url=http://www.sohu.com/index.html&name=123&id=000  
  79.   
  80.         http://www.sohu.com/index.html?id=000&name=123  
  81.   
  82. //ฮารว  
  83. }  
  84. }  
注意Proxy中针对GET方式和POST方式进行了分别的处理,其中GET方式仍然将参数信息拼到URL中,而POST方式则向HttpURLConnection的数据流中添加参数信息。 
由于对本来请求的地址和其包含的参数进行了转换,导致url参数中只包含原来请求的地址信息,而原来请求的参数信息则需要我们解析出来和地址信息一起重新组成本来的请求URL,因此方法开头的一段while就做了这个工作。 

注意由于进入servelt之前参数信息已经被做过一次URLDecoder,因此这个时候参数信息中的中文信息传到真正要访问的servlet时解码会出现乱码,因此我们再拼接参数信息之前又再一次通过URLEncoder.encode方法对所有参数信息进行了一次编码,这样就解决了中文的乱码问题。
在从远端服务器读取数据时,要显示的指定输入流的编码格式,这样才可以保证通过BufferReader读到的内容不会有乱码信息。