项目需求:需要实时的读取日志文件里的数据,并且使用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实现长连接的更多相关文章

  1. ajax 异步长连接遭遇堵塞,“排序执行请求”的问题解决

    今天开发一个网页聊天程序,利用AJAX保持着一个长连接监听新的聊天信息,之后又调用了另外一个AJAX来发言,于是就发生了一个AJAX线程被阻塞的问题. 在未监听到新的聊天信息的之前,发言用的AJAX就 ...

  2. Ajax长连接和SignalR(刷新客户端数据)的区别

    ajax实现长连接   <%@ page language="java" import="java.util.*" pageEncoding=" ...

  3. Web 通信 之 长连接、长轮询(转)

    Web 通信 之 长连接.长轮询(long polling) 基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强 ...

  4. Web 通信 之 长连接、长轮询(long polling)

    基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...

  5. Web 通信 之 长连接、长轮询(long polling)(转)

    基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...

  6. [转]Web 通信 之 长连接、长轮询(long polling)

    本篇文章转载自Web 通信之长连接.长轮询(longpolling),版权归作者所有. 转者按:随着技术的发展,在HTML5中,可以通过WebSocket技术来完成长连接的开发,虽然如此,本文依然存在 ...

  7. Web 通信 之 长连接、长轮询(long polling)(转载)

    基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...

  8. Web 通信 之 长连接、长轮询(转)

    Web 通信 之 长连接.长轮询(long polling) 基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强 ...

  9. 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室

    实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...

随机推荐

  1. Linux(DeepInOS) 下 mysql 的安装与基本配置

    索引: 目录索引 参看代码 GitHub: DeepIn(GNU/Linux) MySQL 一.安装 sudo apt-get install mysql-server 期间需要输入两次密码,root ...

  2. office2019下载以及激活密钥(亲测可用)

    office2019激活密钥 W8W6K-3N7KK-PXB9H-8TD8W-BWTH9  或者: 链接:https://pan.baidu.com/s/1Ch0rc2ZN9I_lwmbjGESTuw ...

  3. 拉勾网爬取全国python职位并数据分析薪资,工作经验,学历等信息

    首先前往拉勾网“爬虫”职位相关页面 确定网页的加载方式是JavaScript加载 通过谷歌浏览器开发者工具分析和寻找网页的真实请求,确定真实数据在position.Ajax开头的链接里,请求方式是PO ...

  4. 微信小程序测试方法总结

    最近的新项目是小程序加web端后台管理 主要找了些文章方便自己使用也分享给大家: 小程序官方文档 https://developers.weixin.qq.com/miniprogram/design ...

  5. php 表单提交大量数据发生丢失的解决方法

    最近在项目中,出现一个奇怪的现象,有一个大form里面有上千个input,提交的时候,老是发现post过来的数据不完整,一开始还怀疑是html 表单名称有冲突,排除掉了.然后,网上找了一堆,php.i ...

  6. python3 time模块

    import time '''查看系统时间拿到的是一个数字(时间戳)从1970-01-01 00:00:00开始计算,以秒为单位'''print(time.time()) 执行结果:155650817 ...

  7. Spring Security(二十九):9.4.1 ExceptionTranslationFilter

    ExceptionTranslationFilter is a Spring Security filter that has responsibility for detecting any Spr ...

  8. Linux内核入门到放弃-Ext2数据结构-《深入Linux内核架构》笔记

    Ext2文件系统 物理结构 结构概观 块组是该文件系统的基本成分,容纳了文件系统的其他结构.每个文件系统都由大量块组组成,在硬盘上相继排布: ----------------------------- ...

  9. [SCOI2016]萌萌哒

    Luogu P3295 mrclr两周前做的题让蒟蒻的我现在做? 第一眼组合计数,如果把数字相同的数位看作一个整体,除了第一位不能为零,剩下的每一位都有$0$~$9$十种. 设不同的位数为$x$,那么 ...

  10. 网易云歌词解析(配合audio标签实现本地歌曲播放,歌词同步)

    先看下效果 github上做的一个音乐播放器: https://github.com/SorrowX/electron-music 中文歌曲 英文歌曲(如果有翻译的中文给回返回出去) 韩文歌曲 来看下 ...