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 {
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,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> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |