linux查看实时日志命令 查看日志的三种命令分享( 二 )

对于上面的几个接口可能没使用过他的人有点蒙 , 至少我在学习他的时候是这样的 , 看上面的代码 , 我们先要理清逻辑 , 才能明白为什么要这样写 。
实现registerStompEndpoints方法首先是
WebSocketMessageBrokerConfigurer接口 , Spring Boot提供的一个WebSocket配置接口 , 只需要简简单单地配置两下 , 就可以实现一个WebSocket程序 , 这个接口中有8个方法 , 而我们只需要用到三个个 。
然后就是给出前端连接WebSocket所需要的地址 , 如果连连接地址都不给 , 后面步骤怎么继续?这个就是通过实现registerStompEndpoints方法来完成 , 只需要向StompEndpointRegistry中通过addEndpoint添加一个新的”连接点”就可以 , 还可以设置拦截器 , 也就是在前端试图连接的时候 , 如果后端发现这个连接不对劲 , 有猫腻 , 可以拒绝和他连接 , 这步可以通过addInterceptors来完成 。
切记如果使用了SocketJs库 , 那么一定要加入withSockJS 。
@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/log").addInterceptors(new HttpHandshakeInterceptor()).setHandshakeHandler(new DefaultHandshakeHandler() {@Overrideprotected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {return new StompPrincipal(UUID.randomUUID().toString());}}).withSockJS();}保存SessionId和WebSocketSession对应关系这一步是为了方便管理 , 比如主动断开连接 , 需要实现
configureWebSocketTransport接口 , 但是这里的SessionId并不是服务端生成的会话ID , 而是这个WebSocket的会话ID , 每个WebSocket连接都是不同的 。
这里主要考虑到如果前端传过来的文件不存在 , 那么服务端要能主动断开连接 。
@Overridepublic void configureWebSocketTransport(WebSocketTransportRegistration registration) {registration.addDecoratorFactory(new WebSocketHandlerDecoratorFactory() {@Overridepublic WebSocketHandler decorate(WebSocketHandler webSocketHandler) {return new WebSocketHandlerDecorator(webSocketHandler) {@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {log.info("日志监控WebSocket连接,sessionId={}", session.getId());mWebSocketManager.add(session);super.afterConnectionEstablished(session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {mWebSocketManager.remove(session.getId());super.afterConnectionClosed(session, closeStatus);}};}});}监听订阅接着前端通过Stomp的API来订阅一个消息 , 那么我们怎么接收订阅的事件呢?就是通过 @EventListener注解来接收SessionSubscribeEvent事件 。
【linux查看实时日志命令 查看日志的三种命令分享】而前端订阅时就需要传入要监控的日志路径 。这时候我们就能拿到这个WebSocket要监听的日志路径了 。
@EventListenerpublic void handlerSessionSubscribeEvent(SessionSubscribeEvent sessionSubscribeEvent) {....}开启tail进程接着我们要为每个WebSocket都开启一个线程 , 用来执行tail命令 。
@Componentpublic class TailLog {public static final int MAX_LOG = 3;private List<LogMonitorExecute> mLogMonitorExecutes = new CopyOnWriteArrayList<>();/*** Log线程池*/private ExecutorService mExecutors = Executors.newFixedThreadPool(MAX_LOG);public void addMonitor(LogMonitorObject object) {LogMonitorExecute logMonitorExecute = new LogMonitorExecute(object);mExecutors.execute(logMonitorExecute);mLogMonitorExecutes.add(logMonitorExecute);}public void stopMonitor(String sessionId) {if (sessionId == null) {return;}for (LogMonitorExecute logMonitorExecute : mLogMonitorExecutes) {if (sessionId.equals(logMonitorExecute.getLogMonitorObject().getSessionId())) {logMonitorExecute.stop();mLogMonitorExecutes.remove(logMonitorExecute);}}}public boolean isArriveMaxLog() {return mLogMonitorExecutes.size() == MAX_LOG;}}最终执行者 , 其中的stop()方法是在WebSocket断开连接时执行的 。那么需要事先保存好sessionId和LogMonitorExecute的对应关系 。当文件有新变化时 , 发送给对应的WebSocket 。
public class LogMonitorExecute implements Runnable {private static final Logger log = LoggerFactory.getLogger(LogMonitorExecute.class.getName());/*** 监控的对象*/private LogMonitorObject mLogMonitorObject;private volatile boolean isStop = false;/*** tail 进程对象*/private Process mProcess;public LogMonitorExecute(LogMonitorObject logMonitorObject) {mLogMonitorObject = logMonitorObject;}public LogMonitorObject getLogMonitorObject() {return mLogMonitorObject;}@Overridepublic void run() {try {String path = Paths.get(mLogMonitorObject.getPath(), mLogMonitorObject.getName()).toString();log.info("{}对{}开始进行日志监控", mLogMonitorObject.getSessionId(), path);mProcess = Runtime.getRuntime().exec(new String[]{"bash", "-c", "tail -f " + path});InputStream inputStream = mProcess.getInputStream();BufferedReader mBufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));String buffer = null;while (!Thread.currentThread().isInterrupted() && !isStop) {buffer = mBufferedReader.readLine();if (mLogMonitorObject.getTailLogListener() != null) {mLogMonitorObject.getTailLogListener().onNewLine(mLogMonitorObject.getName(), mLogMonitorObject.getPath(), buffer);continue;}break;}mBufferedReader.close();} catch (Exception e) {e.printStackTrace();}log.info("{}退出对{}的监控", mLogMonitorObject.getSessionId(), mLogMonitorObject.getPath() + "/" + mLogMonitorObject.getName());}public void stop() {mProcess.destroy();isStop = true;}}