最近做了一個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 內部服務器錯誤