项目需求:需要实时的读取日志文件里的数据,并且使用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. 爬虫基础--IO多路复用单线程异步非阻塞

    最近一直的学习爬虫  ,进行基础的学习 性能相关 参考 https://www.cnblogs.com/wupeiqi/p/6229292.html # 目标:单线程实现并发HTTP请求 # # so ...

  2. momentjs的使用

    一.脚本引用 <script src="~/Scripts/moment.js"></script> <script src="~/Scri ...

  3. spingboot一键部署到阿里云(Cloud Toolkit工具)

    一般做法 一键部署工具   前些天在完成一个项目时候需要将springboot项目部署到服务器上, 以下是两种做法 前面介绍的是一般做法: 后面将介绍省去这些步骤的一键部署工具Cloud Toolki ...

  4. ASP.NET基础知识汇总之WebConfig各节点介绍

    web.config虽然一直用,接触最多的也就是节点appSettings和connectionSettings,今天系统的梳理一下,了解一下webconfig各个节点的含义,先简单的浏览一下具体的w ...

  5. Storm入门(三)HelloWorld示例

    一.配置开发环境 storm有两种操作模式: 本地模式和远程模式.使用本地模式的时候,你可以在你的本地机器上开发测试你的topology, 一切都在你的本地机器上模拟出来; 用远程模式的时候你提交的t ...

  6. P5239 回忆京都(洛谷3月月赛T2)

    题目描述 射命丸文在取材中发现了一个好玩的东西,叫做组合数. 组合数的定义如下:从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合.所有组合的数量,就是组合数 ...

  7. 多线程学习笔记-深入理解ThreadPoolExecutor

    java多线程中,线程池的最上层接口是Executor,ExecutorService实现了Executor,是真正的管理线程池的接口,ThreadPoolExecutor间接继承了ExecutorS ...

  8. [JLOI2015]骗我呢

    [JLOI2015]骗我呢 Tags:题解 作业部落 评论地址 TAG:数学,DP 题意 骗你呢 求满足以下条件的\(n*m\)的矩阵的个数对\(10^9+7\)取模 对于矩阵中的第\(i\)行第\( ...

  9. 最简单易懂的Spring Security 身份认证流程讲解

    最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...

  10. 基于 HTML5 的 WebGL 和 VR 技术的 3D 机房数据中心可视化

    前言 在 3D 机房数据中心可视化应用中,随着视频监控联网系统的不断普及和发展, 网络摄像机更多的应用于监控系统中,尤其是高清时代的来临,更加快了网络摄像机的发展和应用. 在监控摄像机数量的不断庞大的 ...