@@ -0,0 +1,18 @@ | |||||
package com.xkcoding.websocket.common; | |||||
/** | |||||
* <p> | |||||
* WebSocket常量 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.common | |||||
* @description: WebSocket常量 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 16:01 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
public interface WebSocketConsts { | |||||
String PUSH_SERVER = "/topic/server"; | |||||
} |
@@ -0,0 +1,43 @@ | |||||
package com.xkcoding.websocket.config; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import org.springframework.messaging.simp.config.MessageBrokerRegistry; | |||||
import org.springframework.web.socket.config.annotation.EnableWebSocket; | |||||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; | |||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; | |||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; | |||||
/** | |||||
* <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"); | |||||
} | |||||
} |
@@ -0,0 +1,220 @@ | |||||
package com.xkcoding.websocket.model; | |||||
import cn.hutool.core.util.NumberUtil; | |||||
import com.xkcoding.websocket.model.server.*; | |||||
import com.xkcoding.websocket.util.IpUtil; | |||||
import oshi.SystemInfo; | |||||
import oshi.hardware.CentralProcessor; | |||||
import oshi.hardware.CentralProcessor.TickType; | |||||
import oshi.hardware.GlobalMemory; | |||||
import oshi.hardware.HardwareAbstractionLayer; | |||||
import oshi.software.os.FileSystem; | |||||
import oshi.software.os.OSFileStore; | |||||
import oshi.software.os.OperatingSystem; | |||||
import oshi.util.Util; | |||||
import java.net.UnknownHostException; | |||||
import java.util.LinkedList; | |||||
import java.util.List; | |||||
import java.util.Properties; | |||||
/** | |||||
* <p> | |||||
* 服务器相关信息实体 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.model | |||||
* @description: 服务器相关信息实体 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 16:09 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
public class Server { | |||||
private static final int OSHI_WAIT_SECOND = 1000; | |||||
/** | |||||
* CPU相关信息 | |||||
*/ | |||||
private Cpu cpu = new Cpu(); | |||||
/** | |||||
* 內存相关信息 | |||||
*/ | |||||
private Mem mem = new Mem(); | |||||
/** | |||||
* JVM相关信息 | |||||
*/ | |||||
private Jvm jvm = new Jvm(); | |||||
/** | |||||
* 服务器相关信息 | |||||
*/ | |||||
private Sys sys = new Sys(); | |||||
/** | |||||
* 磁盘相关信息 | |||||
*/ | |||||
private List<SysFile> sysFiles = new LinkedList<SysFile>(); | |||||
public Cpu getCpu() { | |||||
return cpu; | |||||
} | |||||
public void setCpu(Cpu cpu) { | |||||
this.cpu = cpu; | |||||
} | |||||
public Mem getMem() { | |||||
return mem; | |||||
} | |||||
public void setMem(Mem mem) { | |||||
this.mem = mem; | |||||
} | |||||
public Jvm getJvm() { | |||||
return jvm; | |||||
} | |||||
public void setJvm(Jvm jvm) { | |||||
this.jvm = jvm; | |||||
} | |||||
public Sys getSys() { | |||||
return sys; | |||||
} | |||||
public void setSys(Sys sys) { | |||||
this.sys = sys; | |||||
} | |||||
public List<SysFile> getSysFiles() { | |||||
return sysFiles; | |||||
} | |||||
public void setSysFiles(List<SysFile> sysFiles) { | |||||
this.sysFiles = sysFiles; | |||||
} | |||||
public void copyTo() throws Exception { | |||||
SystemInfo si = new SystemInfo(); | |||||
HardwareAbstractionLayer hal = si.getHardware(); | |||||
setCpuInfo(hal.getProcessor()); | |||||
setMemInfo(hal.getMemory()); | |||||
setSysInfo(); | |||||
setJvmInfo(); | |||||
setSysFiles(si.getOperatingSystem()); | |||||
} | |||||
/** | |||||
* 设置CPU信息 | |||||
*/ | |||||
private void setCpuInfo(CentralProcessor processor) { | |||||
// CPU信息 | |||||
long[] prevTicks = processor.getSystemCpuLoadTicks(); | |||||
Util.sleep(OSHI_WAIT_SECOND); | |||||
long[] ticks = processor.getSystemCpuLoadTicks(); | |||||
long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; | |||||
long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; | |||||
long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; | |||||
long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; | |||||
long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; | |||||
long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; | |||||
long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; | |||||
long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; | |||||
long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; | |||||
cpu.setCpuNum(processor.getLogicalProcessorCount()); | |||||
cpu.setTotal(totalCpu); | |||||
cpu.setSys(cSys); | |||||
cpu.setUsed(user); | |||||
cpu.setWait(iowait); | |||||
cpu.setFree(idle); | |||||
} | |||||
/** | |||||
* 设置内存信息 | |||||
*/ | |||||
private void setMemInfo(GlobalMemory memory) { | |||||
mem.setTotal(memory.getTotal()); | |||||
mem.setUsed(memory.getTotal() - memory.getAvailable()); | |||||
mem.setFree(memory.getAvailable()); | |||||
} | |||||
/** | |||||
* 设置服务器信息 | |||||
*/ | |||||
private void setSysInfo() { | |||||
Properties props = System.getProperties(); | |||||
sys.setComputerName(IpUtil.getHostName()); | |||||
sys.setComputerIp(IpUtil.getHostIp()); | |||||
sys.setOsName(props.getProperty("os.name")); | |||||
sys.setOsArch(props.getProperty("os.arch")); | |||||
sys.setUserDir(props.getProperty("user.dir")); | |||||
} | |||||
/** | |||||
* 设置Java虚拟机 | |||||
*/ | |||||
private void setJvmInfo() throws UnknownHostException { | |||||
Properties props = System.getProperties(); | |||||
jvm.setTotal(Runtime.getRuntime().totalMemory()); | |||||
jvm.setMax(Runtime.getRuntime().maxMemory()); | |||||
jvm.setFree(Runtime.getRuntime().freeMemory()); | |||||
jvm.setVersion(props.getProperty("java.version")); | |||||
jvm.setHome(props.getProperty("java.home")); | |||||
} | |||||
/** | |||||
* 设置磁盘信息 | |||||
*/ | |||||
private void setSysFiles(OperatingSystem os) { | |||||
FileSystem fileSystem = os.getFileSystem(); | |||||
OSFileStore[] fsArray = fileSystem.getFileStores(); | |||||
for (OSFileStore fs : fsArray) { | |||||
long free = fs.getUsableSpace(); | |||||
long total = fs.getTotalSpace(); | |||||
long used = total - free; | |||||
SysFile sysFile = new SysFile(); | |||||
sysFile.setDirName(fs.getMount()); | |||||
sysFile.setSysTypeName(fs.getType()); | |||||
sysFile.setTypeName(fs.getName()); | |||||
sysFile.setTotal(convertFileSize(total)); | |||||
sysFile.setFree(convertFileSize(free)); | |||||
sysFile.setUsed(convertFileSize(used)); | |||||
sysFile.setUsage(NumberUtil.mul(NumberUtil.div(used, total, 4), 100)); | |||||
sysFiles.add(sysFile); | |||||
} | |||||
} | |||||
/** | |||||
* 字节转换 | |||||
* | |||||
* @param size 字节大小 | |||||
* @return 转换后值 | |||||
*/ | |||||
public String convertFileSize(long size) { | |||||
long kb = 1024; | |||||
long mb = kb * 1024; | |||||
long gb = mb * 1024; | |||||
if (size >= gb) { | |||||
return String.format("%.1f GB", (float) size / gb); | |||||
} else if (size >= mb) { | |||||
float f = (float) size / mb; | |||||
return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); | |||||
} else if (size >= kb) { | |||||
float f = (float) size / kb; | |||||
return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); | |||||
} else { | |||||
return String.format("%d B", size); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,101 @@ | |||||
package com.xkcoding.websocket.model.server; | |||||
import cn.hutool.core.util.NumberUtil; | |||||
/** | |||||
* <p> | |||||
* CPU相关信息实体 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.model.server | |||||
* @description: CPU相关信息实体 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 16:09 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
public class Cpu { | |||||
/** | |||||
* 核心数 | |||||
*/ | |||||
private int cpuNum; | |||||
/** | |||||
* CPU总的使用率 | |||||
*/ | |||||
private double total; | |||||
/** | |||||
* CPU系统使用率 | |||||
*/ | |||||
private double sys; | |||||
/** | |||||
* CPU用户使用率 | |||||
*/ | |||||
private double used; | |||||
/** | |||||
* CPU当前等待率 | |||||
*/ | |||||
private double wait; | |||||
/** | |||||
* CPU当前空闲率 | |||||
*/ | |||||
private double free; | |||||
public int getCpuNum() { | |||||
return cpuNum; | |||||
} | |||||
public void setCpuNum(int cpuNum) { | |||||
this.cpuNum = cpuNum; | |||||
} | |||||
public double getTotal() { | |||||
return NumberUtil.round(NumberUtil.mul(total, 100), 2) | |||||
.doubleValue(); | |||||
} | |||||
public void setTotal(double total) { | |||||
this.total = total; | |||||
} | |||||
public double getSys() { | |||||
return NumberUtil.round(NumberUtil.mul(sys / total, 100), 2) | |||||
.doubleValue(); | |||||
} | |||||
public void setSys(double sys) { | |||||
this.sys = sys; | |||||
} | |||||
public double getUsed() { | |||||
return NumberUtil.round(NumberUtil.mul(used / total, 100), 2) | |||||
.doubleValue(); | |||||
} | |||||
public void setUsed(double used) { | |||||
this.used = used; | |||||
} | |||||
public double getWait() { | |||||
return NumberUtil.round(NumberUtil.mul(wait / total, 100), 2) | |||||
.doubleValue(); | |||||
} | |||||
public void setWait(double wait) { | |||||
this.wait = wait; | |||||
} | |||||
public double getFree() { | |||||
return NumberUtil.round(NumberUtil.mul(free / total, 100), 2) | |||||
.doubleValue(); | |||||
} | |||||
public void setFree(double free) { | |||||
this.free = free; | |||||
} | |||||
} |
@@ -0,0 +1,133 @@ | |||||
package com.xkcoding.websocket.model.server; | |||||
import cn.hutool.core.date.DateUtil; | |||||
import cn.hutool.core.util.NumberUtil; | |||||
import java.lang.management.ManagementFactory; | |||||
import java.util.Date; | |||||
/** | |||||
* <p> | |||||
* JVM相关信息实体 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.model.server | |||||
* @description: JVM相关信息实体 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 16:09 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
public class Jvm { | |||||
/** | |||||
* 当前JVM占用的内存总数(M) | |||||
*/ | |||||
private double total; | |||||
/** | |||||
* JVM最大可用内存总数(M) | |||||
*/ | |||||
private double max; | |||||
/** | |||||
* JVM空闲内存(M) | |||||
*/ | |||||
private double free; | |||||
/** | |||||
* JDK版本 | |||||
*/ | |||||
private String version; | |||||
/** | |||||
* JDK路径 | |||||
*/ | |||||
private String home; | |||||
/** | |||||
* JDK启动时间 | |||||
*/ | |||||
private String startTime; | |||||
/** | |||||
* JDK运行时间 | |||||
*/ | |||||
private String runTime; | |||||
public double getTotal() { | |||||
return NumberUtil.div(total, (1024 * 1024), 2); | |||||
} | |||||
public void setTotal(double total) { | |||||
this.total = total; | |||||
} | |||||
public double getMax() { | |||||
return NumberUtil.div(max, (1024 * 1024), 2); | |||||
} | |||||
public void setMax(double max) { | |||||
this.max = max; | |||||
} | |||||
public double getFree() { | |||||
return NumberUtil.div(free, (1024 * 1024), 2); | |||||
} | |||||
public void setFree(double free) { | |||||
this.free = free; | |||||
} | |||||
public double getUsed() { | |||||
return NumberUtil.div(total - free, (1024 * 1024), 2); | |||||
} | |||||
public double getUsage() { | |||||
return NumberUtil.mul(NumberUtil.div(total - free, total, 4), 100); | |||||
} | |||||
/** | |||||
* 获取JDK名称 | |||||
*/ | |||||
public String getName() { | |||||
return ManagementFactory.getRuntimeMXBean() | |||||
.getVmName(); | |||||
} | |||||
public String getVersion() { | |||||
return version; | |||||
} | |||||
public void setVersion(String version) { | |||||
this.version = version; | |||||
} | |||||
public String getHome() { | |||||
return home; | |||||
} | |||||
public void setHome(String home) { | |||||
this.home = home; | |||||
} | |||||
public void setStartTime(String startTime) { | |||||
this.startTime = startTime; | |||||
} | |||||
public String getStartTime() { | |||||
return DateUtil.formatDateTime(new Date(ManagementFactory.getRuntimeMXBean() | |||||
.getStartTime())); | |||||
} | |||||
public void setRunTime(String runTime) { | |||||
this.runTime = runTime; | |||||
} | |||||
public String getRunTime() { | |||||
long startTime = ManagementFactory.getRuntimeMXBean() | |||||
.getStartTime(); | |||||
return DateUtil.formatBetween(DateUtil.current(false) - startTime); | |||||
} | |||||
} |
@@ -0,0 +1,61 @@ | |||||
package com.xkcoding.websocket.model.server; | |||||
import cn.hutool.core.util.NumberUtil; | |||||
/** | |||||
* <p> | |||||
* 內存相关信息实体 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.model.server | |||||
* @description: 內存相关信息实体 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 16:09 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
public class Mem { | |||||
/** | |||||
* 内存总量 | |||||
*/ | |||||
private double total; | |||||
/** | |||||
* 已用内存 | |||||
*/ | |||||
private double used; | |||||
/** | |||||
* 剩余内存 | |||||
*/ | |||||
private double free; | |||||
public double getTotal() { | |||||
return NumberUtil.div(total, (1024 * 1024 * 1024), 2); | |||||
} | |||||
public void setTotal(long total) { | |||||
this.total = total; | |||||
} | |||||
public double getUsed() { | |||||
return NumberUtil.div(used, (1024 * 1024 * 1024), 2); | |||||
} | |||||
public void setUsed(long used) { | |||||
this.used = used; | |||||
} | |||||
public double getFree() { | |||||
return NumberUtil.div(free, (1024 * 1024 * 1024), 2); | |||||
} | |||||
public void setFree(long free) { | |||||
this.free = free; | |||||
} | |||||
public double getUsage() { | |||||
return NumberUtil.mul(NumberUtil.div(used, total, 4), 100); | |||||
} | |||||
} |
@@ -0,0 +1,81 @@ | |||||
package com.xkcoding.websocket.model.server; | |||||
/** | |||||
* <p> | |||||
* 系统相关信息实体 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.model.server | |||||
* @description: 系统相关信息实体 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 16:10 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
public class Sys { | |||||
/** | |||||
* 服务器名称 | |||||
*/ | |||||
private String computerName; | |||||
/** | |||||
* 服务器Ip | |||||
*/ | |||||
private String computerIp; | |||||
/** | |||||
* 项目路径 | |||||
*/ | |||||
private String userDir; | |||||
/** | |||||
* 操作系统 | |||||
*/ | |||||
private String osName; | |||||
/** | |||||
* 系统架构 | |||||
*/ | |||||
private String osArch; | |||||
public String getComputerName() { | |||||
return computerName; | |||||
} | |||||
public void setComputerName(String computerName) { | |||||
this.computerName = computerName; | |||||
} | |||||
public String getComputerIp() { | |||||
return computerIp; | |||||
} | |||||
public void setComputerIp(String computerIp) { | |||||
this.computerIp = computerIp; | |||||
} | |||||
public String getUserDir() { | |||||
return userDir; | |||||
} | |||||
public void setUserDir(String userDir) { | |||||
this.userDir = userDir; | |||||
} | |||||
public String getOsName() { | |||||
return osName; | |||||
} | |||||
public void setOsName(String osName) { | |||||
this.osName = osName; | |||||
} | |||||
public String getOsArch() { | |||||
return osArch; | |||||
} | |||||
public void setOsArch(String osArch) { | |||||
this.osArch = osArch; | |||||
} | |||||
} |
@@ -0,0 +1,107 @@ | |||||
package com.xkcoding.websocket.model.server; | |||||
/** | |||||
* <p> | |||||
* 系统文件相关信息实体 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.model.server | |||||
* @description: 系统文件相关信息实体 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 16:10 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
public class SysFile { | |||||
/** | |||||
* 盘符路径 | |||||
*/ | |||||
private String dirName; | |||||
/** | |||||
* 盘符类型 | |||||
*/ | |||||
private String sysTypeName; | |||||
/** | |||||
* 文件类型 | |||||
*/ | |||||
private String typeName; | |||||
/** | |||||
* 总大小 | |||||
*/ | |||||
private String total; | |||||
/** | |||||
* 剩余大小 | |||||
*/ | |||||
private String free; | |||||
/** | |||||
* 已经使用量 | |||||
*/ | |||||
private String used; | |||||
/** | |||||
* 资源的使用率 | |||||
*/ | |||||
private double usage; | |||||
public String getDirName() { | |||||
return dirName; | |||||
} | |||||
public void setDirName(String dirName) { | |||||
this.dirName = dirName; | |||||
} | |||||
public String getSysTypeName() { | |||||
return sysTypeName; | |||||
} | |||||
public void setSysTypeName(String sysTypeName) { | |||||
this.sysTypeName = sysTypeName; | |||||
} | |||||
public String getTypeName() { | |||||
return typeName; | |||||
} | |||||
public void setTypeName(String typeName) { | |||||
this.typeName = typeName; | |||||
} | |||||
public String getTotal() { | |||||
return total; | |||||
} | |||||
public void setTotal(String total) { | |||||
this.total = total; | |||||
} | |||||
public String getFree() { | |||||
return free; | |||||
} | |||||
public void setFree(String free) { | |||||
this.free = free; | |||||
} | |||||
public String getUsed() { | |||||
return used; | |||||
} | |||||
public void setUsed(String used) { | |||||
this.used = used; | |||||
} | |||||
public double getUsage() { | |||||
return usage; | |||||
} | |||||
public void setUsage(double usage) { | |||||
this.usage = usage; | |||||
} | |||||
} |
@@ -0,0 +1,33 @@ | |||||
package com.xkcoding.websocket.payload; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
/** | |||||
* <p> | |||||
* 键值匹配 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.payload | |||||
* @description: 键值匹配 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 17:41 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Data | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public class KV { | |||||
/** | |||||
* 键 | |||||
*/ | |||||
private String key; | |||||
/** | |||||
* 值 | |||||
*/ | |||||
private Object value; | |||||
} |
@@ -0,0 +1,39 @@ | |||||
package com.xkcoding.websocket.payload; | |||||
import com.google.common.collect.Lists; | |||||
import com.xkcoding.websocket.model.Server; | |||||
import com.xkcoding.websocket.payload.server.*; | |||||
import lombok.Data; | |||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* 服务器信息VO | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.payload | |||||
* @description: 服务器信息VO | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 17:25 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Data | |||||
public class ServerVO { | |||||
List<CpuVO> cpu = Lists.newArrayList(); | |||||
List<JvmVO> jvm = Lists.newArrayList(); | |||||
List<MemVO> mem = Lists.newArrayList(); | |||||
List<SysFileVO> sysFile = Lists.newArrayList(); | |||||
List<SysVO> sys = Lists.newArrayList(); | |||||
public ServerVO create(Server server) { | |||||
cpu.add(CpuVO.create(server.getCpu())); | |||||
jvm.add(JvmVO.create(server.getJvm())); | |||||
mem.add(MemVO.create(server.getMem())); | |||||
sysFile.add(SysFileVO.create(server.getSysFiles())); | |||||
sys.add(SysVO.create(server.getSys())); | |||||
return null; | |||||
} | |||||
} |
@@ -0,0 +1,37 @@ | |||||
package com.xkcoding.websocket.payload.server; | |||||
import com.google.common.collect.Lists; | |||||
import com.xkcoding.websocket.model.server.Cpu; | |||||
import com.xkcoding.websocket.payload.KV; | |||||
import lombok.Data; | |||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* CPU相关信息实体VO | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.payload.server | |||||
* @description: CPU相关信息实体VO | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 17:27 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Data | |||||
public class CpuVO { | |||||
List<KV> data = Lists.newArrayList(); | |||||
public static CpuVO create(Cpu cpu) { | |||||
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())); | |||||
return vo; | |||||
} | |||||
} |
@@ -0,0 +1,39 @@ | |||||
package com.xkcoding.websocket.payload.server; | |||||
import com.google.common.collect.Lists; | |||||
import com.xkcoding.websocket.model.server.Jvm; | |||||
import com.xkcoding.websocket.payload.KV; | |||||
import lombok.Data; | |||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* JVM相关信息实体VO | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.payload.server | |||||
* @description: JVM相关信息实体VO | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 17:28 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Data | |||||
public class JvmVO { | |||||
List<KV> data = Lists.newArrayList(); | |||||
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("JDK版本", jvm.getVersion())); | |||||
vo.data.add(new KV("JDK路径", jvm.getHome())); | |||||
vo.data.add(new KV("JDK启动时间", jvm.getStartTime())); | |||||
vo.data.add(new KV("JDK运行时间", jvm.getRunTime())); | |||||
return vo; | |||||
} | |||||
} |
@@ -0,0 +1,34 @@ | |||||
package com.xkcoding.websocket.payload.server; | |||||
import com.google.common.collect.Lists; | |||||
import com.xkcoding.websocket.model.server.Mem; | |||||
import com.xkcoding.websocket.payload.KV; | |||||
import lombok.Data; | |||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* 內存相关信息实体VO | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.payload.server | |||||
* @description: 內存相关信息实体VO | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 17:28 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Data | |||||
public class MemVO { | |||||
List<KV> data = Lists.newArrayList(); | |||||
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())); | |||||
return vo; | |||||
} | |||||
} |
@@ -0,0 +1,44 @@ | |||||
package com.xkcoding.websocket.payload.server; | |||||
import com.google.common.collect.Lists; | |||||
import com.xkcoding.websocket.model.server.SysFile; | |||||
import com.xkcoding.websocket.payload.KV; | |||||
import lombok.Data; | |||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* 系统文件相关信息实体VO | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.payload.server | |||||
* @description: 系统文件相关信息实体VO | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 17:30 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Data | |||||
public class SysFileVO { | |||||
List<List<KV>> data = Lists.newArrayList(); | |||||
public static SysFileVO create(List<SysFile> sysFiles) { | |||||
SysFileVO vo = new SysFileVO(); | |||||
for (SysFile sysFile : sysFiles) { | |||||
List<KV> item = Lists.newArrayList(); | |||||
item.add(new KV("盘符路径", sysFile.getDirName())); | |||||
item.add(new KV("盘符类型", sysFile.getSysTypeName())); | |||||
item.add(new KV("文件类型", sysFile.getTypeName())); | |||||
item.add(new KV("总大小", sysFile.getTotal())); | |||||
item.add(new KV("剩余大小", sysFile.getFree())); | |||||
item.add(new KV("已经使用量", sysFile.getUsed())); | |||||
item.add(new KV("资源的使用率", sysFile.getUsage())); | |||||
vo.data.add(item); | |||||
} | |||||
return vo; | |||||
} | |||||
} |
@@ -0,0 +1,36 @@ | |||||
package com.xkcoding.websocket.payload.server; | |||||
import com.google.common.collect.Lists; | |||||
import com.xkcoding.websocket.model.server.Sys; | |||||
import com.xkcoding.websocket.payload.KV; | |||||
import lombok.Data; | |||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* 系统相关信息实体VO | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.payload.server | |||||
* @description: 系统相关信息实体VO | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 17:28 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Data | |||||
public class SysVO { | |||||
List<KV> data = Lists.newArrayList(); | |||||
public static SysVO create(Sys sys) { | |||||
SysVO vo = new SysVO(); | |||||
vo.data.add(new KV("服务器名称", sys.getComputerName())); | |||||
vo.data.add(new KV("服务器Ip", sys.getComputerIp())); | |||||
vo.data.add(new KV("项目路径", sys.getUserDir())); | |||||
vo.data.add(new KV("操作系统", sys.getOsName())); | |||||
vo.data.add(new KV("系统架构", sys.getOsArch())); | |||||
return vo; | |||||
} | |||||
} |
@@ -0,0 +1,49 @@ | |||||
package com.xkcoding.websocket.task; | |||||
import cn.hutool.core.date.DateUtil; | |||||
import cn.hutool.json.JSONUtil; | |||||
import com.xkcoding.websocket.common.WebSocketConsts; | |||||
import com.xkcoding.websocket.model.Server; | |||||
import com.xkcoding.websocket.payload.ServerVO; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.messaging.simp.SimpMessagingTemplate; | |||||
import org.springframework.scheduling.annotation.Scheduled; | |||||
import org.springframework.stereotype.Component; | |||||
import java.util.Date; | |||||
/** | |||||
* <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; | |||||
/** | |||||
* 按照标准时间来算,每隔 10s 执行一次 | |||||
*/ | |||||
@Scheduled(cron = "0/10 * * * * ?") | |||||
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)); | |||||
log.info("【推送消息】执行结束:{}", DateUtil.formatDateTime(new Date())); | |||||
} | |||||
} |
@@ -0,0 +1,169 @@ | |||||
package com.xkcoding.websocket.util; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import java.net.InetAddress; | |||||
import java.net.UnknownHostException; | |||||
/** | |||||
* <p> | |||||
* IP 工具类 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.websocket.util | |||||
* @description: IP 工具类 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2018-12-14 16:08 | |||||
* @copyright: Copyright (c) 2018 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
public class IpUtil { | |||||
public static String getIpAddr(HttpServletRequest request) { | |||||
if (request == null) { | |||||
return "unknown"; | |||||
} | |||||
String ip = request.getHeader("x-forwarded-for"); | |||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |||||
ip = request.getHeader("Proxy-Client-IP"); | |||||
} | |||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |||||
ip = request.getHeader("X-Forwarded-For"); | |||||
} | |||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |||||
ip = request.getHeader("WL-Proxy-Client-IP"); | |||||
} | |||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |||||
ip = request.getHeader("X-Real-IP"); | |||||
} | |||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |||||
ip = request.getRemoteAddr(); | |||||
} | |||||
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; | |||||
} | |||||
public static boolean internalIp(String ip) { | |||||
byte[] addr = textToNumericFormatV4(ip); | |||||
return internalIp(addr) || "127.0.0.1".equals(ip); | |||||
} | |||||
private static boolean internalIp(byte[] addr) { | |||||
final byte b0 = addr[0]; | |||||
final byte b1 = addr[1]; | |||||
// 10.x.x.x/8 | |||||
final byte SECTION_1 = 0x0A; | |||||
// 172.16.x.x/12 | |||||
final byte SECTION_2 = (byte) 0xAC; | |||||
final byte SECTION_3 = (byte) 0x10; | |||||
final byte SECTION_4 = (byte) 0x1F; | |||||
// 192.168.x.x/16 | |||||
final byte SECTION_5 = (byte) 0xC0; | |||||
final byte SECTION_6 = (byte) 0xA8; | |||||
switch (b0) { | |||||
case SECTION_1: | |||||
return true; | |||||
case SECTION_2: | |||||
if (b1 >= SECTION_3 && b1 <= SECTION_4) { | |||||
return true; | |||||
} | |||||
case SECTION_5: | |||||
switch (b1) { | |||||
case SECTION_6: | |||||
return true; | |||||
} | |||||
default: | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* 将IPv4地址转换成字节 | |||||
* | |||||
* @param text IPv4地址 | |||||
* @return byte 字节 | |||||
*/ | |||||
public static byte[] textToNumericFormatV4(String text) { | |||||
if (text.length() == 0) { | |||||
return null; | |||||
} | |||||
byte[] bytes = new byte[4]; | |||||
String[] elements = text.split("\\.", -1); | |||||
try { | |||||
long l; | |||||
int i; | |||||
switch (elements.length) { | |||||
case 1: | |||||
l = Long.parseLong(elements[0]); | |||||
if ((l < 0L) || (l > 4294967295L)) { | |||||
return null; | |||||
} | |||||
bytes[0] = (byte) (int) (l >> 24 & 0xFF); | |||||
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); | |||||
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); | |||||
bytes[3] = (byte) (int) (l & 0xFF); | |||||
break; | |||||
case 2: | |||||
l = Integer.parseInt(elements[0]); | |||||
if ((l < 0L) || (l > 255L)) { | |||||
return null; | |||||
} | |||||
bytes[0] = (byte) (int) (l & 0xFF); | |||||
l = Integer.parseInt(elements[1]); | |||||
if ((l < 0L) || (l > 16777215L)) { | |||||
return null; | |||||
} | |||||
bytes[1] = (byte) (int) (l >> 16 & 0xFF); | |||||
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); | |||||
bytes[3] = (byte) (int) (l & 0xFF); | |||||
break; | |||||
case 3: | |||||
for (i = 0; i < 2; ++i) { | |||||
l = Integer.parseInt(elements[i]); | |||||
if ((l < 0L) || (l > 255L)) { | |||||
return null; | |||||
} | |||||
bytes[i] = (byte) (int) (l & 0xFF); | |||||
} | |||||
l = Integer.parseInt(elements[2]); | |||||
if ((l < 0L) || (l > 65535L)) { | |||||
return null; | |||||
} | |||||
bytes[2] = (byte) (int) (l >> 8 & 0xFF); | |||||
bytes[3] = (byte) (int) (l & 0xFF); | |||||
break; | |||||
case 4: | |||||
for (i = 0; i < 4; ++i) { | |||||
l = Integer.parseInt(elements[i]); | |||||
if ((l < 0L) || (l > 255L)) { | |||||
return null; | |||||
} | |||||
bytes[i] = (byte) (int) (l & 0xFF); | |||||
} | |||||
break; | |||||
default: | |||||
return null; | |||||
} | |||||
} catch (NumberFormatException e) { | |||||
return null; | |||||
} | |||||
return bytes; | |||||
} | |||||
public static String getHostIp() { | |||||
try { | |||||
return InetAddress.getLocalHost().getHostAddress(); | |||||
} catch (UnknownHostException e) { | |||||
} | |||||
return "127.0.0.1"; | |||||
} | |||||
public static String getHostName() { | |||||
try { | |||||
return InetAddress.getLocalHost().getHostName(); | |||||
} catch (UnknownHostException e) { | |||||
} | |||||
return "未知"; | |||||
} | |||||
} |
@@ -0,0 +1,501 @@ | |||||
// Generated by CoffeeScript 1.7.1 | |||||
/* | |||||
Stomp Over WebSocket http://www.jmesnil.net/stomp-websocket/doc/ | Apache License V2.0 | |||||
Copyright (C) 2010-2013 [Jeff Mesnil](http://jmesnil.net/) | |||||
Copyright (C) 2012 [FuseSource, Inc.](http://fusesource.com) | |||||
*/ | |||||
(function() { | |||||
var Byte, Client, Frame, Stomp, | |||||
__hasProp = {}.hasOwnProperty, | |||||
__slice = [].slice; | |||||
Byte = { | |||||
LF: '\x0A', | |||||
NULL: '\x00' | |||||
}; | |||||
Frame = (function() { | |||||
var unmarshallSingle; | |||||
function Frame(command, headers, body) { | |||||
this.command = command; | |||||
this.headers = headers != null ? headers : {}; | |||||
this.body = body != null ? body : ''; | |||||
} | |||||
Frame.prototype.toString = function() { | |||||
var lines, name, skipContentLength, value, _ref; | |||||
lines = [this.command]; | |||||
skipContentLength = this.headers['content-length'] === false ? true : false; | |||||
if (skipContentLength) { | |||||
delete this.headers['content-length']; | |||||
} | |||||
_ref = this.headers; | |||||
for (name in _ref) { | |||||
if (!__hasProp.call(_ref, name)) continue; | |||||
value = _ref[name]; | |||||
lines.push("" + name + ":" + value); | |||||
} | |||||
if (this.body && !skipContentLength) { | |||||
lines.push("content-length:" + (Frame.sizeOfUTF8(this.body))); | |||||
} | |||||
lines.push(Byte.LF + this.body); | |||||
return lines.join(Byte.LF); | |||||
}; | |||||
Frame.sizeOfUTF8 = function(s) { | |||||
if (s) { | |||||
return encodeURI(s).match(/%..|./g).length; | |||||
} else { | |||||
return 0; | |||||
} | |||||
}; | |||||
unmarshallSingle = function(data) { | |||||
var body, chr, command, divider, headerLines, headers, i, idx, len, line, start, trim, _i, _j, _len, _ref, _ref1; | |||||
divider = data.search(RegExp("" + Byte.LF + Byte.LF)); | |||||
headerLines = data.substring(0, divider).split(Byte.LF); | |||||
command = headerLines.shift(); | |||||
headers = {}; | |||||
trim = function(str) { | |||||
return str.replace(/^\s+|\s+$/g, ''); | |||||
}; | |||||
_ref = headerLines.reverse(); | |||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |||||
line = _ref[_i]; | |||||
idx = line.indexOf(':'); | |||||
headers[trim(line.substring(0, idx))] = trim(line.substring(idx + 1)); | |||||
} | |||||
body = ''; | |||||
start = divider + 2; | |||||
if (headers['content-length']) { | |||||
len = parseInt(headers['content-length']); | |||||
body = ('' + data).substring(start, start + len); | |||||
} else { | |||||
chr = null; | |||||
for (i = _j = start, _ref1 = data.length; start <= _ref1 ? _j < _ref1 : _j > _ref1; i = start <= _ref1 ? ++_j : --_j) { | |||||
chr = data.charAt(i); | |||||
if (chr === Byte.NULL) { | |||||
break; | |||||
} | |||||
body += chr; | |||||
} | |||||
} | |||||
return new Frame(command, headers, body); | |||||
}; | |||||
Frame.unmarshall = function(datas) { | |||||
var frame, frames, last_frame, r; | |||||
frames = datas.split(RegExp("" + Byte.NULL + Byte.LF + "*")); | |||||
r = { | |||||
frames: [], | |||||
partial: '' | |||||
}; | |||||
r.frames = (function() { | |||||
var _i, _len, _ref, _results; | |||||
_ref = frames.slice(0, -1); | |||||
_results = []; | |||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |||||
frame = _ref[_i]; | |||||
_results.push(unmarshallSingle(frame)); | |||||
} | |||||
return _results; | |||||
})(); | |||||
last_frame = frames.slice(-1)[0]; | |||||
if (last_frame === Byte.LF || (last_frame.search(RegExp("" + Byte.NULL + Byte.LF + "*$"))) !== -1) { | |||||
r.frames.push(unmarshallSingle(last_frame)); | |||||
} else { | |||||
r.partial = last_frame; | |||||
} | |||||
return r; | |||||
}; | |||||
Frame.marshall = function(command, headers, body) { | |||||
var frame; | |||||
frame = new Frame(command, headers, body); | |||||
return frame.toString() + Byte.NULL; | |||||
}; | |||||
return Frame; | |||||
})(); | |||||
Client = (function() { | |||||
var now; | |||||
function Client(ws) { | |||||
this.ws = ws; | |||||
this.ws.binaryType = "arraybuffer"; | |||||
this.counter = 0; | |||||
this.connected = false; | |||||
this.heartbeat = { | |||||
outgoing: 10000, | |||||
incoming: 10000 | |||||
}; | |||||
this.maxWebSocketFrameSize = 16 * 1024; | |||||
this.subscriptions = {}; | |||||
this.partialData = ''; | |||||
} | |||||
Client.prototype.debug = function(message) { | |||||
var _ref; | |||||
return typeof window !== "undefined" && window !== null ? (_ref = window.console) != null ? _ref.log(message) : void 0 : void 0; | |||||
}; | |||||
now = function() { | |||||
if (Date.now) { | |||||
return Date.now(); | |||||
} else { | |||||
return new Date().valueOf; | |||||
} | |||||
}; | |||||
Client.prototype._transmit = function(command, headers, body) { | |||||
var out; | |||||
out = Frame.marshall(command, headers, body); | |||||
if (typeof this.debug === "function") { | |||||
this.debug(">>> " + out); | |||||
} | |||||
while (true) { | |||||
if (out.length > this.maxWebSocketFrameSize) { | |||||
this.ws.send(out.substring(0, this.maxWebSocketFrameSize)); | |||||
out = out.substring(this.maxWebSocketFrameSize); | |||||
if (typeof this.debug === "function") { | |||||
this.debug("remaining = " + out.length); | |||||
} | |||||
} else { | |||||
return this.ws.send(out); | |||||
} | |||||
} | |||||
}; | |||||
Client.prototype._setupHeartbeat = function(headers) { | |||||
var serverIncoming, serverOutgoing, ttl, v, _ref, _ref1; | |||||
if ((_ref = headers.version) !== Stomp.VERSIONS.V1_1 && _ref !== Stomp.VERSIONS.V1_2) { | |||||
return; | |||||
} | |||||
_ref1 = (function() { | |||||
var _i, _len, _ref1, _results; | |||||
_ref1 = headers['heart-beat'].split(","); | |||||
_results = []; | |||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) { | |||||
v = _ref1[_i]; | |||||
_results.push(parseInt(v)); | |||||
} | |||||
return _results; | |||||
})(), serverOutgoing = _ref1[0], serverIncoming = _ref1[1]; | |||||
if (!(this.heartbeat.outgoing === 0 || serverIncoming === 0)) { | |||||
ttl = Math.max(this.heartbeat.outgoing, serverIncoming); | |||||
if (typeof this.debug === "function") { | |||||
this.debug("send PING every " + ttl + "ms"); | |||||
} | |||||
this.pinger = Stomp.setInterval(ttl, (function(_this) { | |||||
return function() { | |||||
_this.ws.send(Byte.LF); | |||||
return typeof _this.debug === "function" ? _this.debug(">>> PING") : void 0; | |||||
}; | |||||
})(this)); | |||||
} | |||||
if (!(this.heartbeat.incoming === 0 || serverOutgoing === 0)) { | |||||
ttl = Math.max(this.heartbeat.incoming, serverOutgoing); | |||||
if (typeof this.debug === "function") { | |||||
this.debug("check PONG every " + ttl + "ms"); | |||||
} | |||||
return this.ponger = Stomp.setInterval(ttl, (function(_this) { | |||||
return function() { | |||||
var delta; | |||||
delta = now() - _this.serverActivity; | |||||
if (delta > ttl * 2) { | |||||
if (typeof _this.debug === "function") { | |||||
_this.debug("did not receive server activity for the last " + delta + "ms"); | |||||
} | |||||
return _this.ws.close(); | |||||
} | |||||
}; | |||||
})(this)); | |||||
} | |||||
}; | |||||
Client.prototype._parseConnect = function() { | |||||
var args, connectCallback, errorCallback, headers; | |||||
args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; | |||||
headers = {}; | |||||
switch (args.length) { | |||||
case 2: | |||||
headers = args[0], connectCallback = args[1]; | |||||
break; | |||||
case 3: | |||||
if (args[1] instanceof Function) { | |||||
headers = args[0], connectCallback = args[1], errorCallback = args[2]; | |||||
} else { | |||||
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2]; | |||||
} | |||||
break; | |||||
case 4: | |||||
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3]; | |||||
break; | |||||
default: | |||||
headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3], headers.host = args[4]; | |||||
} | |||||
return [headers, connectCallback, errorCallback]; | |||||
}; | |||||
Client.prototype.connect = function() { | |||||
var args, errorCallback, headers, out; | |||||
args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; | |||||
out = this._parseConnect.apply(this, args); | |||||
headers = out[0], this.connectCallback = out[1], errorCallback = out[2]; | |||||
if (typeof this.debug === "function") { | |||||
this.debug("Opening Web Socket..."); | |||||
} | |||||
this.ws.onmessage = (function(_this) { | |||||
return function(evt) { | |||||
var arr, c, client, data, frame, messageID, onreceive, subscription, unmarshalledData, _i, _len, _ref, _results; | |||||
data = typeof ArrayBuffer !== 'undefined' && evt.data instanceof ArrayBuffer ? (arr = new Uint8Array(evt.data), typeof _this.debug === "function" ? _this.debug("--- got data length: " + arr.length) : void 0, ((function() { | |||||
var _i, _len, _results; | |||||
_results = []; | |||||
for (_i = 0, _len = arr.length; _i < _len; _i++) { | |||||
c = arr[_i]; | |||||
_results.push(String.fromCharCode(c)); | |||||
} | |||||
return _results; | |||||
})()).join('')) : evt.data; | |||||
_this.serverActivity = now(); | |||||
if (data === Byte.LF) { | |||||
if (typeof _this.debug === "function") { | |||||
_this.debug("<<< PONG"); | |||||
} | |||||
return; | |||||
} | |||||
if (typeof _this.debug === "function") { | |||||
_this.debug("<<< " + data); | |||||
} | |||||
unmarshalledData = Frame.unmarshall(_this.partialData + data); | |||||
_this.partialData = unmarshalledData.partial; | |||||
_ref = unmarshalledData.frames; | |||||
_results = []; | |||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |||||
frame = _ref[_i]; | |||||
switch (frame.command) { | |||||
case "CONNECTED": | |||||
if (typeof _this.debug === "function") { | |||||
_this.debug("connected to server " + frame.headers.server); | |||||
} | |||||
_this.connected = true; | |||||
_this._setupHeartbeat(frame.headers); | |||||
_results.push(typeof _this.connectCallback === "function" ? _this.connectCallback(frame) : void 0); | |||||
break; | |||||
case "MESSAGE": | |||||
subscription = frame.headers.subscription; | |||||
onreceive = _this.subscriptions[subscription] || _this.onreceive; | |||||
if (onreceive) { | |||||
client = _this; | |||||
messageID = frame.headers["message-id"]; | |||||
frame.ack = function(headers) { | |||||
if (headers == null) { | |||||
headers = {}; | |||||
} | |||||
return client.ack(messageID, subscription, headers); | |||||
}; | |||||
frame.nack = function(headers) { | |||||
if (headers == null) { | |||||
headers = {}; | |||||
} | |||||
return client.nack(messageID, subscription, headers); | |||||
}; | |||||
_results.push(onreceive(frame)); | |||||
} else { | |||||
_results.push(typeof _this.debug === "function" ? _this.debug("Unhandled received MESSAGE: " + frame) : void 0); | |||||
} | |||||
break; | |||||
case "RECEIPT": | |||||
_results.push(typeof _this.onreceipt === "function" ? _this.onreceipt(frame) : void 0); | |||||
break; | |||||
case "ERROR": | |||||
_results.push(typeof errorCallback === "function" ? errorCallback(frame) : void 0); | |||||
break; | |||||
default: | |||||
_results.push(typeof _this.debug === "function" ? _this.debug("Unhandled frame: " + frame) : void 0); | |||||
} | |||||
} | |||||
return _results; | |||||
}; | |||||
})(this); | |||||
this.ws.onclose = (function(_this) { | |||||
return function() { | |||||
var msg; | |||||
msg = "Whoops! Lost connection to " + _this.ws.url; | |||||
if (typeof _this.debug === "function") { | |||||
_this.debug(msg); | |||||
} | |||||
_this._cleanUp(); | |||||
return typeof errorCallback === "function" ? errorCallback(msg) : void 0; | |||||
}; | |||||
})(this); | |||||
return this.ws.onopen = (function(_this) { | |||||
return function() { | |||||
if (typeof _this.debug === "function") { | |||||
_this.debug('Web Socket Opened...'); | |||||
} | |||||
headers["accept-version"] = Stomp.VERSIONS.supportedVersions(); | |||||
headers["heart-beat"] = [_this.heartbeat.outgoing, _this.heartbeat.incoming].join(','); | |||||
return _this._transmit("CONNECT", headers); | |||||
}; | |||||
})(this); | |||||
}; | |||||
Client.prototype.disconnect = function(disconnectCallback, headers) { | |||||
if (headers == null) { | |||||
headers = {}; | |||||
} | |||||
this._transmit("DISCONNECT", headers); | |||||
this.ws.onclose = null; | |||||
this.ws.close(); | |||||
this._cleanUp(); | |||||
return typeof disconnectCallback === "function" ? disconnectCallback() : void 0; | |||||
}; | |||||
Client.prototype._cleanUp = function() { | |||||
this.connected = false; | |||||
if (this.pinger) { | |||||
Stomp.clearInterval(this.pinger); | |||||
} | |||||
if (this.ponger) { | |||||
return Stomp.clearInterval(this.ponger); | |||||
} | |||||
}; | |||||
Client.prototype.send = function(destination, headers, body) { | |||||
if (headers == null) { | |||||
headers = {}; | |||||
} | |||||
if (body == null) { | |||||
body = ''; | |||||
} | |||||
headers.destination = destination; | |||||
return this._transmit("SEND", headers, body); | |||||
}; | |||||
Client.prototype.subscribe = function(destination, callback, headers) { | |||||
var client; | |||||
if (headers == null) { | |||||
headers = {}; | |||||
} | |||||
if (!headers.id) { | |||||
headers.id = "sub-" + this.counter++; | |||||
} | |||||
headers.destination = destination; | |||||
this.subscriptions[headers.id] = callback; | |||||
this._transmit("SUBSCRIBE", headers); | |||||
client = this; | |||||
return { | |||||
id: headers.id, | |||||
unsubscribe: function() { | |||||
return client.unsubscribe(headers.id); | |||||
} | |||||
}; | |||||
}; | |||||
Client.prototype.unsubscribe = function(id) { | |||||
delete this.subscriptions[id]; | |||||
return this._transmit("UNSUBSCRIBE", { | |||||
id: id | |||||
}); | |||||
}; | |||||
Client.prototype.begin = function(transaction) { | |||||
var client, txid; | |||||
txid = transaction || "tx-" + this.counter++; | |||||
this._transmit("BEGIN", { | |||||
transaction: txid | |||||
}); | |||||
client = this; | |||||
return { | |||||
id: txid, | |||||
commit: function() { | |||||
return client.commit(txid); | |||||
}, | |||||
abort: function() { | |||||
return client.abort(txid); | |||||
} | |||||
}; | |||||
}; | |||||
Client.prototype.commit = function(transaction) { | |||||
return this._transmit("COMMIT", { | |||||
transaction: transaction | |||||
}); | |||||
}; | |||||
Client.prototype.abort = function(transaction) { | |||||
return this._transmit("ABORT", { | |||||
transaction: transaction | |||||
}); | |||||
}; | |||||
Client.prototype.ack = function(messageID, subscription, headers) { | |||||
if (headers == null) { | |||||
headers = {}; | |||||
} | |||||
headers["message-id"] = messageID; | |||||
headers.subscription = subscription; | |||||
return this._transmit("ACK", headers); | |||||
}; | |||||
Client.prototype.nack = function(messageID, subscription, headers) { | |||||
if (headers == null) { | |||||
headers = {}; | |||||
} | |||||
headers["message-id"] = messageID; | |||||
headers.subscription = subscription; | |||||
return this._transmit("NACK", headers); | |||||
}; | |||||
return Client; | |||||
})(); | |||||
Stomp = { | |||||
VERSIONS: { | |||||
V1_0: '1.0', | |||||
V1_1: '1.1', | |||||
V1_2: '1.2', | |||||
supportedVersions: function() { | |||||
return '1.1,1.0'; | |||||
} | |||||
}, | |||||
client: function(url, protocols) { | |||||
var klass, ws; | |||||
if (protocols == null) { | |||||
protocols = ['v10.stomp', 'v11.stomp']; | |||||
} | |||||
klass = Stomp.WebSocketClass || WebSocket; | |||||
ws = new klass(url, protocols); | |||||
return new Client(ws); | |||||
}, | |||||
over: function(ws) { | |||||
return new Client(ws); | |||||
}, | |||||
Frame: Frame | |||||
}; | |||||
if (typeof exports !== "undefined" && exports !== null) { | |||||
exports.Stomp = Stomp; | |||||
} | |||||
if (typeof window !== "undefined" && window !== null) { | |||||
Stomp.setInterval = function(interval, f) { | |||||
return window.setInterval(f, interval); | |||||
}; | |||||
Stomp.clearInterval = function(id) { | |||||
return window.clearInterval(id); | |||||
}; | |||||
window.Stomp = Stomp; | |||||
} else if (!exports) { | |||||
self.Stomp = Stomp; | |||||
} | |||||
}).call(this); |
@@ -0,0 +1,97 @@ | |||||
<!DOCTYPE html> | |||||
<html lang="en"> | |||||
<head> | |||||
<meta charset="UTF-8"> | |||||
<title>服务器信息</title> | |||||
<!-- import CSS --> | |||||
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> | |||||
</head> | |||||
<body> | |||||
<div id="app"> | |||||
<el-container> | |||||
<el-header> | |||||
<el-button @click="_initSockJs">手动连接</el-button> | |||||
<el-button @click="_destroySockJs" danger>断开连接</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"> | |||||
<div slot="header"> | |||||
<span>CPU信息</span> | |||||
</div> | |||||
<el-table :data="server.cpu[0].data" 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-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> | |||||
const wsHost = "http://localhost:8080/demo/notification"; | |||||
const wsTopic = "/topic/server"; | |||||
const app = new Vue({ | |||||
el: '#app', | |||||
data: function () { | |||||
return { | |||||
stompClient: {}, | |||||
socket: {}, | |||||
server: { | |||||
cpu: [], | |||||
jvm: [], | |||||
mem: [], | |||||
sysFile: [], | |||||
sys: [] | |||||
} | |||||
} | |||||
}, | |||||
methods: { | |||||
_initSockJs() { | |||||
this.socket = new SockJS(wsHost); | |||||
this.stompClient = Stomp.over(this.socket); | |||||
this.stompClient.connect({}, (frame) => { | |||||
console.log('websocket连接成功:' + frame); | |||||
this.$message('websocket服务器连接成功'); | |||||
// 另外再注册一下消息推送 | |||||
this.stompClient.subscribe(wsTopic, function (response) { | |||||
this.server = JSON.parse(response); | |||||
}); | |||||
}); | |||||
}, | |||||
_destroySockJs() { | |||||
if (this.stompClient != null) { | |||||
this.stompClient.disconnect(); | |||||
this.socket.onclose; | |||||
this.socket.close(); | |||||
this.stompClient = {}; | |||||
this.socket = {}; | |||||
} | |||||
console.log('websocket断开成功!'); | |||||
this.$message.error('websocket断开成功!'); | |||||
} | |||||
}, | |||||
mounted() { | |||||
this._initSockJs(); | |||||
}, | |||||
beforeDestroy() { | |||||
this._destroySockJs(); | |||||
} | |||||
}) | |||||
</script> | |||||
</html> |