
com.ajaxjs.developer.TomcatLogController Maven / Gradle / Ivy
package com.ajaxjs.developer;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.function.Consumer;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import com.ajaxjs.Version;
import com.ajaxjs.config.GetConfig;
import com.ajaxjs.util.logger.FileHandler;
import com.ajaxjs.util.logger.LogHelper;
/**
* 通过浏览器 WebSocket 技术查看服务端 Tomcat 输出日志
*
* @author sp42 [email protected]
*
*/
@RequestMapping("/admin/common/tomcat-log")
@ServerEndpoint("/tomcat_log")
public class TomcatLogController {
private static final LogHelper LOGGER = LogHelper.getLog(TomcatLogController.class);
@Autowired
private GetConfig cfg;
/**
* 日志跟踪器
*/
private LogFileTailer tailer;
/**
* 新的 WebSocket 请求开启
*/
@OnOpen
public void onOpen(Session session) {
if (Version.isDebug || !cfg.getBol("forDelevelopers.enableWebSocketLogOutput")) {
try {
session.getBasicRemote().sendText("配置未开启实时浏览 Tomcat 日志,或者正在调试模式中。");
} catch (IOException e) {
LOGGER.warning(e);
}
return;
}
tailer = new LogFileTailer(FileHandler.LOG_PATH, 1000, true);
tailer.setTailing(true);
tailer.addListener(log -> {
try {
session.getBasicRemote().sendText(log + "
");
} catch (IOException e) {
LOGGER.warning(e);
}
});
tailer.start();
}
/**
* WebSocket 请求关闭
*/
@OnClose
public void onClose() {
if (tailer != null)
tailer.setTailing(false);
}
@OnError
public void onError(Throwable e) {
LOGGER.warning(e);
}
/**
* 实现Linux Tail 功能跟踪日志,可持续监控某日志信息。 Linux
* tail命令用途是依照要求将指定的文件的最后部分输出到标准设备,通常是终端,通俗讲来,就是把某个档案文件的最后几行显示到终端上,假设该档案有更新,tail会自己主动刷新,确保你看到最新的档案内容。
*
* 参考:https://blog.51cto.com/6140717/1052845
* https://www.cnblogs.com/snowater/p/7603611.html
* https://blog.csdn.net/xxgwo/article/details/51198113
*
* @author sp42 [email protected]
*
*/
public static class LogFileTailer extends Thread {
/**
* 要监视的文本文件
*/
private long sampleInterval = 2000;
/**
* 读取时间间隔
*/
private File logfile;
/**
* 是否显示文件头?还是说只显示后面变化的部分
*/
private boolean startAtBeginning;
/**
* 自定义的回调事件
*/
private Consumer callback;
/**
* 监视开关,true = 打开监视
*/
private boolean tailing;
/**
*
* @param file 要监视的文本文件
* @param sampleInterval 读取时间间隔
* @param startAtBeginning 是否显示文件头?还是说只显示后面变化的部分
*/
public LogFileTailer(String file, long sampleInterval, boolean startAtBeginning) {
logfile = new File(file);
this.sampleInterval = sampleInterval;
this.startAtBeginning = startAtBeginning;
}
/**
* 设置回调事件
*
* @param callback 自定义的回调事件
*/
public void addListener(Consumer callback) {
this.callback = callback;
}
/**
* 监视开关,true = 打开监视
*
* @param tailing true = 打开监视
*/
public void setTailing(boolean tailing) {
this.tailing = tailing;
}
@Override
public void run() {
long filePointer = startAtBeginning ? 0 : logfile.length();
try {
RandomAccessFile file = new RandomAccessFile(logfile, "r");
while (tailing) {
long fileLength = logfile.length();
if (fileLength < filePointer) {
file = new RandomAccessFile(logfile, "r");
filePointer = 0;
}
if (fileLength > filePointer) {
file.seek(filePointer);
String line = file.readLine();
while (line != null) {
line = new String(line.getBytes("ISO-8859-1"), "utf-8");
if (callback != null)
callback.accept(line);
line = file.readLine();
}
filePointer = file.getFilePointer();
}
sleep(sampleInterval);
}
file.close();
} catch (IOException | InterruptedException e) {
LOGGER.warning(e);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy