Jquery Ajax長(zhǎng)輪詢的原理主要是,前臺(tái)客戶端發(fā)送ajax請(qǐng)求到服務(wù)器,服務(wù)器接收到請(qǐng)求之后會(huì)保持住連接,直到有新消息才返回響應(yīng)信息并關(guān)閉連接,客戶端處理完響應(yīng)信息后再向服務(wù)器發(fā)送新的請(qǐng)求。
優(yōu)點(diǎn):在無(wú)消息的情況下不會(huì)頻繁的請(qǐng)求,耗費(fèi)資源小。
缺點(diǎn):服務(wù)器保持住連接會(huì)消耗資源。
jquery ajax長(zhǎng)輪詢的過(guò)程如下圖:
可以看到,長(zhǎng)輪詢的關(guān)閉連接有兩種情況:
服務(wù)器有新的數(shù)據(jù),正常響應(yīng),斷開(kāi)連接
請(qǐng)求超時(shí),斷開(kāi)連接
發(fā)送消息的Servlet和前面的一樣
下面是長(zhǎng)輪詢時(shí)候服務(wù)器的Servlet:
/** * 基于http長(zhǎng)連接的ajax長(zhǎng)輪詢實(shí)現(xiàn)消息提醒 * @author 馬藝俊 * */public class JsLongPollingMsgServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); PrintWriter out = resp.getWriter(); MessageDao msgDao = new MessageDao(); String pageMsgNumStr = req.getParameter("pageMsgNum"); if(pageMsgNumStr==null || "".equals(pageMsgNumStr)){ pageMsgNumStr = "0"; } int pageMsgNum = Integer.parseInt(pageMsgNumStr); int num = 0; StringBuffer json = null; while(true){ num = msgDao.getMsgNum(); //數(shù)據(jù)發(fā)生改變 將數(shù)據(jù)響應(yīng)客戶端 if(num != pageMsgNum){ json = new StringBuffer("{"); json.append("\"msgNum\":"+num); json.append("}"); break; }else{ //沒(méi)有新的數(shù)據(jù) 保持住連接 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } out.write(json.toString()); out.close();}}
在這個(gè)Servlet里,接受到請(qǐng)求之后會(huì)進(jìn)入一個(gè)死循環(huán),循環(huán)里面會(huì)判斷消息數(shù)據(jù)是否發(fā)生了改變,如果沒(méi)改變的話會(huì)保持住連接,要是這段時(shí)間到了連接超時(shí)時(shí)間,請(qǐng)求會(huì)超時(shí),服務(wù)器斷開(kāi)連接,客戶端則會(huì)重新建立請(qǐng)求;要是這段時(shí)間檢測(cè)到有數(shù)據(jù)改變,則會(huì)將數(shù)據(jù)響應(yīng)給客戶端,正常斷開(kāi)連接,客戶端再重新建立請(qǐng)求。
下面是長(zhǎng)輪詢的頁(yè)面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServ erPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head><base href="<%=basePath%>"><title>My JSP 'index.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--><script type="text/javascript" src="jquery-easyui-v1.4.4/jquery.min.js"></script><script type="text/javascript">$(function(){ getMsgNum();});function getMsgNum(){ $.ajax({ url:'JsLongPollingMsgServlet', type:'post', dataType:'json', data:{"pageMsgNum":$("#pageMsgNum").val()}, timeout:5000, success:function(data, textStatus){ if(data && data.msgNum){ //請(qǐng)求成功,刷新數(shù)據(jù) $("#msgNum").html(data.msgNum); //這個(gè)是用來(lái)和后臺(tái)數(shù)據(jù)作對(duì)比判斷是否發(fā)生了改變 $("#pageMsgNum").val(data.msgNum); } if(textStatus == "success"){ //成功之后,再發(fā)送請(qǐng)求,遞歸調(diào)用 getMsgNum(); } }, error:function(XMLHttpRequest, textStatus, errorThrown){ if(textStatus == "timeout"){ //有效時(shí)間內(nèi)沒(méi)有響應(yīng),請(qǐng)求超時(shí),重新發(fā)請(qǐng)求 getMsgNum(); }else{ // 其他的錯(cuò)誤,如網(wǎng)絡(luò)錯(cuò)誤等 getMsgNum(); } } });}</script> </head> <body><div> <input id="pageMsgNum" name="pageMsgNum" type="hidden"/> 您有<span id="msgNum" style="color: red;">0</span>條消息!</div><div> <p id="title">title</p> <p id="content">content</p></div> </body></html>
應(yīng)用部署完后,訪問(wèn)輪詢頁(yè)面http://localhost:8088/JsLongPollingDemo/longPollingPage.jsp
現(xiàn)在還沒(méi)有新的消息,我們可以按F12看下客戶端發(fā)送請(qǐng)求的特點(diǎn)
可以看到,客戶端每次發(fā)送請(qǐng)求之后,5s(請(qǐng)求超時(shí)時(shí)間)內(nèi)由于后臺(tái)服務(wù)器保持住連接并且沒(méi)有響應(yīng)前臺(tái),所以5s后請(qǐng)求超時(shí)了,請(qǐng)求被取消(cancel),然后客戶端又重新發(fā)送了請(qǐng)求
我們?cè)L問(wèn)發(fā)送消息的頁(yè)面,提交新消息
再看看longPollingPage.jsp
消息回來(lái)了~
再看看請(qǐng)求的樣子
可以看到,我們提交了消息之后,輪詢請(qǐng)求檢測(cè)到數(shù)據(jù)發(fā)生變化,就正常地返回?cái)?shù)據(jù)響應(yīng)了
聯(lián)系客服