轉自: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
- <servlet>
- <servlet-name>ServerTimeMonitorServlet</servlet-name>
- <servlet-class>com.ebiz.test.ServerTimeMonitorServlet</servlet-class>
- <init-param>
- <param-name>interval</param-name>
- <param-value>1</param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>ServerTimeMonitorServlet</servlet-name>
- <url-pattern>/ServerTimeMonitor</url-pattern>
- </servlet-mapping>
2、servlet:ServerTimeMonitorServlet.java
- package com.ebiz.test;
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import javax.servlet.ServletConfig;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class ServerTimeMonitorServlet extends HttpServlet {
- private static final long serialVersionUID = -3981794330055840248L;
- private String interval = "1";
- public void init(ServletConfig config) throws ServletException {
- this.interval = config.getInitParameter("interval");
- super.init();
- }
- public void destroy() {
- this.interval = null;
- super.destroy();
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- java.io.IOException {
- for (int i = 0; i < 100; i++) {
- try {
- Thread.sleep(1000 * Integer.valueOf(interval));
- } catch (NumberFormatException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss E");
- String date_str = df.format(new Date());
- writerResponse(response, date_str, "showServerTime");// msg是test.jsp中的那個js方法的名稱
- }
- return;
- }
- protected void writerResponse(HttpServletResponse response, String body, String client_method) throws IOException {
- StringBuffer sb = new StringBuffer();
- sb.append("<script type=\"text/javascript\">//<![CDATA[\n");
- sb.append(" parent.").append(client_method).append("(\"").append(body).append("\");\n");
- sb.append("//]]></script>");
- System.out.println(sb.toString());
- response.setContentType("text/html;charset=GBK");
- response.addHeader("Pragma", "no-cache");
- response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate");
- response.setHeader("Cache-Control", "pre-check=0,post-check=0");
- response.setDateHeader("Expires", 0);
- response.getWriter().write(sb.toString());
- response.flushBuffer();
- }
- public String getInterval() {
- return interval;
- }
- public void setInterval(String interval) {
- this.interval = interval;
- }
- }
3、jsp:server-time-monitor.jsp
- <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
- <c:set var="ctx" value="${pageContext.request['contextPath']}" />
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>HTTP 長連接測試 —— 監控服務器時間 </title>
- </head>
- <body>
- <div id="monitor-window">服務器現在是:<span id="time"></span></div>
- <form id="a-form" action="${ctx}/ServerTimeMonitor" method="post" target="handleFrame">
- <input type="submit" name="submit" id="submit" value=" 獲取並監控服務器時間 " />
- </form>
- <iframe name="handleFrame" id="handleFrame" style="display:none"></iframe>
- <!-- <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script> -->
- <script type="text/javascript" src="jquery-1.10.2.min.js"></script>
- <script type="text/javascript">//<![CDATA[
- function showServerTime(msg) {
- $("#time").html(msg);
- }
- //]]></script>
- </body>
- </html>
執行過程
仔細看JSP這段HTML代碼,很有意思。
1、form通過POST請求把返回的Script代碼輸出到iframe中(form的target="handleFrame")。這段返回的Script代碼在服務器的控制檯輸出如下:
- <script type="text/javascript">//<![CDATA[
- parent.showServerTime("2013-08-17 12:08:14 星期六");
- //]]></script>
3、父頁面showServerTime函數負責處理接收到的消息。
4、Servlet負責定時執行和輸出,源源不斷向客戶端發送內容。
原來,這個隱藏的iframe起到了一個“紐帶”的作用。
測試結果
在Chrome中標題前面有一個正在加載的圖標,感覺上頁面一直在加載,IE9中沒有這個現象,其他瀏覽器沒有測試。
(完)