ajax实现长连接
项目需求:需要实时的读取日志文件里的数据,并且使用Echart实时更新折线图。
使用ajax实现客户端与服务器端的数据传输。
目的:我想通过ajax与服务器建立一个长连接,服务器会不断的传输数据给前台,由于日志不断的更新,我想把新的数据不断的传给前台。
设计:本来想着使用服务器使用一个死循环去读取日志信息,一个线程去提交数据。
参考:https://www.cnblogs.com/hoojo/p/longPolling_comet_jquery_iframe_ajax.html
发现与想象的不同,这个长连接并不是不间断的连接,而是连接成功一次,传输完数据断开,再重新建立新连接,会重新去调用函数。
由于一开始的理解错误,因为用死循环去读取日志,这样会导致每次都会调用一次函数,这样会开启多个死循环,打开任务管理器,发现CPU和内存的不断飙升,所以每次连接都要跳出死循环。
这样会产生新问题,每次都要重新读日志。
设计,保存上一次读取的位置,避免重头开始。
前台代码:
//异步请求获取数据,递归调用自己,实现长连接
function longPolling() {
$.ajax({
type:'POST',
url:'get',
dataType:'json',
data:postData,
timeout: 20000,
success:function(result){
if(result){
//保存文件指针,再传给后台
postData.lastTimeFileSize = result.pointer
//添加数据
for(var i=0;i<result.axis.length;i++){
datax.push(result.axis[i]);
datay.push(result.series[0].data[i]);
}
//画图
myChart.hideLoading();
myChart.setOption({
xAxis: {
data: datax
},
series: [{
// 根据名字对应到相应的系列
name: 'alpha.water',
data: datay
}]
});
longPolling();
}
},
error:function(XMLHttpRequest, textStatus, errorThrown){
console.error("加载数据失败");
longPolling();
},
});
};
后台代码:
发送数据
public class getData extends HttpServlet {
File logFile = new File("D:\\workspace\\drawChart\\src\\read_log\\log.txt");
private long lastTimeFileSize = 0; // 上次文件大小
//打包数据为Json格式传给前台
public void pickData(HttpServletRequest request,HttpServletResponse response,Float message[][],long pointer) throws ServletException, IOException {
List<String> legend = new ArrayList<String>(Arrays.asList(new String[]{"alpha.water"}));
//x轴时间
List<Float> axis = new ArrayList<Float>(Arrays.asList(message[0]));
List<Series> series=new ArrayList<Series>();
//series
series.add(new Series("alpha.water","line",new ArrayList<Float>(Arrays.asList(message[1]))));
//更改下一行代码,添加多个series
Echarts echarts = new Echarts(legend,axis,series,pointer);
ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(echarts);
System.out.println(objectMapper.writeValueAsString(echarts));
response.setContentType("text/html;charset=utf-8");
//发送数据
PrintWriter out = response.getWriter();
out.write(str);
System.out.println("发送post方法。。。。。。。。。。");
out.flush();
out.close();
}
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
String regEx = "(-?\\d+)(\\.\\d+)?";
String regEx0 = "^Time = [0-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*$";
Pattern pattern = Pattern.compile(regEx);
Pattern pattern0 = Pattern.compile(regEx0);
float alpha = 0;
float p_rgh = 0;
float omega = 0;
float k = 0;
float DTime = 0;
//用来保存所有数据的二维数组
Float message[][] = new Float[14][5];
//计数器,个数据传一次
int flag = -1;
//获取保存的上一次读取的位置
String str = request.getParameter("lastTimeFileSize");
lastTimeFileSize = Long.parseLong(str);
System.out.println(lastTimeFileSize);
try {
long len = logFile.length();
System.out.println(len);
if(lastTimeFileSize >= len){
lastTimeFileSize = len;
try {
//如果读取的速度超过写的速度,等待5秒
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}else{
RandomAccessFile randomFile = new RandomAccessFile(logFile, "r");
randomFile.seek(lastTimeFileSize);
String tmp = null;
while ((tmp = randomFile.readLine()) != null) {
//正则匹配时间
Matcher matcher0 = pattern0.matcher(tmp);
if(matcher0.lookingAt()){
if(flag==4){
//记录读取文件的位置
lastTimeFileSize = randomFile.getFilePointer();
System.out.println(lastTimeFileSize);
//传数据
try {
Thread.sleep(3000);
//由于是根据time决定是否提交,所以提交5次需要读6个time,文件指针会只在time后面,因此要倒回
lastTimeFileSize -= 50;
pickData(request,response,message,lastTimeFileSize);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
randomFile.close();
flag = -1;
break;
}
DTime = Float.parseFloat(tmp.split("=")[1]);
flag++;
message[0][flag] = DTime;
}
//yangmo
//找到 alpha p_rgh Omega k;
else if((tmp.startsWith("smoothSolver: Solving for alpha.water")))
{
String[] splitAddress = tmp.split(",")[1].split("=");
alpha = Float.parseFloat(splitAddress[1]);
System.out.println(flag);
message[1][flag] = alpha;
//System.out.println(alpha);
}
else if((tmp.startsWith("GAMG: Solving for p_rgh")))
{
String[] splitAddress = tmp.split(",")[1].split("=");
p_rgh = Float.parseFloat(splitAddress[1]);
message[2][flag] = p_rgh;
//System.out.println(p_rgh);
}
else if((tmp.startsWith("smoothSolver: Solving for omega")))
{
String[] splitAddress = tmp.split(",")[1].split("=");
omega = Float.parseFloat(splitAddress[1]);
message[3][flag] = omega;
//System.out.println(omega);
}
else if((tmp.startsWith("smoothSolver: Solving for k")))
{
String[] splitAddress = tmp.split(",")[1].split("=");
k = Float.parseFloat(splitAddress[1]);
message[4][flag] = k;
//System.out.println(k);
}
//找到 x,y,z
else if(tmp.equals("Sum of forces"))
{
int j = 5;
for(int i=1;i<=3;i++){
String line = randomFile.readLine();
Matcher matcher = pattern.matcher(line);
//正则匹配数值
while(matcher.find()){
message[j][flag] = Float.parseFloat(matcher.group());
j++;
}
}
}
}
//读到文件的末尾需要把剩余数据的提交
if(flag>-1){
//提交最后的数据
lastTimeFileSize = randomFile.getFilePointer();
lastTimeFileSize -= 50;
pickData(request,response,message,lastTimeFileSize);
}else
{
//等待,可以有效的避免前台无间歇的询问导致CPU占用增大
try {
Thread.sleep(10000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
//其它操作
}
}
}
红色标记内容是相关内容
注意:类中如果使用构造器去传递文件的路径名,则ajax请求会失败
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<servlet>
<description></description>
<display-name>getData</display-name>
<servlet-name>getData</servlet-name>
<servlet-class>read_log.getData</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getData</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>chart.jsp</welcome-file>
</welcome-file-list>
</web-app>
ajax实现长连接的更多相关文章
- ajax 异步长连接遭遇堵塞,“排序执行请求”的问题解决
今天开发一个网页聊天程序,利用AJAX保持着一个长连接监听新的聊天信息,之后又调用了另外一个AJAX来发言,于是就发生了一个AJAX线程被阻塞的问题. 在未监听到新的聊天信息的之前,发言用的AJAX就 ...
- Ajax长连接和SignalR(刷新客户端数据)的区别
ajax实现长连接 <%@ page language="java" import="java.util.*" pageEncoding=" ...
- Web 通信 之 长连接、长轮询(转)
Web 通信 之 长连接.长轮询(long polling) 基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强 ...
- Web 通信 之 长连接、长轮询(long polling)
基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...
- Web 通信 之 长连接、长轮询(long polling)(转)
基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...
- [转]Web 通信 之 长连接、长轮询(long polling)
本篇文章转载自Web 通信之长连接.长轮询(longpolling),版权归作者所有. 转者按:随着技术的发展,在HTML5中,可以通过WebSocket技术来完成长连接的开发,虽然如此,本文依然存在 ...
- Web 通信 之 长连接、长轮询(long polling)(转载)
基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...
- Web 通信 之 长连接、长轮询(转)
Web 通信 之 长连接.长轮询(long polling) 基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强 ...
- 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室
实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...
随机推荐
- 20181112-PostgreSQL数据库dmp文件导入(记录一次数据导入)
20181112-PostgreSQL数据库dmp文件导入 标注:dmp文件导入,场景:多个schema导入 1. 环境准备: postgres集群master节点上,postgres用户执行以下操作 ...
- pycharm导入自定义py文件出错
1. 被导入的py文件不能以数字开头,否则会报错,红色波浪线
- Saltstack_使用指南05_数据系统-Pillar
1. 主机规划 Pillar文档 https://docs.saltstack.com/en/latest/topics/pillar/index.html 注意事项 修改了master或者minio ...
- insert into select的实际用法
INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Table ...
- day 10函数二
今日内容 '''实参:调用函数,在括号内传入的实际值,值可以为常量.变量.表达式或三者的组合*****形参:定义函数,在括号内声明的变量名,用来接受外界传来的值''''''注:形参随着函数的调用 ...
- 初识服务发现及Consul框架的简单使用
初识服务发现及Consul框架的简单使用 1.什么是服务发现? 服务发现组件记录了(大规模)分布式系统中所有服务的信息,人们或者其它服务可以据此找到这些服务. DNS 就是一个简单的例子. 当然, ...
- .NET CORE微服务中CONSUL的相关使用
.NET CORE微服务中CONSUL的相关使用 1.consul在微服务中的作用 consul主要做三件事:1.提供服务到ip的注册 2.提供ip到服务地址的列表查询 3.对提供服务方做健康检查(定 ...
- python3 闭包函数
'''闭包函数:内部函数引用外部函数变量(非全局变量)'''def func(y): x = 1 def func1(): print(x, y) return func1 f = func(2)pr ...
- springBoot集成redisCluster
本文主要内容:springBoot简介,在SpringBoot中如何集成Redis,可配置Redis集群. 关于SpringBoot 你想要的,这里都有:https://spring.io/proje ...
- Gdi绘图
在使用VC开发项目过程中,界面是项目中的一个子模块.虽然界面并不那么重要,把握住核心功能就可以了,但界面美观与否直接关系到用户的体验, 因此我们也应该关注界面的处理. 我们可以在OnEraseBkgn ...