项目需求:需要实时的读取日志文件里的数据,并且使用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实现长连接
原文地址:https://www.cnblogs.com/zhxuxu/p/9745462.html