diff --git a/spring-boot-demo-websocket/README.md b/spring-boot-demo-websocket/README.md index 479c0d8..2994b24 100644 --- a/spring-boot-demo-websocket/README.md +++ b/spring-boot-demo-websocket/README.md @@ -1 +1,388 @@ # spring-boot-demo-websocket + +> 此 demo 主要演示了 Spring Boot 如何集成 WebSocket,实现后端主动往前端推送数据。网上大部分websocket的例子都是聊天室,本例主要是推送服务器状态信息。前端页面基于vue和element-ui实现。 + +## 1. 代码 + +### 1.1. pom.xml + +```xml + + + 4.0.0 + + spring-boot-demo-websocket + 1.0.0-SNAPSHOT + + spring-boot-demo-websocket + Demo project for Spring Boot + + + com.xkcoding + spring-boot-demo + 1.0.0-SNAPSHOT + + + + UTF-8 + UTF-8 + 1.8 + 3.9.1 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-websocket + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.github.oshi + oshi-core + ${oshi.version} + + + + cn.hutool + hutool-all + + + + com.google.guava + guava + + + + org.projectlombok + lombok + true + + + + + spring-boot-demo-websocket + + + org.springframework.boot + spring-boot-maven-plugin + + + + + +``` + +### 1.2. WebSocketConfig.java + +```java +/** + *

+ * WebSocket配置 + *

+ * + * @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 +/** + *

+ * 服务器定时推送任务 + *

+ * + * @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 + + + + + 服务器信息 + + + + +
+ + + 手动连接 + 断开连接 + + + + + +
+ CPU信息 +
+ + + + + + +
+
+ + +
+ 内存信息 +
+ + + + + + +
+
+
+ + + +
+ 服务器信息 +
+ + + + + + +
+
+
+ + + +
+ Java虚拟机信息 +
+ + + + + + +
+
+
+ + + +
+ 磁盘状态 +
+
+ + + + + + +
+
+
+
+
+
+
+ + + + + + + + +``` + +## 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 \ No newline at end of file diff --git a/spring-boot-demo-websocket/assets/image-20181217110240322-5015760.png b/spring-boot-demo-websocket/assets/image-20181217110240322-5015760.png new file mode 100644 index 0000000..ebdd82b Binary files /dev/null and b/spring-boot-demo-websocket/assets/image-20181217110240322-5015760.png differ diff --git a/spring-boot-demo-websocket/assets/image-20181217110240322.png b/spring-boot-demo-websocket/assets/image-20181217110240322.png new file mode 100644 index 0000000..ebdd82b Binary files /dev/null and b/spring-boot-demo-websocket/assets/image-20181217110240322.png differ diff --git a/spring-boot-demo-websocket/assets/image-20181217110304065-5015784.png b/spring-boot-demo-websocket/assets/image-20181217110304065-5015784.png new file mode 100644 index 0000000..187b5f3 Binary files /dev/null and b/spring-boot-demo-websocket/assets/image-20181217110304065-5015784.png differ diff --git a/spring-boot-demo-websocket/assets/image-20181217110304065.png b/spring-boot-demo-websocket/assets/image-20181217110304065.png new file mode 100644 index 0000000..187b5f3 Binary files /dev/null and b/spring-boot-demo-websocket/assets/image-20181217110304065.png differ diff --git a/spring-boot-demo-websocket/assets/image-20181217110328810-5015808.png b/spring-boot-demo-websocket/assets/image-20181217110328810-5015808.png new file mode 100644 index 0000000..b19c042 Binary files /dev/null and b/spring-boot-demo-websocket/assets/image-20181217110328810-5015808.png differ diff --git a/spring-boot-demo-websocket/assets/image-20181217110328810.png b/spring-boot-demo-websocket/assets/image-20181217110328810.png new file mode 100644 index 0000000..b19c042 Binary files /dev/null and b/spring-boot-demo-websocket/assets/image-20181217110328810.png differ diff --git a/spring-boot-demo-websocket/assets/image-20181217110336017-5015816.png b/spring-boot-demo-websocket/assets/image-20181217110336017-5015816.png new file mode 100644 index 0000000..0b982d4 Binary files /dev/null and b/spring-boot-demo-websocket/assets/image-20181217110336017-5015816.png differ diff --git a/spring-boot-demo-websocket/assets/image-20181217110336017.png b/spring-boot-demo-websocket/assets/image-20181217110336017.png new file mode 100644 index 0000000..0b982d4 Binary files /dev/null and b/spring-boot-demo-websocket/assets/image-20181217110336017.png differ diff --git a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/controller/ServerController.java b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/controller/ServerController.java new file mode 100644 index 0000000..b4c61e8 --- /dev/null +++ b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/controller/ServerController.java @@ -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; + +/** + *

+ * 服务器监控Controller + *

+ * + * @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); + } + +} diff --git a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/CpuVO.java b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/CpuVO.java index 8cd3258..e9524c9 100644 --- a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/CpuVO.java +++ b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/CpuVO.java @@ -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; } } \ No newline at end of file diff --git a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/JvmVO.java b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/JvmVO.java index bc2940c..78b6749 100644 --- a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/JvmVO.java +++ b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/JvmVO.java @@ -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())); diff --git a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/MemVO.java b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/MemVO.java index b580e15..fa24fce 100644 --- a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/MemVO.java +++ b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/MemVO.java @@ -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; } } \ No newline at end of file diff --git a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/SysFileVO.java b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/SysFileVO.java index 1f4429a..c4e5e46 100644 --- a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/SysFileVO.java +++ b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/payload/server/SysFileVO.java @@ -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); } diff --git a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/task/ServerTask.java b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/task/ServerTask.java index 73e27a2..62d24e9 100644 --- a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/task/ServerTask.java +++ b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/task/ServerTask.java @@ -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())); } } diff --git a/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/util/ServerUtil.java b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/util/ServerUtil.java new file mode 100644 index 0000000..4256f18 --- /dev/null +++ b/spring-boot-demo-websocket/src/main/java/com/xkcoding/websocket/util/ServerUtil.java @@ -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; + +/** + *

+ * 服务器转换工具类 + *

+ * + * @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; + } +} diff --git a/spring-boot-demo-websocket/src/main/resources/static/server.html b/spring-boot-demo-websocket/src/main/resources/static/server.html index 7642224..460d38a 100644 --- a/spring-boot-demo-websocket/src/main/resources/static/server.html +++ b/spring-boot-demo-websocket/src/main/resources/static/server.html @@ -3,24 +3,68 @@ 服务器信息 - - + +
- 手动连接 - 断开连接 + 手动连接 + 断开连接 - - - + + +
CPU信息
- + + + + + + +
+
+ + +
+ 内存信息 +
+ + + + + + +
+
+
+ + + +
+ 服务器信息 +
+ @@ -29,16 +73,47 @@
+ + + +
+ Java虚拟机信息 +
+ + + + + + +
+
+
+ + + +
+ 磁盘状态 +
+
+ + + + + + +
+
+
+
- - - - + + +