关于 XMLHttpRequest对象的onreadyStateChange方法
最近做了一个Ajax的demo,前台用HTML+javascript,后台用一个servlet来响应,流程如下:
页面点击链接事件,由js捕获,生成一个请求到后台,servlet处理后给出响应信息,并显示在页面上。
问题是,页面无法获取到servlet的响应信息。
初始代码
index.html
<!DOCTYPE html> <html> <head> <title>Test H2</title> <style> #result{ position:absolute; left:50px; top:300px; } </style> <!-- <script type="text/javascript" src="js/jquery-1.11.1.js"></script> --> <script> function handle(url){ // Fetch the data, HERE i just give some dummy data var username = "joshua"; var query = "query_test"; var feature = url; var click_type = "clc_test"; var rank = 1; var page_number = 1; var paras = "?query="+query+"&username="+username+"&feature="+feature+ "&click_type="+click_type+"&rank="+rank+"&page_number="+page_number; // transfer this data to servlet to save var xmlhttp; // code for IE7+, Firefox, Chrome, Opera, Safari if(window.XMLHttpRequest){ xmlhttp = new XMLHttpRequest; // code for IE6, IE5 }else{ xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("POST","/WebDemo_H2/AjaxServlet"+paras+"&tip="+Math.random(),true); xmlhttp.send(); document.getElementById("result").innerHTML = xmlhttp.responseText; } </script> </head> <body> <aside style="margin:10px;"> <div> <p style="font-weight:bold;">Main Testing Page</p> <a href="index.html">Back</a> </div> <div style="height:20px"></div> <div> <a href="javascript:handle('test1.html')">test link 1</a><br/> <a href="javascript:handle('test2.html')">test link 2</a><br/> <a href="javascript:handle('test3.html')">test link 3</a> </div> </aside> <button onclick="">Clear Data</button> <div id="result"> </div> </body> </html>
Servlet:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; 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; public class AjaxServlet extends HttpServlet { public Connection conn = null; public void init() { try { Class.forName("org.h2.Driver"); conn = DriverManager.getConnection( "jdbc:h2:C:/Users/zhoum18/H2Test/db/test", "sa", ""); } catch (Exception e) { e.printStackTrace(); } } public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("GBK"); response.setContentType("text/html;charset=GBK"); // get the parameters try { PrintWriter out = response.getWriter(); String userName = request.getParameter("username"); String query = request.getParameter("query"); String feature = request.getParameter("feature"); String click_type = request.getParameter("click_type"); String rank = request.getParameter("rank"); String page_number = request.getParameter("page_number"); String sql = "INSERT INTO CLICK_TRACKING SELECT ?,?,?,?,?,?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, query); pstmt.setString(2, userName); pstmt.setString(3, feature); pstmt.setString(4, click_type); pstmt.setInt(5, Integer.parseInt(rank)); pstmt.setInt(6, Integer.parseInt(page_number)); pstmt.executeUpdate(); conn.commit(); sql = "select feature,count(*) as num from click_tracking group by feature"; pstmt = conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery(); out.println("<table border='1'>"); out.println("<tr>"); out.println("<td>Link</td>"); out.println("<td>Click Times</td>"); out.println("</tr>"); while (rs.next()) { out.println("<tr>"); out.println("<td>" + rs.getString("feature") + "</td>"); out.println("<td>" + rs.getString("num") + "</td>"); out.println("</tr>"); } out.println("</table>"); out.close(); } catch (Exception e) { e.printStackTrace(); } } public void destroy() { if (conn != null) { try { conn.close(); } catch (Exception e) { } } } }
可以看到在servlet中用PrintWriter对象返回了建立table的HTML语句,按照逻辑,应该在页面上打印出table的内容跟应有的值;
结果是,xmlhttp.responseText方法返回的值始终为空,没有任何值返回,用chrome浏览器调试,发现HTTP请求是有响应的,而且response tab里面有值:
经过代码查看,发现xmlhttp对象的readystate始终为1.
修改了下页面js的代码,将原有的写入改成了以下代码:
xmlhttp.open("POST","/WebDemo_H2/AjaxServlet"+paras+"&tip="+Math.random(),true); xmlhttp.onreadystatechange = function(){ if (xmlhttp.readyState == 4) { document.getElementById("result").innerHTML = xmlhttp.responseText; } } xmlhttp.send();
成功显示出response的内容。
结论:
页面发送出请求后,往往无法得知什么时候才能完成这个请求并获得回应,所以要使用一个事件机制来捕获请求完成的状态。
XmlHttpRequest对象有一个方法,onreadystatechange这个函数实现这一个功能。
类似于回调函数,在readystate改变时,这个方法可以指定一个函数来判断和处理,比如上面的代码:
xmlhttp.onreadystatechange = function(){
// 这里面的就是当readystate改变时,处理事件的代码,在我的例子中,判断了当readyState等于4的时候,再捕获相应的信息。
}
readyState的不同值,代表了不同的状态:
0:尚未初始化
1:正在加载
2:加载完毕
3:正在处理
4:处理完毕
当其变为4, 就可以访问从服务器返回的数据了。
另附http请求相应代码
200 请求成功
202 请求被接受但处理未完成
400 错误请求
404 请求资源未找到
500 内部服务器错误