Jquery Ajax长轮询
原理
Jquery Ajax长轮询的原理主要是,前台客户端发送ajax请求到服务器,服务器接收到请求之后会保持住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
优点:在无消息的情况下不会频繁的请求,耗费资源小。
缺点:服务器保持住连接会消耗资源。
jquery ajax长轮询的过程如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FuQ6AEkk-1651461291361)(http://www.ibm.com/developerworks/cn/web/wa-lo-comet/fig002.jpg#pic_center)]
可以看到,长轮询的关闭连接有两种情况:
-
服务器有新的数据,正常响应,断开连接
-
请求超时,断开连接
实例
发送消息的Servlet和前面的一样
下面是长轮询时候服务器的Servlet:
/**
* 基于http长连接的ajax长轮询实现消息提醒
* @author 马艺俊
*
*/
public class JsLongPollingMsgServlet extends HttpServlet {
@Override
protected 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();
//数据发生改变 将数据响应客户端
if(num != pageMsgNum){
json = new StringBuffer("{");
json.append("\"msgNum\":"+num);
json.append("}");
break;
}else{
//没有新的数据 保持住连接
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
out.write(json.toString());
out.close();
}
}
在这个Servlet里,接受到请求之后会进入一个死循环,循环里面会判断消息数据是否发生了改变,如果没改变的话会保持住连接,要是这段时间到了连接超时时间,请求会超时,服务器断开连接,客户端则会重新建立请求;要是这段时间检测到有数据改变,则会将数据响应给客户端,正常断开连接,客户端再重新建立请求。
下面是长轮询的页面:
<%@ 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){
//请求成功,刷新数据
$("#msgNum").html(data.msgNum);
//这个是用来和后台数据作对比判断是否发生了改变
$("#pageMsgNum").val(data.msgNum);
}
if(textStatus == "success"){
//成功之后,再发送请求,递归调用
getMsgNum();
}
},
error:function(XMLHttpRequest, textStatus, errorThrown){
if(textStatus == "timeout"){
//有效时间内没有响应,请求超时,重新发请求
getMsgNum();
}else{
// 其他的错误,如网络错误等
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>
测试
应用部署完后,访问轮询页面http://localhost:8088/JsLongPollingDemo/longPollingPage.jsp
现在还没有新的消息,我们可以按F12看下客户端发送请求的特点
可以看到,客户端每次发送请求之后,5s(请求超时时间)内由于后台服务器保持住连接并且没有响应前台,所以5s后请求超时了,请求被取消(cancel),然后客户端又重新发送了请求
我们访问发送消息的页面,提交新消息
再看看longPollingPage.jsp
消息回来了~
再看看请求的样子
可以看到,我们提交了消息之后,轮询请求检测到数据发生变化,就正常地返回数据响应了