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 ...
随机推荐
- win7 64 位操作系统,进程System,PID为4,扫描连接局域网ip地址的139和445端口
偶然发现电脑的System进程不间断扫描连接局域网内的其它IP对应的445和139端口,这是个问题. 上网搜索,立即关闭139端口的监听. 方法如下: 本地连接属性-TCP/IP属性-高级-WINS选 ...
- The account that is running SQL Server Setup does not have one or all of the following rights: the right to back up files and directories, the right to manage auditing and the security log and the rig
安装SQL SERVER 是规则检查提示权限问题 运行secpol.msc,没有Debug program权限,添加即可,如果已加域则要在域策略修改,或退域安装后在加域.
- 搭建一个dubbo+zookeeper平台
本篇主要是来分享从头开始搭建一个dubbo+zookeeper平台的过程,其中会简要介绍下dubbo服务的作用. 首先,看下一般网站架构随着业务的发展,逻辑越来越复杂,数据量越来越大,交互越来越多之后 ...
- java反射(java.lang.reflect) ---普通单例模式唯一性问题
1. 普通的饱汉式.饿汉式 package org.bighead.test2; public class TestPrivate { private String str = "strPr ...
- 微信js-sdk开发获取签名和获取地理位置接口示例
###微信js-sdk开发获取签名和获取地理位置接口示例 前言:在做微信公众号开发时需要获取用户的地理位置信息,之前通过高德或者百度.腾讯等地图的api时发现经常获取不到,毕竟第三方的东西,后来改为采 ...
- 与非java语言使用RSA加解密遇到的问题:algid parse error, not a sequence
遇到的问题 在一个与Ruby语言对接的项目中,决定使用RSA算法来作为数据传输的加密与签名算法.但是,在使用Ruby生成后给我的私钥时,却发生了异常:IOException: algid parse ...
- logback.xml的使用,将日志异步保存到数据库中
想要把日志异步保存到数据库中,首先需要创建一个数据库,然后创建三张固定的表: https://github.com/xiaorenwu-dashijie/logback.git <?xml ve ...
- Django 简介
一 MVC 与 MTV 模型 (1)MVC C: controller 控制器(url分发和视图函数) V: 存放html文件 M: model:数据库操作 Web服务器开发领域里著名的MVC模式 ...
- There Are Now 3 Apache Spark APIs. Here’s How to Choose the Right One
See Apache Spark 2.0 API Improvements: RDD, DataFrame, DataSet and SQL here. Apache Spark is evolvin ...
- ElasticSearch(八):elasticsearch.yml配置说明
集群名称:cluster.name: my-application确保在不同的环境中的集群的名称不重复,否则,节点可能会连接到错误的集群上 节点名称:node.name: node-1默认情况下,当节 ...