以前面的博客为基础,最近一篇为Spring Boot 入门(十):集成Redis哨兵模式,实现Mybatis二级缓存。本篇博客主要介绍了Spring Boot集成 Web Socket进行日志的推送,并实时显示在页面上。

1.导入jar包

第一个jar包是websocket的,第二个jar包是关于环形队列的jar包,本案例是通过本地队列存储日志。有条件的话,最好通过中间件存储(eg:redis,mq……)。通过本地队列存储日志会存在日志丢失的情况,且日志量太大,会把页面卡死。

  <!--begin web socket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>
<!--end web socket-->

2.增加监听器

(1).在logback中增加监听器

并根据logback编写相应的监听器ProcessLogFilter

 @Service
public class ProcessLogFilter extends Filter<ILoggingEvent> { @Override
public FilterReply decide(ILoggingEvent event) {
LoggerMessage loggerMessage = new LoggerMessage(
event.getMessage()
, DateFormat.getDateTimeInstance().format(new Date(event.getTimeStamp())),
event.getThreadName(),
event.getLoggerName(),
event.getLevel().levelStr
);
LoggerDisruptorQueue.publishEvent(loggerMessage);
return FilterReply.ACCEPT;
}
}

该监听器将监听的日志消息推送到本地消息队列中,然后页面通过 Web Socket 去此队列获取日志信息,从而在页面显示

(2).编写日志处理器

 //进程日志事件内容载体
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoggerEvent {
private LoggerMessage log;
}
 /**
* Content :进程日志事件工厂类
*/
public class LoggerEventFactory implements EventFactory<LoggerEvent> {
@Override
public LoggerEvent newInstance() {
return new LoggerEvent();
}
}
 /**
* Content :进程日志事件处理器
*/
@Component
public class LoggerEventHandler implements EventHandler<LoggerEvent> { @Autowired
private SimpMessagingTemplate messagingTemplate; @Override
public void onEvent(LoggerEvent stringEvent, long l, boolean b) {
messagingTemplate.convertAndSend("/topic/pullLogger", stringEvent.getLog());
}
}

日志事件处理器的作用是监听本地环形队列中的消息,如果有消息,就会将这些消息推送到 Socket 管道中

(3).编写页面

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>欢迎页</title>
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script src="plugins/jQuery/jquery-2.2.3.min.js"></script>
<script src="js/websocket/sockjs.min.js"></script>
<script src="js/websocket/stomp.min.js"></script>
</head>
<body>
<div class="panel panel-default">
<h1>jvm进程内的日志</h1>
<button onclick="openSocket()">开启日志</button>
<button onclick="closeSocket()">关闭日志</button>
<div id="log-container" style="height: 600px; overflow-y: scroll; background: #333; color: #aaa; padding: 10px;">
<div></div>
</div>
</div>
<script>
var stompClient = null;
$(document).ready(function () {
openSocket();
}); function openSocket() {
if (stompClient == null) {
var socket = new SockJS('http://localhost:8080/websocket?token=kl');
stompClient = Stomp.over(socket);
stompClient.connect({token: "kl"}, function (frame) {
stompClient.subscribe('/topic/pullLogger', function (event) {
var content = JSON.parse(event.body);
$("#log-container div").append("<font color='red'>" + content.timestamp + "</font>|<font color='highlight'>" + content.level + "</font> |<font color='green'>" + content.threadName + "</font>| <font color='boldMagenta'>" + content.className + "</font>|<font color='cyan'>" + content.body + "</font>").append("<br/>");
$("#log-container").scrollTop($("#log-container div").height() - $("#log-container").height());
}, {
token: "kltoen"
});
});
}
} function closeSocket() {
if (stompClient != null) {
stompClient.disconnect();
stompClient = null;
}
}
</script>
</body>
</html>

页面链接web Socket服务器,如果有消息,就能获取

(4).其他辅助类

环形本地队列类

 package com.learn.hello.system.common.queue;

 import com.learn.hello.modules.entity.LoggerMessage;
import com.learn.hello.system.common.event.LoggerEvent;
import com.learn.hello.system.common.event.LoggerEventFactory;
import com.learn.hello.system.common.event.LoggerEventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; /**
* Content :Disruptor 环形队列
*/
@Component
public class LoggerDisruptorQueue { private Executor executor = Executors.newCachedThreadPool(); // The factory for the event
private LoggerEventFactory factory = new LoggerEventFactory(); // Specify the size of the ring buffer, must be power of 2.
private int bufferSize = 2 * 1024; // Construct the Disruptor
private Disruptor<LoggerEvent> disruptor = new Disruptor<>(factory, bufferSize, executor);
; private static RingBuffer<LoggerEvent> ringBuffer; @Autowired
LoggerDisruptorQueue(LoggerEventHandler eventHandler) {
disruptor.handleEventsWith(eventHandler);
this.ringBuffer = disruptor.getRingBuffer();
disruptor.start();
} public static void publishEvent(LoggerMessage log) {
long sequence = ringBuffer.next(); // Grab the next sequence
try {
LoggerEvent event = ringBuffer.get(sequence); // Get the entry in the Disruptor
// for the sequence
event.setLog(log); // Fill with data
} finally {
ringBuffer.publish(sequence);
}
} }

消息实体类

 package com.learn.hello.modules.entity;

 import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; // 日志实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoggerMessage {
private String body;
private String timestamp;
private String threadName;
private String className;
private String level;
}

3.效果

页面中的颜色可以自行设置

.

Spring Boot 入门(十一):集成 WebSocket, 实时显示系统日志的更多相关文章

  1. Spring Boot 入门(十二):报表导出,对比poi、jxl和esayExcel的效率

    本片博客是紧接着Spring Boot 入门(十一):集成 WebSocket, 实时显示系统日志写的 关于poi.jxl和esayExcel的介绍自行百度. jxl最多支持03版excel,所以单个 ...

  2. Spring boot入门(三):SpringBoot集成结合AdminLTE(Freemarker),利用generate自动生成代码,利用DataTable和PageHelper进行分页显示

    关于SpringBoot和PageHelper,前篇博客已经介绍过Spring boot入门(二):Spring boot集成MySql,Mybatis和PageHelper插件,前篇博客大致讲述了S ...

  3. Spring boot 入门(四):集成 Shiro 实现登陆认证和权限管理

    本文是接着上篇博客写的:Spring boot 入门(三):SpringBoot 集成结合 AdminLTE(Freemarker),利用 generate 自动生成代码,利用 DataTable 和 ...

  4. Spring boot入门(二):Spring boot集成MySql,Mybatis和PageHelper插件

    上一篇文章,写了如何搭建一个简单的Spring boot项目,本篇是接着上一篇文章写得:Spring boot入门:快速搭建Spring boot项目(一),主要是spring boot集成mybat ...

  5. Spring Boot 入门(六):集成 treetable 和 zTree 实现树形图

    本篇文章是接着Spring Boot 入门(五):集成 AOP 进行日志管理写的,主要集成了树形图,在部门列表或者权限列表中,树形图经常被用上.主要是根据相应的 API 凭借 html 字符串 1.t ...

  6. Spring Boot 入门(五):集成 AOP 进行日志管理

    本篇文章是接着 Spring boot 入门(四):集成 Shiro 实现登陆认证和权限管理写的,按照前面几篇博客的教程,可以搭建一个简单的项目,主要包含了 Pagehelper+MyBatis 分页 ...

  7. Spring Boot 入门(七):集成 swagger2

    本片文章是基于前一篇写的,<Spring Boot 入门(六):集成 treetable 和 zTree 实现树形图>,本篇主要介绍了spring boot集成swagger2.关于swa ...

  8. Spring Boot 入门(九):集成Quartz定时任务

    本片文章续<Spring Boot 入门(八):集成RabbitMQ消息队列>,关于Quartz定时任务请参考<Quartz的基本使用之入门(2.3.0版本)> spring ...

  9. Spring Boot 入门(八):集成RabbitMQ消息队列

    本片文章续<Spring Boot 入门(七):集成 swagger2>,关于RabbitMQ的介绍请参考<java基础(六):RabbitMQ 入门> 1.增加依赖 < ...

随机推荐

  1. Lifecycle mapping "org.eclipse.m2e.jdt.JarLifecycleMapping" Eclipse Maven报错

    eclipse 项目中报错Lifecycle mapping "org.eclipse.m2e.jdt.JarLifecycleMapping" is not available, ...

  2. java 集合类 & 容器

    为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就要对对象进行存储,集合就是存储对象最常用的一种方式. 数组和集合类同是容器,有何不同? 数组虽然也可以存储 ...

  3. Tomcat停,图片名字中文显示不出来

    Tomcat停,图片名字中文显示不出来     Tomcat下,图片名字中文显示不出来在tomcat的server.xml中加入URIEncoding="utf-8"<Con ...

  4. 安装vue-cli和安装nuxt

    安装vue-cli:1.npm install vue-cli -g2.vue install webpack 项目名3.cd 项目名4.npm install5.npm i webpack-dev- ...

  5. win10系统激活 快捷方式

    系统不定期就会提示激活,每次激活都是找各种工具折腾,今天捣鼓简单的脚本直接激活~~ 首先查看自己系统的版本,后面才能找到合适的激活码 win+R 启动程序 输入 winver 即可查看系统版本 2.查 ...

  6. H3C RIP路由表的初始化

  7. HDU 1540 Tunnel Warfare (线段树)

    Tunnel Warfare Problem Description During the War of Resistance Against Japan, tunnel warfare was ca ...

  8. H3C 根据主机地址数划分子网

  9. [学习笔记]Pollard-Rho

    之前学的都是假的 %%zzt Miller_Rabin:Miller-Rabin与二次探测 大质数分解: 找到所有质因子,再logn搞出质因子的次数 方法:不断找到一个约数d,递归d,n/d进行分解, ...

  10. js求1到任意数之间的所有质数

    何为质数: 只能被1 和 自身 整除的数; 方法: 利用js中求模, 看是否有余数. ---> 3%2 = 1; 5%2 = 3......... 代码如下: function test (n) ...