log4j输出日志到前端页面

一、简介  

   有些时候webapp有需求将日志输出到前台页面,便于开发者查看日志,本篇将介绍如何将日志输出到前台显示;

二、准备

  WebSocket技术、log4j、miniui(本项目所用前端,其他也一样);

三、参考文档

  受到此博主的启发,特感谢此博主:https://blog.csdn.net/xiao__gui/article/details/50041673

四、过程

  1、log4j配置

  

log4j.rootLogger=debug,stdout,WA
# 选用WriterAppender作为Appender,表示以流的形式输出,这个Appender一般很少用,是常用Appender的父类 log4j.appender.WA=org.apache.log4j.WriterAppender log4j.appender.WA.Threshold=debug log4j.appender.WA.layout=org.apache.log4j.PatternLayout
# %X{ip} 输出本服务器的ip,通过MDC输入(见后面描述) log4j.appender.WA.layout.ConversionPattern=%d{ISO8601} - [%X{ip}] -%5p %c{1}:%L - %m%n

  2、WebSocket后台编写

import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Writer; import java.net.InetAddress; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import org.apache.log4j.Appender; import org.apache.log4j.Logger; import org.apache.log4j.MDC; import org.apache.log4j.WriterAppender; /** * @Author : ycj * @Description : 日志文件处理websocket服务 * @CreateDate : 2018/6/12 9:42 */ @ServerEndpoint("/log") public class LogWebsocketHandle { private PipedReader reader; private Writer writer; /** * WebSocket请求开启 */ @OnOpen public void onOpen(Session session) { Logger root = Logger.getRootLogger(); try { // 获取本服务器id String hostAddress = InetAddress.getLocalHost().getHostAddress();
   // MDC是key-value结构,有兴趣的可以去了解下,在log4j的配置中设置 %X{ip},在日志中输出 MDC.put("ip",hostAddress); Appender appender = root.getAppender("WA");
   // 通过管道流进行线程间的通讯 reader = new PipedReader(); writer = new PipedWriter( reader) ; ((WriterAppender) appender).setWriter(writer); // 启动新的线程 LogThread thread = new LogThread(reader, session); thread.start(); } catch (Exception ex) { ex.printStackTrace(); } } /** * WebSocket请求关闭,关闭请求时调用此方法,关闭流 */ @OnClose public void onClose() { try { if(reader != null) { reader.close(); } } catch (Exception ex) { ex.printStackTrace(); } try { if(writer != null) { writer.close(); } } catch (Exception ex) { ex.printStackTrace(); } } @OnError public void onError(Throwable thr) { thr.printStackTrace(); } }

  LogThread 线程

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PipedReader; import javax.websocket.Session; /** * 新线程 */ public class LogThread extends Thread { private BufferedReader reader; private Session session; public LogThread(PipedReader pipedReader, Session session) { this.reader = new BufferedReader(pipedReader); this.session = session; } @Override public void run() { String line; try { while((line = reader.readLine()) != null) { // 将实时日志通过WebSocket发送给客户端 session.getBasicRemote().sendText(line + "<br>"); } } catch (IOException e) { e.printStackTrace(); } } }

  

  2、前端编写

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>tail log</title>
 <!-- 此boot.js不需要--> <script src="../../boot.js"></script> <script src="../../js/jquery-1.6.2.min.js"></script> </head> <body> <div id="log-container" style="height: 480px; overflow-y: scroll; background: #333;padding: 10px;"> <div> </div> </div> <div>
  <!-- 下面div用的是miniui的样式,其他的稍微改变一下即可--> <div id="ck1" name="product" class="mini-checkbox" checked = "true" readOnly="false" text="是否滚动" onvaluechanged="onValueChanged" style="left: 20px"></div> <a style="left: 30px;top: 1px" class="mini-button mini-button-info" onclick="clearContext()">清屏</a> </div> </body> <script> // 控制是否滚动显示日志 var checked = true; function onValueChanged(e) { checked = this.getChecked(); } $(document).ready(function() { // 指定websocket路径,此地址建议根据用js动态获取 var websocket = new WebSocket('ws://localhost:8080/log'); websocket.onmessage = function(event) { // 接收服务端的实时日志并添加到HTML页面中(error显示红色) if (event.data.search("ERROR") != -1) { $("#log-container div").append(event.data).css("color", "#AA0000"); } else { $("#log-container div").append(event.data).css("color", "#aaa"); } // 是否滚动 if (checked) { // 滚动条滚动到最低部 $("#log-container").scrollTop($("#log-container div").height() - $("#log-container").height()); } }; }); // 清屏日志 function clearContext() { $("#log-container div").empty(); } </script> </body> </html>

  3、js获取项目路径代码(供参考)

// 此方式获取的bootPath项目根路径放入WebSocket路径需要进行截取
JsPath = function (js) { var scripts = document.getElementsByTagName("script"); var path = ""; for (var i = 0, l = scripts.length; i < l; i++) { var src = scripts[i].src; if (src.indexOf(js) != -1) { var ss = src.split(js); path = ss[0]; break; } } var href = location.href; href = href.split("#")[0]; href = href.split("?")[0]; var ss = href.split("/"); ss.length = ss.length - 1; href = ss.join("/"); if (path.indexOf("https:") == -1 && path.indexOf("http:") == -1 && path.indexOf("file:") == -1 && path.indexOf("\/") != 0) { path = href + "/" + path; } return path; } var bootPATH = JsPath("boot.js");

   4、成果展示

 

猜你喜欢

转载自www.cnblogs.com/ycjcham/p/9243455.html