HTTP长连接实现
HTTP长连接这种把数据从服务器主动“推”到客户端的技术,能带来的好处不言而喻。它可以把最新的统计数据输出到客户端,也可以实现即时通讯。
1. Area.jsp
<head>
<script type="text/javascript">
var series1 ;
var series2 ;
function jsFun(m)
{
var jsdata = eval("("+m+")");
series1.setData(eval(jsdata.todayData));
series2.setData(eval(jsdata.hisData));
}
function init()
{
var action = "<%=path%>/servlet/AreaSvlt";
$('#myForm').attr("action",action);
$('#myForm').submit();
}
</script>
<script type="text/javascript">
$(function () {
// Set up the chart
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
events : {
load : function()
{
series1 = this.series[0];
series2 = this.series[1];
init();
}
},
margin: 75,
options3d: {
enabled: true,
alpha: 15,
beta: 15,
depth: 50,
viewDistance: 25
}
},
title: {
text: '地区实时金额'
},
subtitle: {
text: '按天统计'
},
plotOptions: {
column : {
dataLabels : {
enabled : true
}
}
},
xAxis : {
categories : ['北京','上海','广州','深圳','成都']
},
yAxis : {
min : 0 ,
labels : {
overflow : 'justify'
}
},
series: [
{
name:'当前',
color:'#41A8BE',
legendIndex:2,
index : 2,
data: []
},
{
name:'上月同期',
color:'#808080',
legendIndex:3,
index : 4,
data: []
} ]
});
});
</script>
</head>
<body>
<form method="post" id="myForm" action="" target="myiframe"></form>
<iframe id="myiframe" name="myiframe" style="display: none;"></iframe>
<div id="container" style="min-width: 400px; height: 400px"></div>
<div id="sliders"
style="min-width: 310px; max-width: 800px; margin: 0 auto;">
</div>
</body>
</html>
2、servlet: AreaSvlt .java
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Result;
import backtype.storm.utils.Utils;
import cloudy.hbase.dao.HBaseDAO;
import cloudy.hbase.dao.imp.HBaseDAOImp;
import cloudy.tools.DateFmt;
import cloudy.vo.AreaVo;
public class AreaSvlt extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
hisDay = DateFmt.getCountDate(null, DateFmt.date_short, -1) ;// 取昨天
System.out.println("hisDay="+hisDay);
hisData = this.getData(hisDay, dao);
System.out.println("hisData="+hisData);
while(true)
{
String dateStr = DateFmt.getCountDate(null, DateFmt.date_short) ;
if (! dateStr.equals(today)) {
//跨天处理
today = dateStr ;
}
//每个3s查询一次hbase
String data = this.getData(today, dao);
//todayData:123,hisData:456
String jsDataString = "{\'todayData\':"+data+",\'hisData\':"+hisData+"}";
boolean flag = this.sentData("jsFun", response, jsDataString);
if (! flag) {
break ;
}
Utils.sleep(3000) ;
}
}
public boolean sentData(String jsFun,HttpServletResponse response,String data)
{
try {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<script type=\"text/javascript\">parent." + jsFun + "(\""+data+"\")</script>");
response.flushBuffer() ;
return true;
} catch (Exception e) {
System.out.println(" long connect 已断开 ");
return false ;
}
}
}
执行过程
仔细看JSP这段HTML代码,很有意思。
1、form通过POST请求把返回的Script代码输出到iframe中(form的target=”myiframe”)。这段返回的Script代码在服务器的控制台输出如下:
<script type=\"text/javascript\">parent." + jsFun + "(\""+data+"\")</script>")
.2、iframe完成加载上面这段代码后解析并执行,这段代码的作用是调用父页面的“jsFun”方法,把消息传入。
3、父页面jsFun函数负责处理接收到的消息。
4、Servlet负责定时执行和输出,源源不断向客户端发送内容。
原来,这个隐藏的iframe起到了一个“纽带”的作用。