@@ -1 +1,388 @@ | |||
# spring-boot-demo-websocket | |||
> 此 demo 主要演示了 Spring Boot 如何集成 WebSocket,实现后端主动往前端推送数据。网上大部分websocket的例子都是聊天室,本例主要是推送服务器状态信息。前端页面基于vue和element-ui实现。 | |||
## 1. 代码 | |||
### 1.1. pom.xml | |||
```xml | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>spring-boot-demo-websocket</artifactId> | |||
<version>1.0.0-SNAPSHOT</version> | |||
<name>spring-boot-demo-websocket</name> | |||
<description>Demo project for Spring Boot</description> | |||
<parent> | |||
<groupId>com.xkcoding</groupId> | |||
<artifactId>spring-boot-demo</artifactId> | |||
<version>1.0.0-SNAPSHOT</version> | |||
</parent> | |||
<properties> | |||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |||
<java.version>1.8</java.version> | |||
<oshi.version>3.9.1</oshi.version> | |||
</properties> | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-web</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-websocket</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-test</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.github.oshi</groupId> | |||
<artifactId>oshi-core</artifactId> | |||
<version>${oshi.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>cn.hutool</groupId> | |||
<artifactId>hutool-all</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.google.guava</groupId> | |||
<artifactId>guava</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.projectlombok</groupId> | |||
<artifactId>lombok</artifactId> | |||
<optional>true</optional> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<finalName>spring-boot-demo-websocket</finalName> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-maven-plugin</artifactId> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> | |||
``` | |||
### 1.2. WebSocketConfig.java | |||
```java | |||
/** | |||
* <p> | |||
* WebSocket配置 | |||
* </p> | |||
* | |||
* @package: com.xkcoding.websocket.config | |||
* @description: WebSocket配置 | |||
* @author: yangkai.shen | |||
* @date: Created in 2018-12-14 15:58 | |||
* @copyright: Copyright (c) 2018 | |||
* @version: V1.0 | |||
* @modified: yangkai.shen | |||
*/ | |||
@Configuration | |||
@EnableWebSocket | |||
@EnableWebSocketMessageBroker | |||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { | |||
@Override | |||
public void registerStompEndpoints(StompEndpointRegistry registry) { | |||
// 注册一个 /notification 端点,前端通过这个端点进行连接 | |||
registry.addEndpoint("/notification") | |||
//解决跨域问题 | |||
.setAllowedOrigins("*") | |||
.withSockJS(); | |||
} | |||
@Override | |||
public void configureMessageBroker(MessageBrokerRegistry registry) { | |||
//定义了一个客户端订阅地址的前缀信息,也就是客户端接收服务端发送消息的前缀信息 | |||
registry.enableSimpleBroker("/topic"); | |||
} | |||
} | |||
``` | |||
### 1.3. 服务器相关实体 | |||
> 此部分实体 参见包路径 [com.xkcoding.websocket.model](./src/main/java/com/xkcoding/websocket/model) | |||
### 1.4. ServerTask.java | |||
```java | |||
/** | |||
* <p> | |||
* 服务器定时推送任务 | |||
* </p> | |||
* | |||
* @package: com.xkcoding.websocket.task | |||
* @description: 服务器定时推送任务 | |||
* @author: yangkai.shen | |||
* @date: Created in 2018-12-14 16:04 | |||
* @copyright: Copyright (c) 2018 | |||
* @version: V1.0 | |||
* @modified: yangkai.shen | |||
*/ | |||
@Slf4j | |||
@Component | |||
public class ServerTask { | |||
@Autowired | |||
private SimpMessagingTemplate wsTemplate; | |||
/** | |||
* 按照标准时间来算,每隔 2s 执行一次 | |||
*/ | |||
@Scheduled(cron = "0/2 * * * * ?") | |||
public void websocket() throws Exception { | |||
log.info("【推送消息】开始执行:{}", DateUtil.formatDateTime(new Date())); | |||
// 查询服务器状态 | |||
Server server = new Server(); | |||
server.copyTo(); | |||
ServerVO serverVO = ServerUtil.wrapServerVO(server); | |||
Dict dict = ServerUtil.wrapServerDict(serverVO); | |||
wsTemplate.convertAndSend(WebSocketConsts.PUSH_SERVER, JSONUtil.toJsonStr(dict)); | |||
log.info("【推送消息】执行结束:{}", DateUtil.formatDateTime(new Date())); | |||
} | |||
} | |||
``` | |||
### 1.5. server.html | |||
```html | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<title>服务器信息</title> | |||
<link href="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.11/theme-chalk/index.css" rel="stylesheet"> | |||
<style> | |||
.el-row { | |||
margin-bottom: 20px; | |||
} | |||
.el-row:last-child { | |||
margin-bottom: 0; | |||
} | |||
.sysFile { | |||
margin-bottom: 5px; | |||
} | |||
.sysFile:last-child { | |||
margin-bottom: 0; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div id="app"> | |||
<el-container> | |||
<el-header> | |||
<el-button @click="_initSockJs" type="primary" :disabled="isConnected">手动连接</el-button> | |||
<el-button @click="_destroySockJs" type="danger" :disabled="!isConnected">断开连接</el-button> | |||
</el-header> | |||
<el-main> | |||
<el-row :gutter="20"> | |||
<el-col :span="12"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>CPU信息</span> | |||
</div> | |||
<el-table size="small" border :data="server.cpu" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</el-card> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>内存信息</span> | |||
</div> | |||
<el-table size="small" border :data="server.mem" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>服务器信息</span> | |||
</div> | |||
<el-table size="small" border :data="server.sys" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>Java虚拟机信息</span> | |||
</div> | |||
<el-table size="small" border :data="server.jvm" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>磁盘状态</span> | |||
</div> | |||
<div class="sysFile" v-for="(item,index) in server.sysFile" :key="index"> | |||
<el-table size="small" border :data="item" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</div> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</el-main> | |||
</el-container> | |||
</div> | |||
</body> | |||
<script src="js/sockjs.min.js"></script> | |||
<script src="js/stomp.js"></script> | |||
<script src="https://cdn.bootcss.com/vue/2.5.21/vue.min.js"></script> | |||
<script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.11/index.js"></script> | |||
<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script> | |||
<script> | |||
const wsHost = "http://localhost:8080/demo/notification"; | |||
const wsTopic = "/topic/server"; | |||
const app = new Vue({ | |||
el: '#app', | |||
data: function () { | |||
return { | |||
isConnected: false, | |||
stompClient: {}, | |||
socket: {}, | |||
server: { | |||
cpu: [], | |||
mem: [], | |||
jvm: [], | |||
sys: [], | |||
sysFile: [] | |||
} | |||
} | |||
}, | |||
methods: { | |||
_getServerInfo() { | |||
axios.get('/demo/server') | |||
.then((response) => { | |||
this.server = response.data | |||
}); | |||
}, | |||
_initSockJs() { | |||
this._getServerInfo(); | |||
this.socket = new SockJS(wsHost); | |||
this.stompClient = Stomp.over(this.socket); | |||
this.stompClient.connect({}, (frame) => { | |||
console.log('websocket连接成功:' + frame); | |||
this.isConnected = true; | |||
this.$message('websocket服务器连接成功'); | |||
// 另外再注册一下消息推送 | |||
this.stompClient.subscribe(wsTopic, (response) => { | |||
this.server = JSON.parse(response.body); | |||
}); | |||
}); | |||
}, | |||
_destroySockJs() { | |||
if (this.stompClient != null) { | |||
this.stompClient.disconnect(); | |||
this.socket.onclose; | |||
this.socket.close(); | |||
this.stompClient = {}; | |||
this.socket = {}; | |||
this.isConnected = false; | |||
this.server.cpu = []; | |||
this.server.mem = []; | |||
this.server.jvm = []; | |||
this.server.sys = []; | |||
this.server.sysFile = []; | |||
} | |||
console.log('websocket断开成功!'); | |||
this.$message.error('websocket断开成功!'); | |||
} | |||
}, | |||
mounted() { | |||
this._initSockJs(); | |||
}, | |||
beforeDestroy() { | |||
this._destroySockJs(); | |||
} | |||
}) | |||
</script> | |||
</html> | |||
``` | |||
## 2. 运行方式 | |||
1. 启动 `SpringBootDemoWebsocketApplication.java` | |||
2. 访问 http://localhost:8080/demo/server.html | |||
## 3. 运行效果 | |||
![image-20181217110240322](assets/image-20181217110240322-5015760.png) | |||
![image-20181217110304065](assets/image-20181217110304065-5015784.png) | |||
![image-20181217110328810](assets/image-20181217110328810-5015808.png) | |||
![image-20181217110336017](assets/image-20181217110336017-5015816.png) | |||
## 4. 参考 | |||
### 4.1. 后端 | |||
1. Spring Boot 整合 Websocket 官方文档:https://docs.spring.io/spring/docs/5.1.2.RELEASE/spring-framework-reference/web.html#websocket | |||
2. 服务器信息采集 oshi 使用:https://github.com/oshi/oshi | |||
### 4.2. 前端 | |||
1. vue.js 语法:https://cn.vuejs.org/v2/guide/ | |||
2. element-ui 用法:http://element-cn.eleme.io/#/zh-CN | |||
3. stomp.js 用法:https://github.com/jmesnil/stomp-websocket | |||
4. sockjs 用法:https://github.com/sockjs/sockjs-client |
@@ -0,0 +1,36 @@ | |||
package com.xkcoding.websocket.controller; | |||
import cn.hutool.core.lang.Dict; | |||
import com.xkcoding.websocket.model.Server; | |||
import com.xkcoding.websocket.payload.ServerVO; | |||
import com.xkcoding.websocket.util.ServerUtil; | |||
import org.springframework.web.bind.annotation.GetMapping; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.web.bind.annotation.RestController; | |||
/** | |||
* <p> | |||
* 服务器监控Controller | |||
* </p> | |||
* | |||
* @package: com.xkcoding.websocket.controller | |||
* @description: 服务器监控Controller | |||
* @author: yangkai.shen | |||
* @date: Created in 2018-12-17 10:22 | |||
* @copyright: Copyright (c) 2018 | |||
* @version: V1.0 | |||
* @modified: yangkai.shen | |||
*/ | |||
@RestController | |||
@RequestMapping("/server") | |||
public class ServerController { | |||
@GetMapping | |||
public Dict serverInfo() throws Exception { | |||
Server server = new Server(); | |||
server.copyTo(); | |||
ServerVO serverVO = ServerUtil.wrapServerVO(server); | |||
return ServerUtil.wrapServerDict(serverVO); | |||
} | |||
} |
@@ -28,10 +28,10 @@ public class CpuVO { | |||
CpuVO vo = new CpuVO(); | |||
vo.data.add(new KV("核心数", cpu.getCpuNum())); | |||
vo.data.add(new KV("CPU总的使用率", cpu.getTotal())); | |||
vo.data.add(new KV("CPU系统使用率", cpu.getSys())); | |||
vo.data.add(new KV("CPU用户使用率", cpu.getUsed())); | |||
vo.data.add(new KV("CPU当前等待率", cpu.getWait())); | |||
vo.data.add(new KV("CPU当前空闲率", cpu.getFree())); | |||
vo.data.add(new KV("CPU系统使用率", cpu.getSys() + "%")); | |||
vo.data.add(new KV("CPU用户使用率", cpu.getUsed() + "%")); | |||
vo.data.add(new KV("CPU当前等待率", cpu.getWait() + "%")); | |||
vo.data.add(new KV("CPU当前空闲率", cpu.getFree() + "%")); | |||
return vo; | |||
} | |||
} |
@@ -26,9 +26,10 @@ public class JvmVO { | |||
public static JvmVO create(Jvm jvm) { | |||
JvmVO vo = new JvmVO(); | |||
vo.data.add(new KV("当前JVM占用的内存总数(M)", jvm.getTotal())); | |||
vo.data.add(new KV("JVM最大可用内存总数(M)", jvm.getMax())); | |||
vo.data.add(new KV("JVM空闲内存(M)", jvm.getFree())); | |||
vo.data.add(new KV("当前JVM占用的内存总数(M)", jvm.getTotal() + "M")); | |||
vo.data.add(new KV("JVM最大可用内存总数(M)", jvm.getMax() + "M")); | |||
vo.data.add(new KV("JVM空闲内存(M)", jvm.getFree() + "M")); | |||
vo.data.add(new KV("JVM使用率", jvm.getUsage() + "%")); | |||
vo.data.add(new KV("JDK版本", jvm.getVersion())); | |||
vo.data.add(new KV("JDK路径", jvm.getHome())); | |||
vo.data.add(new KV("JDK启动时间", jvm.getStartTime())); | |||
@@ -26,9 +26,10 @@ public class MemVO { | |||
public static MemVO create(Mem mem) { | |||
MemVO vo = new MemVO(); | |||
vo.data.add(new KV("内存总量", mem.getTotal())); | |||
vo.data.add(new KV("已用内存", mem.getUsed())); | |||
vo.data.add(new KV("剩余内存", mem.getFree())); | |||
vo.data.add(new KV("内存总量", mem.getTotal() + "G")); | |||
vo.data.add(new KV("已用内存", mem.getUsed() + "G")); | |||
vo.data.add(new KV("剩余内存", mem.getFree() + "G")); | |||
vo.data.add(new KV("使用率", mem.getUsage() + "%")); | |||
return vo; | |||
} | |||
} |
@@ -35,7 +35,7 @@ public class SysFileVO { | |||
item.add(new KV("总大小", sysFile.getTotal())); | |||
item.add(new KV("剩余大小", sysFile.getFree())); | |||
item.add(new KV("已经使用量", sysFile.getUsed())); | |||
item.add(new KV("资源的使用率", sysFile.getUsage())); | |||
item.add(new KV("资源的使用率", sysFile.getUsage() + "%")); | |||
vo.data.add(item); | |||
} | |||
@@ -1,10 +1,12 @@ | |||
package com.xkcoding.websocket.task; | |||
import cn.hutool.core.date.DateUtil; | |||
import cn.hutool.core.lang.Dict; | |||
import cn.hutool.json.JSONUtil; | |||
import com.xkcoding.websocket.common.WebSocketConsts; | |||
import com.xkcoding.websocket.model.Server; | |||
import com.xkcoding.websocket.payload.ServerVO; | |||
import com.xkcoding.websocket.util.ServerUtil; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.messaging.simp.SimpMessagingTemplate; | |||
@@ -33,17 +35,17 @@ public class ServerTask { | |||
private SimpMessagingTemplate wsTemplate; | |||
/** | |||
* 按照标准时间来算,每隔 10s 执行一次 | |||
* 按照标准时间来算,每隔 2s 执行一次 | |||
*/ | |||
@Scheduled(cron = "0/10 * * * * ?") | |||
@Scheduled(cron = "0/2 * * * * ?") | |||
public void websocket() throws Exception { | |||
log.info("【推送消息】开始执行:{}", DateUtil.formatDateTime(new Date())); | |||
// 查询服务器状态 | |||
Server server = new Server(); | |||
server.copyTo(); | |||
ServerVO serverVO = new ServerVO(); | |||
serverVO.create(server); | |||
wsTemplate.convertAndSend(WebSocketConsts.PUSH_SERVER, JSONUtil.toJsonStr(serverVO)); | |||
ServerVO serverVO = ServerUtil.wrapServerVO(server); | |||
Dict dict = ServerUtil.wrapServerDict(serverVO); | |||
wsTemplate.convertAndSend(WebSocketConsts.PUSH_SERVER, JSONUtil.toJsonStr(dict)); | |||
log.info("【推送消息】执行结束:{}", DateUtil.formatDateTime(new Date())); | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
package com.xkcoding.websocket.util; | |||
import cn.hutool.core.lang.Dict; | |||
import com.xkcoding.websocket.model.Server; | |||
import com.xkcoding.websocket.payload.ServerVO; | |||
/** | |||
* <p> | |||
* 服务器转换工具类 | |||
* </p> | |||
* | |||
* @package: com.xkcoding.websocket.util | |||
* @description: 服务器转换工具类 | |||
* @author: yangkai.shen | |||
* @date: Created in 2018-12-17 10:24 | |||
* @copyright: Copyright (c) 2018 | |||
* @version: V1.0 | |||
* @modified: yangkai.shen | |||
*/ | |||
public class ServerUtil { | |||
/** | |||
* 包装成 ServerVO | |||
* | |||
* @param server server | |||
* @return ServerVO | |||
*/ | |||
public static ServerVO wrapServerVO(Server server) { | |||
ServerVO serverVO = new ServerVO(); | |||
serverVO.create(server); | |||
return serverVO; | |||
} | |||
/** | |||
* 包装成 Dict | |||
* | |||
* @param serverVO serverVO | |||
* @return Dict | |||
*/ | |||
public static Dict wrapServerDict(ServerVO serverVO) { | |||
Dict dict = Dict.create() | |||
.set("cpu", serverVO.getCpu().get(0).getData()) | |||
.set("mem", serverVO.getMem().get(0).getData()) | |||
.set("sys", serverVO.getSys().get(0).getData()) | |||
.set("jvm", serverVO.getJvm().get(0).getData()) | |||
.set("sysFile", serverVO.getSysFile().get(0).getData()); | |||
return dict; | |||
} | |||
} |
@@ -3,24 +3,68 @@ | |||
<head> | |||
<meta charset="UTF-8"> | |||
<title>服务器信息</title> | |||
<!-- import CSS --> | |||
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> | |||
<link href="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.11/theme-chalk/index.css" rel="stylesheet"> | |||
<style> | |||
.el-row { | |||
margin-bottom: 20px; | |||
} | |||
.el-row:last-child { | |||
margin-bottom: 0; | |||
} | |||
.sysFile { | |||
margin-bottom: 5px; | |||
} | |||
.sysFile:last-child { | |||
margin-bottom: 0; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div id="app"> | |||
<el-container> | |||
<el-header> | |||
<el-button @click="_initSockJs">手动连接</el-button> | |||
<el-button @click="_destroySockJs" danger>断开连接</el-button> | |||
<el-button @click="_initSockJs" type="primary" :disabled="isConnected">手动连接</el-button> | |||
<el-button @click="_destroySockJs" type="danger" :disabled="!isConnected">断开连接</el-button> | |||
</el-header> | |||
<el-main> | |||
<el-row v-if="server.cpu.length > 0"> | |||
<el-col :span="16" :offset="4"> | |||
<el-card class="box-card"> | |||
<el-row :gutter="20"> | |||
<el-col :span="12"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>CPU信息</span> | |||
</div> | |||
<el-table :data="server.cpu[0].data" style="width: 100%"> | |||
<el-table size="small" border :data="server.cpu" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</el-card> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>内存信息</span> | |||
</div> | |||
<el-table size="small" border :data="server.mem" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>服务器信息</span> | |||
</div> | |||
<el-table size="small" border :data="server.sys" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
@@ -29,16 +73,47 @@ | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>Java虚拟机信息</span> | |||
</div> | |||
<el-table size="small" border :data="server.jvm" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-card> | |||
<div slot="header"> | |||
<span>磁盘状态</span> | |||
</div> | |||
<div class="sysFile" v-for="(item,index) in server.sysFile" :key="index"> | |||
<el-table size="small" border :data="item" style="width: 100%"> | |||
<el-table-column prop="key" label="属性"> | |||
</el-table-column> | |||
<el-table-column prop="value" label="值"> | |||
</el-table-column> | |||
</el-table> | |||
</div> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</el-main> | |||
</el-container> | |||
</div> | |||
</body> | |||
<script src="js/sockjs.min.js"></script> | |||
<script src="js/stomp.js"></script> | |||
<!-- import Vue before Element --> | |||
<script src="https://unpkg.com/vue/dist/vue.js"></script> | |||
<!-- import JavaScript --> | |||
<script src="https://unpkg.com/element-ui/lib/index.js"></script> | |||
<script src="https://cdn.bootcss.com/vue/2.5.21/vue.min.js"></script> | |||
<script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.4.11/index.js"></script> | |||
<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script> | |||
<script> | |||
const wsHost = "http://localhost:8080/demo/notification"; | |||
const wsTopic = "/topic/server"; | |||
@@ -47,29 +122,38 @@ | |||
el: '#app', | |||
data: function () { | |||
return { | |||
isConnected: false, | |||
stompClient: {}, | |||
socket: {}, | |||
server: { | |||
cpu: [], | |||
jvm: [], | |||
mem: [], | |||
sysFile: [], | |||
sys: [] | |||
jvm: [], | |||
sys: [], | |||
sysFile: [] | |||
} | |||
} | |||
}, | |||
methods: { | |||
_getServerInfo() { | |||
axios.get('/demo/server') | |||
.then((response) => { | |||
this.server = response.data | |||
}); | |||
}, | |||
_initSockJs() { | |||
this._getServerInfo(); | |||
this.socket = new SockJS(wsHost); | |||
this.stompClient = Stomp.over(this.socket); | |||
this.stompClient.connect({}, (frame) => { | |||
console.log('websocket连接成功:' + frame); | |||
this.isConnected = true; | |||
this.$message('websocket服务器连接成功'); | |||
// 另外再注册一下消息推送 | |||
this.stompClient.subscribe(wsTopic, function (response) { | |||
this.server = JSON.parse(response); | |||
this.stompClient.subscribe(wsTopic, (response) => { | |||
this.server = JSON.parse(response.body); | |||
}); | |||
}); | |||
}, | |||
@@ -80,6 +164,12 @@ | |||
this.socket.close(); | |||
this.stompClient = {}; | |||
this.socket = {}; | |||
this.isConnected = false; | |||
this.server.cpu = []; | |||
this.server.mem = []; | |||
this.server.jvm = []; | |||
this.server.sys = []; | |||
this.server.sysFile = []; | |||
} | |||
console.log('websocket断开成功!'); | |||
this.$message.error('websocket断开成功!'); | |||