Ajax学习系列3—XMLHttpRequest对象使用的扩展问题
这次介绍使用XMLHttpRequest对象过程中,经常遇到三个问题的解决方法:
(在Ajax学习系列2—核心对象XMLHttpRequest中介绍了XMLHttpRequest对象的五步使用法)
- 解决浏览器缓存问题
- 解决中文乱码问题
- 解决跨域访问问题
浏览器缓存带来的问题
AjaxCache.html
<!DOCTYPE html><html> <head> <title>ajax-测试缓存</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <input type="button" value="测试缓存问题" onclick="checkCache()"/> <div id="cacheMes"></div> <script type="text/javascript"> var xmlhttp; function checkCache(){ // 1.创建XMLHttpRequest对象 if(window.XMLHttpRequest){ // IE7,IE8,FireFox,Mozillar,Safari,Opera xmlhttp = new XMLHttpRequest(); // 由于Mozillar版本的,XML以MimeType开头时,服务端可能会无法工作 if(xmlhttp.overrideMimeType){ xmlhttp.overrideMimeType("text/xml"); } }else if(window.ActiveXObject){ // // IE5,IE5.5,IE6 var activexName = ["MSXML2.XMLHTTP","Miscrosoft.XMLHTTP"]; for(var i = 0;i < activexName.length;i++){ // 循环测试 try{ xmlhttp = new ActiveXObject(activeName[i]); break; }catch(e){}; } }else{ alert("不能建立XMLHttpRequest对象"); return false; } // 2.注册回调方法 xmlhttp.onreadystatechange = callback; // 需要方法名 /* // 为了屏蔽浏览器缓存,url中增加时间戳 var url = "Cache"; if(url.indexOf("?") > 0){ url = url + "&t=" + (new Date()).valueOf(); }else{ url = url + "?t=" + (new Date()).valueOf(); }*/ // 3.设置和服务端交互的基本信息(GET方式) xmlhttp.open("GET",url,true); // 4.设置向服务端发送的数据,启动和服务端的交互 xmlhttp.send(null); } function callback(){ // alert(xmlhttp.readyState); // 5.判断和服务端的交互是否完成,服务端是否正确返回数据,如果都正确,更新页面 if(xmlhttp.readyState ==4){ // 表示交互已完成 if(xmlhttp.status ==200){ // 表示服务器的相应代码是200,正确返回数据 // // 纯文本数据的接受方法 var messageNode = document.getElementById("cacheMes"); messageNode.innerHTML = xmlhttp.responseText; // xml数据对应的dom对象接受方法 // 使用的前提是,服务端需要设置content-type为text/xml // var domXml = xmlhttp.responseXML; } } } </script> </body></html>
Cache.java
import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * * @author TCH */public class Cache extends HttpServlet { /** * Processes requests for both HTTP * <code>GET</code> and * <code>POST</code> methods. * * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { Integer counter = (Integer)request.getSession().getAttribute("counter"); if(null == counter){ counter = 0; }else{ counter ++; } request.getSession().setAttribute("counter", counter); out.println("当前计数器的值为:" + counter); } finally { out.close(); } } /** * Handles the HTTP * <code>GET</code> method. * * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } /** * Handles the HTTP * <code>POST</code> method. * * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } /** * Returns a short description of the servlet. * * @return a String containing servlet description */ @Override public String getServletInfo() { return "Short description"; }// </editor-fold>}
单击按钮多次,发现结果依然是0,达不到我们想要的结果。原因是当第二次单击按钮时,给服务端发送的和第一次发送的是相同的url,服务端回到相应的Session中查看,如果有之前访问的结果,则直接从缓存中提取数据。利用HttpWatch工具证明这点:
Result列:200表示从服务端成功返回;(Cache)表示结果从缓存中返回的
URL列:两个地址相同。
屏蔽缓存
思想:善意的欺骗—让浏览器看到每次的url都不一样,也就不会到缓存中去找了。
通过url中增加时间戳实现
// 为了屏蔽浏览器缓存,url中增加时间戳
var url = "Cache";
if(url.indexOf("?") > 0){
url = url + "&t=" + (new Date()).valueOf();
}else{
url = url + "?t=" + (new Date()).valueOf();
}
这次再次点击按钮,就达到了我们想要看到的效果
利用HttpWatch工具证明这点:
解决中文乱码问题
解决跨域访问问题
因为使用Ajax的跨域访问,会带来不安全因素。
解决:通过同域的代理,访问跨域的服务器
用户名校验实例:
AjaxProxy.html
<!--To change this template, choose Tools | Templatesand open the template in the editor.--><!DOCTYPE html><html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <input type="text" id="userName"/> <input type="button" name="submit" onclick="submit()" value="AJAX校验"/> <div id="message"></div> <script type="text/javascript"> var xmlhttp; function submit(){ // 1.创建XMLHttpRequest对象 if(window.XMLHttpRequest){ // IE7,IE8,FireFox,Mozillar,Safari,Opera xmlhttp = new XMLHttpRequest(); // 由于Mozillar版本的,XML以MimeType开头时,服务端可能会无法工作 if(xmlhttp.overrideMimeType){ xmlhttp.overrideMimeType("text/xml"); } }else if(window.ActiveXObject){ // IE5,IE5.5,IE6 var activexName = ["MSXML2.XMLHTTP","Miscrosoft.XMLHTTP"]; for(var i = 0;i < activexName.length;i++){ try{ xmlhttp = new ActiveXObject(activeName[i]); break; }catch(e){}; } }else{ alert("不能建立XMLHttpRequest对象"); return false; } // 2.注册回调方法 xmlhttp.onreadystatechange = callback; // 需要方法名 var name = document.getElementById("userName").value; // 两次编码,屏蔽请求数据中包含中文,服务端接受错误导致中文乱码问题 name = encodeURI(encodeURI(name)); // 通过代理解决跨域问题 var url = "http://192.168.24.145:8084/VerifyUserName/AjaxServer?name=" + name; if(url.indexOf("http://") > 0){ // url = "http://192.168.24.151:8080/Ajax/AjaxServer?name="+name url.replace("?","&"); // url = "http://192.168.24.151:8080/Ajax/AjaxServer&name="+name url = "Proxy?url" + url; // url = "Proxy?http://192.168.24.151:8080/Ajax/AjaxServer&name="+name } // 3.设置和服务端交互的相应参数(GET方式) xmlhttp.open("GET",url,true); // 4.设置向服务端发送的数据,启动和服务端的交互 xmlhttp.send(null); } function callback(){ // alert(xmlhttp.readyState); // 5.判断和服务端的交互是否完成,服务端是否正确返回数据,如果都正确,更新页面 if(xmlhttp.readyState ==4){ // 表示交互已完成 if(xmlhttp.status ==200){ // 表示服务器的相应代码是200,正确返回数据 // // 纯文本数据的接受方法 var messageNode = document.getElementById("message"); messageNode.innerHTML = xmlhttp.responseText; // xml数据对应的dom对象接受方法 // 使用的前提是,服务端需要设置content-type为text/xml // var domXml = xmlhttp.responseXML; } } } </script> </body></html>
Proxy.java
AjaxServer.java(远程服务端)
import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * * @author TCH */public class AjaxServer extends HttpServlet { /** * Processes requests for both HTTP * <code>GET</code> and * <code>POST</code> methods. * * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { String old = request.getParameter("name"); if (old == null || old.length() == 0) { out.println("用户名不能为空"); } else { String name = new String(old.getBytes("ISO8859-1"), "gb2312"); if (name.equals("tch")) { //4。和传统应用不同之处。这一步需要将用户感兴趣的数据返回给页面段,而不是将一个新的页面发送给用户 //写法没有变化,本质发生了改变 out.println("用户名[" + name + "]已经存在,请使用其他用户名"); } else { out.println("用户名[" + name + "]尚未存在,可以使用该用户名注册"); } } } finally { out.close(); } } /** * Handles the HTTP * <code>GET</code> method. * * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } /** * Handles the HTTP * <code>POST</code> method. * * @param request servlet request * @param response servlet response * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } /** * Returns a short description of the servlet. * * @return a String containing servlet description */ @Override public String getServletInfo() { return "Short description"; }// </editor-fold>}
小结
- 1楼tcl_6666昨天 23:45
- 这次够长吧!!!!!