项目需求:需要实时的读取日志文件里的数据,并且使用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. 一个表里有多个字段需要同时使用字典表进行关联显示,如何写sql查询语句

    参考:https://bbs.csdn.net/topics/330032307 数据库里面有一个字典表,这张表里面有id段和对应的名字字段.在另外一个记录的表里面有对应的上述字典表的id,而且有多个 ...

  2. selenium-历史(一)

    简介 Selenium是ThoughtWorks公司研发的一个强大的基于浏览器的开源自动化测试工具,它通常用来编写web应用的自动化测试.早期也即Selenium1.x时期主要使用Selenium R ...

  3. KASAN实现原理【转】

    1. 前言 KASAN是一个动态检测内存错误的工具.KASAN可以检测全局变量.栈.堆分配的内存发生越界访问等问题.功能比SLUB DEBUG齐全并且支持实时检测.越界访问的严重性和危害性通过我之前的 ...

  4. c/c++ 多线程 绕过mutex的保护

    多线程 绕过mutex的保护 mutex,能够解决线程安全的问题,但它不是万能的.下面的例子虽然使用了mutex,但是恶意注入了一个外部函数,导致把被mutex保护的双向链表,让一个外部的指针指向了, ...

  5. DB2增删改不记录日志

    第一步:关闭事务自动提交 C:\DB2>db2set DB2OPTIONS=+c +c永久关闭自动提交,-c永久开启自动提交 第二步:表修改为不记录日志 db2 alter table T1 a ...

  6. 超哥笔记 --nginx入门(6)

    一 NGINX 1 nignx是什么 nginx是一个开源的支持高性能,高并发的web服务和代理服务软件. nginx比他大哥apache性能改进许多,nginx占用的系统资源更少,支持高并发连接,有 ...

  7. springboot mybatis搭建

    非常easy直接写,没有搭建成分 1.目录 2. @RestController public class UserController { @RequestMapping("/hello& ...

  8. k-近邻(KNN)算法改进约会网站的配对效果[Python]

    使用Python实现k-近邻算法的一般流程为: 1.收集数据:提供文本文件 2.准备数据:使用Python解析文本文件,预处理 3.分析数据:可视化处理 4.训练算法:此步骤不适用与k——近邻算法 5 ...

  9. centos查看系统信息命令

    1.cd - :返回上次所在的目录 2.查看系统版本 cat /etc/redhat-release 3.查看linux内核版本1)cat /proc/version 2) uname -a3) un ...

  10. (八)Index and Query a Document

    Let’s now put something into our customer index. We’ll index a simple customer document into the cus ...