diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 76127f0..6ee4e52 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -62,6 +62,7 @@ 2.7.0 3.0.6 4.1.113.Final + 6.6.5 2.17.0 1.27.1 @@ -492,6 +493,13 @@ ${jsoup.version} + + + com.github.oshi + oshi-core + ${oshi-version} + + org.pf4j pf4j diff --git a/framework/commons/pom.xml b/framework/commons/pom.xml index 6bf3c23..61905b8 100644 --- a/framework/commons/pom.xml +++ b/framework/commons/pom.xml @@ -144,6 +144,11 @@ easy-trans-anno + + com.github.oshi + oshi-core + + org.springframework.boot diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Cpu.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Cpu.java new file mode 100644 index 0000000..fb660c7 --- /dev/null +++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Cpu.java @@ -0,0 +1,44 @@ +package cd.casic.framework.commons.util.monitor; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * + * @author mian-bin + * @Description Cpu + * @date 2025/1/10 15:29 + */ +@Data +@Accessors(chain = true) +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; +} diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Jvm.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Jvm.java new file mode 100644 index 0000000..98673dc --- /dev/null +++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Jvm.java @@ -0,0 +1,39 @@ +package cd.casic.framework.commons.util.monitor; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * + * @author mian-bin + * @Description Jvm + * @date 2025/1/10 15:31 + */ +@Data +@Accessors(chain = true) +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; +} diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Mem.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Mem.java new file mode 100644 index 0000000..1417bf4 --- /dev/null +++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Mem.java @@ -0,0 +1,46 @@ +package cd.casic.framework.commons.util.monitor; + +import cd.casic.framework.commons.util.number.ArithUtil; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + * + * @author mian-bin + * @Description Mem + * @date 2025/1/10 15:31 + */ +@Setter +@Accessors(chain = true) +public class Mem { + /** + * 内存总量 + */ + private double total; + + /** + * 已用内存 + */ + private double used; + + /** + * 剩余内存 + */ + private double free; + + public double getTotal() { + return ArithUtil.div(total, (1024 * 1024 * 1024), 2); + } + + public double getUsed() { + return ArithUtil.div(used, (1024 * 1024 * 1024), 2); + } + + public double getFree() { + return ArithUtil.div(free, (1024 * 1024 * 1024), 2); + } + + public double getUsage() { + return ArithUtil.mul(ArithUtil.div(used, total, 4), 100); + } +} diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Server.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Server.java new file mode 100644 index 0000000..a701bc2 --- /dev/null +++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Server.java @@ -0,0 +1,167 @@ +package cd.casic.framework.commons.util.monitor; + +import cd.casic.framework.commons.util.network.IpUtil; +import cd.casic.framework.commons.util.number.ArithUtil; +import lombok.Data; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +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; + +/** + * + * @author mian-bin + * @Description Server + * @date 2025/1/10 15:34 + */ +@Data +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 sysFiles = new LinkedList(); + + 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[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()]; + long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()]; + long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()]; + long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()]; + long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()]; + long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()]; + long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()]; + long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()). + setTotal(totalCpu). + setSys(cSys). + setUsed(user). + setWait(iowait). + 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()). + setComputerIp(IpUtil.getHostIp()). + setOsName(props.getProperty("os.name")). + setUserDir(props.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() throws UnknownHostException { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime(). + totalMemory()). + setMax(Runtime.getRuntime().maxMemory()). + setFree(Runtime.getRuntime().freeMemory()). + setVersion(props.getProperty("java.version")). + setHome(props.getProperty("java.home")); + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) { + FileSystem fileSystem = os.getFileSystem(); + List fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFile sysFile = new SysFile() + .setDirName(fs.getMount()) + .setSysTypeName(fs.getType()) + .setTypeName(fs.getName()) + .setTotal(convertFileSize(total)) + .setFree(convertFileSize(free)) + .setUsed(convertFileSize(used)) + .setUsage(ArithUtil.mul(ArithUtil.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); + } + } +} diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Sys.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Sys.java new file mode 100644 index 0000000..ad1a86c --- /dev/null +++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/Sys.java @@ -0,0 +1,36 @@ +package cd.casic.framework.commons.util.monitor; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 系统相关 + * + * @author mian-bin + * @Description Sys + * @date 2025/1/10 15:35 + */ +@Data +@Accessors(chain = true) +public class Sys { + /** + * 服务器名称 + */ + private String computerName; + + /** + * 服务器Ip + */ + private String computerIp; + + /** + * 项目路径 + */ + private String userDir; + + /** + * 操作系统 + */ + private String osName; + +} diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/SysFile.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/SysFile.java new file mode 100644 index 0000000..995ff1c --- /dev/null +++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/monitor/SysFile.java @@ -0,0 +1,49 @@ +package cd.casic.framework.commons.util.monitor; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * + * @author mian-bin + * @Description SysFile + * @date 2025/1/10 15:36 + */ +@Data +@Accessors(chain = true) +public class SysFile { + /** + * 盘符路径 + */ + private String dirName; + + /** + * 盘符类型 + */ + private String sysTypeName; + + /** + * 文件类型 + */ + private String typeName; + + /** + * 总大小 + */ + private String total; + + /** + * 剩余大小 + */ + private String free; + + /** + * 已经使用量 + */ + private String used; + + /** + * 资源的使用率 + */ + private double usage; +} diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/network/IpUtil.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/network/IpUtil.java new file mode 100644 index 0000000..3567d4a --- /dev/null +++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/network/IpUtil.java @@ -0,0 +1,101 @@ +package cd.casic.framework.commons.util.network; + +import jakarta.servlet.http.HttpServletRequest; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Ip工具类 + * + * @author mian-bin + * @Description Ip工具类 + * @date 2025/1/10 15:29 + */ + +public class IpUtil { + + /** + * 获取Ip + * + * @param request request + * @return String + */ + public static String getIpAddr(HttpServletRequest request) { + String ipAddress = null; + try { + ipAddress = request.getHeader("x-forwarded-for"); + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + if ("127.0.0.1".equals(ipAddress)) { + // 根据网卡取本机配置的IP + InetAddress inet = null; + try { + inet = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + ipAddress = inet.getHostAddress(); + } + } + if (ipAddress != null && ipAddress.length() > 15) { + // = 15 + if (ipAddress.indexOf(",") > 0) { + ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); + } + } + } catch (Exception e) { + ipAddress = ""; + } + return ipAddress; + } + + + /** + * 获取当前服务的ip和端口 + */ + public static String getUrl(int serverPort) { + InetAddress address = null; + try { + address = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + return "http://" + address.getHostAddress() + ":" + serverPort; + } + + 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 "未知"; + } + + /** + * 基路径 + * + * @param request + * @return + */ + public static String basePath(HttpServletRequest request) { + String bathPath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/"; + // log.info("当前域名:[{}]", bathPath); + return bathPath; + // return "http://wuwenbin.me/"; + } +} diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/number/ArithUtil.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/number/ArithUtil.java new file mode 100644 index 0000000..77231de --- /dev/null +++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/number/ArithUtil.java @@ -0,0 +1,108 @@ +package cd.casic.framework.commons.util.number; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 计算内存需要用到的算数帮助类 + * + * @author mian-bin + * @Description ArithUtil + * @date 2025/1/10 15:33 + */ +public class ArithUtil { + /** + * 默认除法运算精度 + */ + private static final int DEF_DIV_SCALE = 10; + + /** + * 这个类不能实例化 + */ + private ArithUtil() { + } + + /** + * 提供精确的加法运算。 + * @param v1 被加数 + * @param v2 加数 + * @return 两个参数的和 + */ + public static double add(double v1, double v2) { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.add(b2).doubleValue(); + } + + /** + * 提供精确的减法运算。 + * @param v1 被减数 + * @param v2 减数 + * @return 两个参数的差 + */ + public static double sub(double v1, double v2) { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.subtract(b2).doubleValue(); + } + + /** + * 提供精确的乘法运算。 + * @param v1 被乘数 + * @param v2 乘数 + * @return 两个参数的积 + */ + public static double mul(double v1, double v2) { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.multiply(b2).doubleValue(); + } + + /** + * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 + * 小数点以后10位,以后的数字四舍五入。 + * @param v1 被除数 + * @param v2 除数 + * @return 两个参数的商 + */ + public static double div(double v1, double v2) { + return div(v1, v2, DEF_DIV_SCALE); + } + + /** + * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 + * 定精度,以后的数字四舍五入。 + * @param v1 被除数 + * @param v2 除数 + * @param scale 表示表示需要精确到小数点以后几位。 + * @return 两个参数的商 + */ + public static double div(double v1, double v2, int scale) { + if (scale < 0) { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + if (b1.compareTo(BigDecimal.ZERO) == 0) { + return BigDecimal.ZERO.doubleValue(); + } + return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); + } + + /** + * 提供精确的小数位四舍五入处理。 + * @param v 需要四舍五入的数字 + * @param scale 小数点后保留几位 + * @return 四舍五入后的结果 + */ + public static double round(double v, int scale) { + if (scale < 0) { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b = new BigDecimal(Double.toString(v)); + BigDecimal one = new BigDecimal("1"); + return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); + } +}