HTTP長連接實現“服務器推”的技術快速入門及演示示例

轉自:http://blog.csdn.net/xxd851116/article/details/10022015

在我的印象裏HTTP是一種“無狀態的協議”,也就是不知道以前請求的歷史,無法保留上一次請求的結果。
Cookie的誕生,彌補了這個不足,瀏覽器可以通過本地持久化請求數據來記錄上次請求的環境。但這個沒有根本上改變HTTP請求本身的這種“客戶端請求服務器端相應”模式——客戶端是主動的,而服務器是被動的。
最近聽說有“HTTP長連接”,去探索了一把,果然很有意思,能夠實現“服務器推”的這種概念,也就是服務器是主動發送請求,客戶端是被動接受請求。
關於“服務器推”及“HTTP長連接”的概念網上很多,給一個比較系統的介紹文章:
http://www.ibm.com/developerworks/cn/web/wa-lo-comet/

HTTP長連接這種把數據從服務器主動“推”到客戶端的技術,能帶來的好處不言而喻。它可以把最新的統計數據輸出到客戶端,也可以實現即時通訊。

下面是JSP實現的一個“監控服務器時間”程序的代碼示例(片段)
1、web.xml

[html] view plaincopy
  1. <servlet>  
  2.     <servlet-name>ServerTimeMonitorServlet</servlet-name>  
  3.     <servlet-class>com.ebiz.test.ServerTimeMonitorServlet</servlet-class>  
  4.     <init-param>  
  5.         <param-name>interval</param-name>  
  6.         <param-value>1</param-value>  
  7.     </init-param>  
  8. </servlet>  
  9. <servlet-mapping>  
  10.     <servlet-name>ServerTimeMonitorServlet</servlet-name>  
  11.     <url-pattern>/ServerTimeMonitor</url-pattern>  
  12. </servlet-mapping>  

2、servlet:ServerTimeMonitorServlet.java
[java] view plaincopy
  1. package com.ebiz.test;  
  2.   
  3. import java.io.IOException;  
  4. import java.text.SimpleDateFormat;  
  5. import java.util.Date;  
  6.   
  7. import javax.servlet.ServletConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.http.HttpServlet;  
  10. import javax.servlet.http.HttpServletRequest;  
  11. import javax.servlet.http.HttpServletResponse;  
  12.   
  13. public class ServerTimeMonitorServlet extends HttpServlet {  
  14.   
  15.     private static final long serialVersionUID = -3981794330055840248L;  
  16.   
  17.     private String interval = "1";  
  18.   
  19.     public void init(ServletConfig config) throws ServletException {  
  20.         this.interval = config.getInitParameter("interval");  
  21.         super.init();  
  22.     }  
  23.   
  24.     public void destroy() {  
  25.         this.interval = null;  
  26.         super.destroy();  
  27.     }  
  28.   
  29.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,  
  30.             java.io.IOException {  
  31.         for (int i = 0; i < 100; i++) {  
  32.             try {  
  33.                 Thread.sleep(1000 * Integer.valueOf(interval));  
  34.             } catch (NumberFormatException e) {  
  35.                 e.printStackTrace();  
  36.             } catch (InterruptedException e) {  
  37.                 e.printStackTrace();  
  38.             }  
  39.               
  40.             SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss E");  
  41.             String date_str = df.format(new Date());  
  42.               
  43.             writerResponse(response, date_str, "showServerTime");// msg是test.jsp中的那個js方法的名稱  
  44.         }  
  45.         return;  
  46.     }  
  47.   
  48.     protected void writerResponse(HttpServletResponse response, String body, String client_method) throws IOException {  
  49.         StringBuffer sb = new StringBuffer();  
  50.         sb.append("<script type=\"text/javascript\">//<![CDATA[\n");  
  51.         sb.append("     parent.").append(client_method).append("(\"").append(body).append("\");\n");  
  52.         sb.append("//]]></script>");  
  53.         System.out.println(sb.toString());  
  54.   
  55.         response.setContentType("text/html;charset=GBK");  
  56.         response.addHeader("Pragma""no-cache");  
  57.         response.setHeader("Cache-Control""no-cache,no-store,must-revalidate");  
  58.         response.setHeader("Cache-Control""pre-check=0,post-check=0");  
  59.         response.setDateHeader("Expires"0);  
  60.         response.getWriter().write(sb.toString());  
  61.         response.flushBuffer();  
  62.     }  
  63.   
  64.     public String getInterval() {  
  65.         return interval;  
  66.     }  
  67.   
  68.     public void setInterval(String interval) {  
  69.         this.interval = interval;  
  70.     }  
  71.   
  72. }  

3、jsp:server-time-monitor.jsp

[html] view plaincopy
  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>  
  2. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
  3. <c:set var="ctx" value="${pageContext.request['contextPath']}" />  
  4.   
  5. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  6. <html xmlns="http://www.w3.org/1999/xhtml">  
  7. <head>  
  8. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  9. <title>HTTP 長連接測試 —— 監控服務器時間 </title>  
  10. </head>  
  11.   
  12. <body>  
  13. <div id="monitor-window">服務器現在是:<span id="time"></span></div>  
  14. <form id="a-form" action="${ctx}/ServerTimeMonitor" method="post" target="handleFrame">  
  15.     <input type="submit" name="submit" id="submit" value=" 獲取並監控服務器時間 " />  
  16. </form>  
  17. <iframe name="handleFrame" id="handleFrame" style="display:none"></iframe>  
  18.   
  19. <!-- <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script> -->  
  20. <script type="text/javascript" src="jquery-1.10.2.min.js"></script>  
  21. <script type="text/javascript">//<![CDATA[ 
  22. function showServerTime(msg) { 
  23.     $("#time").html(msg); 
  24. } 
  25. //]]></script>  
  26. </body>  
  27. </html>  


執行過程

仔細看JSP這段HTML代碼,很有意思。

1、form通過POST請求把返回的Script代碼輸出到iframe中(form的target="handleFrame")。這段返回的Script代碼在服務器的控制檯輸出如下:

[javascript] view plaincopy
  1. <script type="text/javascript">//<![CDATA[  
  2.         parent.showServerTime("2013-08-17 12:08:14 星期六");  
  3. //]]></script>  
2、iframe完成加載上面這段代碼後解析並執行,這段代碼的作用是調用父頁面的“showServerTime”方法,把消息傳入。

3、父頁面showServerTime函數負責處理接收到的消息。

4、Servlet負責定時執行和輸出,源源不斷向客戶端發送內容。

原來,這個隱藏的iframe起到了一個“紐帶”的作用。

演示結果



測試結果

在Chrome中標題前面有一個正在加載的圖標,感覺上頁面一直在加載,IE9中沒有這個現象,其他瀏覽器沒有測試。


(完)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章