实时展现内容,就像tail -f命令的功能一样,可能不同的人有不同的表述方法,但是其实是殊途同归。
我想在网页上实时展示服务器上某个日志文件(内容随时在变化)的变化,怎么做呢?是有这样的场景的,再比如,我现在需要点击一个按钮执行服务器上的一个shell脚本,脚本会把执行过程中的信息输出到一个文件sh.log中,我现在需要实时展示sh.log的内容,跟上面的那个日志文件也是一个道理。
实现思路:
1.这里最重要的实现就是java里面的RandomAccessFile类,RandomAccessFile类可以得到本次读结束时候的位置并且可以指定从哪个位置开始读。
2.在前端页面通过javascript的setInterval()函数轮循去请求就行了,需要注意的是一定要调用clearInterval(id),不然请求将一直继续
好了,有了上面两个实现思路我把核心代码贴出来,就行了:
html:
<div class="part">实时日志</div> <div id="rtlog"></div>
js:
var interId;//setInterval的id,用于清除轮循 var loc=0;//从哪里开始读文件 interId=setInterval("appendLog()",1000); function appendLog(){ $.ajax({ type: "POST", url: "appendLogRealTime", data:{"pointer":loc}, success: function(data){ if(data.status){//出错了才会进入 $("#rtlog").append(data.info); clearInterval(interId); }else{ if(data.complete){ console.log("正确清除轮循"); clearInterval(interId); } $("#rtlog").append(data.cont+"<br>"); loc=data.pointer; } } }); }
java后端的代码:
@RequestMapping("/appendLogRealTime") @ResponseBody public Map<String, Object> appendLogRealTime(HttpServletRequest request){ Map<String, Object> retMap=new HashMap<String, Object>(); try { Map<String, Object> map=fraudService.appendLogRealTime(request); return map; } catch (Exception e) { logger.info("实时读取日志出错", e); retMap.put("status", "error"); retMap.put("info", "实时读取日志出错,请查看日志获取明细信息"); return retMap; } }
fraudService.appendLogRealTime(HttpServletRequest request);方法:
@Override public Map<String, Object> appendLogRealTime(HttpServletRequest request) throws Exception{ Map<String, Object> retMap=new HashMap<String, Object>(); String realPath = request.getSession().getServletContext().getRealPath("/output.log"); File f=new File(realPath); RandomAccessFile raf=new RandomAccessFile(f, "r"); String reqPointer = request.getParameter("pointer"); long pointer=Long.valueOf(reqPointer); raf.seek(pointer);//移动文件指针位置 String line =null; StringBuffer sb=new StringBuffer(); while((line = raf.readLine())!=null){ line = new String(line.getBytes("ISO-8859-1"),"utf-8");//写入的时候是utf-8,现在也要转为utf-8 pointer = raf.getFilePointer(); //得到本次读完时候的文件指针位置,并返回前端,下次再传入并设置为 //开始读的位置 sb.append(line); } raf.close(); if (sb.toString().contains(logEnd)) { retMap.put("complete", "yes"); } retMap.put("cont", sb.toString()); retMap.put("pointer", pointer); return retMap; }