本文作者:程序员飞云
展示效果


oshi

引入依赖
还需要引入lombok
<!-- https://mvnrepository.com/artifact/com.github.oshi/oshi-core --><dependency> <groupId>com.github.oshi</groupId> <artifactId>oshi-core</artifactId> <version>6.6.5</version></dependency><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId></dependency><dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version></dependency>编写监控对象实体类
包含Cpu、Disk、Jvm、Mem、Sys
import lombok.Data;
import java.io.Serializable;
/** * CPU相关信息 */@Datapublic class Cpu implements Serializable {
private static final long serialVersionUID = 1L;
/** * 核心数 */ private int cpuNum;
/** * CPU总的使用率 */ private double total;
/** * CPU系统使用率 */ private double sys;
/** * CPU用户使用率 */ private double used;
/** * CPU当前等待率 */ private double wait;
/** * CPU当前空闲率 */ private double free;
}import lombok.Data;
import java.io.Serializable;
/** * 系统文件相关信息 */@Datapublic class Disk implements Serializable {
private static final long serialVersionUID = 1L;
/** * 盘符路径 */ private String dirName;
/** * 盘符类型 */ private String sysTypeName;
/** * 文件类型 */ private String typeName;
/** * 总大小 */ private String total;
/** * 剩余大小 */ private String free;
/** * 已经使用量 */ private String used;
/** * 资源的使用率 */ private double usage;
}import lombok.Data;
import java.io.Serializable;
/** * JVM相关信息 */@Datapublic class Jvm implements Serializable {
private static final long serialVersionUID = 1L;
/** * 当前JVM占用的内存总数(M) */ private double total;
/** * JVM最大可用内存总数(M) */ private double max;
/** * JVM空闲内存(M) */ private double free;
/** * JVM内存使用率 */ private double usage;
/** * JDK版本 */ private String version;
/** * JDK路径 */ private String home;
/** * JDK名称 */ private String name;
/** * 运行参数 */ private String inputArgs;
/** * JDK运行时间 */ private String runTime;
/** * JDK启动时间 */ private String startTime;}import lombok.Data;
import java.io.Serializable;
/** * 內存相关信息 */@Datapublic class Mem implements Serializable {
private static final long serialVersionUID = 1L;
/** * 内存总量 */ private double total;
/** * 已用内存 */ private double used;
/** * 剩余内存 */ private double free;
/** * 使用率 */ private double usage;
}import lombok.Data;
import java.io.Serializable;
/** * 系统相关信息 */@Datapublic class Sys implements Serializable {
private static final long serialVersionUID = 1L;
/** * 服务器名称 */ private String computerName;
/** * 服务器Ip */ private String computerIp;
/** * 项目路径 */ private String userDir;
/** * 操作系统 */ private String osName;
/** * 系统架构 */ private String osArch;
}工具类
也可以不需要这些工具类
获取当前Ip信息
package com.sky.utils;
import cn.hutool.http.HttpUtil;import cn.hutool.json.JSON;import cn.hutool.json.JSONObject;import cn.hutool.json.JSONUtil;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;import java.net.InetAddress;import java.net.UnknownHostException;
/** * IP工具类 */@Slf4jpublic class IpUtils {
public static String getIpAddr(HttpServletRequest request) { 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; }
/** * 根据IP获取所在地址 * * @param ip Ip地址 * @return String (广州省 广州市) * @author fzr */ public static String getRealAddressByIP(String ip) { String IP_URL = "https://whois.pconline.com.cn/ipJson.jsp"; String UNKNOWN = "XX XX";
// 内网不查询 if (IpUtils.internalIp(ip)) { return "内网IP"; } try { String rspStr = HttpUtil.get(IP_URL + "ip=" + ip + "&json=true" + "GBK"); if (StringUtils.isEmpty(rspStr)) { log.error("获取地理位置异常 {}", ip); return UNKNOWN; } // 使用正则表达式提取 JSON 部分 String jsonPart = rspStr.replaceAll(".*?\\{", "{").replaceAll("\\}.*", "}"); JSONObject obj = JSONUtil.parseObj(jsonPart); String region = obj.getStr("pro"); String city = obj.getStr("city"); return String.format("%s %s", region, city); } catch (Exception e) { log.error("获取地理位置异常 {}", ip); }
return UNKNOWN; }
/** * 检查是否为内部IP地址 * * @param ip IP地址 * @return 结果 */ public static boolean internalIp(String ip) { byte[] address = textToNumericFormatV4(ip); return internalIp(address) || "127.0.0.1".equals(ip); }
/** * 检查是否为内部IP地址 * * @param address byte地址 * @return 结果 * @author fzr */ private static boolean internalIp(byte[] address) { if (address == null || address.length < 2) { return true; } final byte b0 = address[0]; final byte b1 = address[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: if (b1 == SECTION_6) { return true; } default: return false; } }
/** * 将IPv4地址转换成字节 * * @param text IPv4地址 * @return byte 字节 * @author fzr */ public static byte[] textToNumericFormatV4(String text) { if (text.isEmpty()) { 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; }
/** * 获取IP地址 * * @return 本地IP地址 * @author fzr */ public static String getHostIp() { try { return InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException ignored) { } return "127.0.0.1"; }
/** * 获取主机名 * * @return 本地主机名 * @author fzr */ public static String getHostName() { try { return InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException ignored) { } return "未知"; }
/** * 从多级反向代理中获得第一个非unknown IP地址 * * @param ip 获得的IP地址 * @return 第一个非unknown IP地址 * @author fzr */ public static String getMultistageReverseProxyIp(String ip) { if (ip != null && ip.indexOf(",") > 0) { final String[] ips = ip.trim().split(","); for (String subIp : ips) { if (!isUnknown(subIp)) { ip = subIp; break; } } } return ip; }
/** * 检测给定字符串是否为未知,多用于检测HTTP请求相关 * * @param checkString 被检测的字符串 * @return 是否未知 * @author fzr */ public static boolean isUnknown(String checkString) { return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); }
public static void main(String[] args) { String ip = "xxx"; String address = getRealAddressByIP(ip); System.out.println(address); }}算术运算工具
package com.sky.utils;
import java.math.BigDecimal;import java.math.RoundingMode;
/** * 算术运算工具 */public class ArithUtils {
/** 默认除法运算精度 */ private static final int DEF_DIV_SCALE = 10;
/** 这个类不能实例化 */ private ArithUtils() {}
/** * 提供精确的加法运算 * * @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 = BigDecimal.ONE; return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); }
}时间工具类
package com.mdd.common.util;
import java.lang.management.ManagementFactory;import java.text.DateFormat;import java.text.ParsePosition;import java.text.SimpleDateFormat;import java.util.*;import java.util.regex.Pattern;
public class TimeUtils {
/** * 时间戳转日期(默认格式) * * @author fzr * @param time 时间戳 * @return String */ public static String timestampToDate(Long time) { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time * 1000)); }
/** * 时间戳转日期(默认格式) * * @author fzr * @param time 时间戳 * @return String */ public static String timestampToDate(String time) { if (time == null) { time = "0"; } long longTime = Long.parseLong(time); return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(longTime * 1000)); }
/** * 时间戳转日期(指定格式) * * @author fzr * @param time 时间戳 * @param format 格式串 * @return String */ public static String timestampToDate(Long time, String format) { return new SimpleDateFormat(format).format(new Date(time * 1000)); }
/** * 时间戳转日期(指定格式) * * @author fzr * @param time 时间戳 * @param format 格式串 * @return String */ public static String timestampToDate(String time, String format) { long longTime = Long.parseLong(time); return new SimpleDateFormat(format).format(new Date(longTime * 1000)); }
/** * 日期转时间戳 * * @author fzr * @param date 日期 * @return Long */ public static Long dateToTimestamp(String date) { String dateTime = TimeUtils.formatDate(date); return (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).parse(dateTime, new ParsePosition(0)).getTime() / 1000; }
/** * 毫秒转日期时间 * * @author fzr * @param time 毫秒 * @return String */ public static String millisecondToDate(Long time) { Date date = new Date(); date.setTime(time); return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date); }
/** * 毫秒转日期时间 * * @author fzr * @param time 毫秒 * @return String */ public static String millisecondToDate(String time) { Date date = new Date(); date.setTime(Long.parseLong(time)); return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date); }
/** * 毫秒转日期时间 * * @author fzr * @param time 毫秒 * @param format 格式串 * @return String */ public static String millisecondToDate(Long time, String format) { Date date = new Date(); date.setTime(time); return new SimpleDateFormat(format).format(date); }
/** * 毫秒转日期时间 * * @author fzr * @param time 毫秒 * @param format 格式串 * @return String */ public static String millisecondToDate(String time, String format) { Date date = new Date(); date.setTime(Long.parseLong(time)); return new SimpleDateFormat(format).format(date); }
/** * 日期转固定格式 yyyy-MM-dd HH:mm:ss * * @author fzr * @param dateStr 日期时间 * @return String */ public static String formatDate(String dateStr){ dateStr = dateStr.trim(); HashMap<String, String> dateRegFormat = new HashMap<>(); dateRegFormat.put("^\\d{4}\\D+\\d{1,2}\\D+\\d{1,2}\\D+\\d{1,2}\\D+\\d{1,2}\\D+\\d{1,2}\\D*$", "yyyy-MM-dd-HH-mm-ss");//2014年3月12日 13时5分34秒,2014-03-12 12:05:34,2014/3/12 12:5:34 dateRegFormat.put("^\\d{4}\\D+\\d{2}\\D+\\d{2}\\D+\\d{2}\\D+\\d{2}$", "yyyy-MM-dd-HH-mm");//2014-03-12 12:05 dateRegFormat.put("^\\d{4}\\D+\\d{2}\\D+\\d{2}\\D+\\d{2}$", "yyyy-MM-dd-HH");//2014-03-12 12 dateRegFormat.put("^\\d{4}\\D+\\d{2}\\D+\\d{2}$", "yyyy-MM-dd");//2014-03-12 dateRegFormat.put("^\\d{4}\\D+\\d{2}$", "yyyy-MM");//2014-03 dateRegFormat.put("^\\d{4}$", "yyyy");//2014 dateRegFormat.put("^\\d{14}$", "yyyyMMddHHmmss");//20140312120534 dateRegFormat.put("^\\d{12}$", "yyyyMMddHHmm");//201403121205 dateRegFormat.put("^\\d{10}$", "yyyyMMddHH");//2014031212 dateRegFormat.put("^\\d{8}$", "yyyyMMdd");//20140312 dateRegFormat.put("^\\d{6}$", "yyyyMM");//201403 dateRegFormat.put("^\\d{2}\\s*:\\s*\\d{2}\\s*:\\s*\\d{2}$", "yyyy-MM-dd-HH-mm-ss");//13:05:34 拼接当前日期 dateRegFormat.put("^\\d{2}\\s*:\\s*\\d{2}$", "yyyy-MM-dd-HH-mm");//13:05 拼接当前日期 dateRegFormat.put("^\\d{2}\\D+\\d{1,2}\\D+\\d{1,2}$", "yy-MM-dd");//14.10.18(年.月.日) dateRegFormat.put("^\\d{1,2}\\D+\\d{1,2}$", "yyyy-dd-MM");//30.12(日.月) 拼接当前年份 dateRegFormat.put("^\\d{1,2}\\D+\\d{1,2}\\D+\\d{4}$", "dd-MM-yyyy");//12.21.2013(日.月.年)
String curDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); DateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); DateFormat formatter2; String dateReplace; String strSuccess = ""; try { for (String key : dateRegFormat.keySet()) { if (Pattern.compile(key).matcher(dateStr).matches()) { formatter2 = new SimpleDateFormat(dateRegFormat.get(key)); if (key.equals("^\\d{2}\\s*:\\s*\\d{2}\\s*:\\s*\\d{2}$") || key.equals("^\\d{2}\\s*:\\s*\\d{2}$")) { // 13:05:34 或 13:05 拼接当前日期 dateStr = curDate + "-" + dateStr; } else if (key.equals("^\\d{1,2}\\D+\\d{1,2}$")) { //21.1 (日.月) 拼接当前年份 dateStr = curDate.substring(0, 4) + "-" + dateStr; } dateReplace = dateStr.replaceAll("\\D+", "-"); strSuccess = formatter1.format(formatter2.parse(dateReplace)); break; } } return strSuccess; } catch (Exception ignored) { } return ""; }
/** * 返回当前时间戳 * * @author fzr * @return Long */ public static Long timestamp() { return System.currentTimeMillis() / 1000; }
/** * 返回当前Date型日期 * * @author fzr * @return Date() 当前日期 */ public static Date nowDate() { return new Date(); }
/** * 返回今日开始和结束的时间戳 * * @author fzr * @return List */ public static List<Long> today() { List<Long> list = new ArrayList<>(); // 开始时间 Calendar todayStart = Calendar.getInstance(); todayStart.set(Calendar.HOUR, 0); todayStart.set(Calendar.MINUTE, 0); todayStart.set(Calendar.SECOND, 0); todayStart.set(Calendar.MILLISECOND, 0); list.add(todayStart.getTime().getTime() / 1000 - 43200);
// 结束时间 Calendar todayEnd = Calendar.getInstance(); todayEnd.set(Calendar.HOUR_OF_DAY, 23); todayEnd.set(Calendar.MINUTE, 59); todayEnd.set(Calendar.SECOND, 59); todayEnd.set(Calendar.MILLISECOND, 999); list.add(todayEnd.getTime().getTime() / 1000);
return list; }
/** * 返回昨日开始和结束的时间戳 * * @author fzr * @return List */ public static List<Long> yesterday() { List<Long> today = TimeUtils.today(); List<Long> list = new ArrayList<>(); list.add(today.get(0) - 86400); list.add(today.get(1) - 86400); return list; }
/** * 返回本周开始和结束的时间戳 * * @author fzr * @return List */ public static List<Long> week() { List<Long> list = new ArrayList<>(); // 开始时间 Calendar cal = Calendar.getInstance(); cal.set(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0,0); cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); list.add(cal.getTimeInMillis() / 1000); // 结束时间 list.add(list.get(0) + ((7 * 24 * 60 * 60 * 1000) / 1000)-1); return list; }
/** * 返回上周开始和结束的时间戳 * * @author fzr * @return List */ public static List<Long> lastWeek() { List<Long> week = TimeUtils.week(); List<Long> list = new ArrayList<>(); list.add(week.get(0) - 604800); list.add(week.get(1) - 604800); return list; }
/** * 返回今天是周几 * * @author fzr * @return Long */ public static Long dayOfWeek() { Date date = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(date); boolean isFirstSunday = (cal.getFirstDayOfWeek() == Calendar.SUNDAY); long week = cal.get(Calendar.DAY_OF_WEEK); if(isFirstSunday){ week = (week -1) == 0? 7:(week - 1); } return week; }
/** * 返回本月开始和结束的时间戳 * * @author fzr * @return List */ public static List<Long> month() { List<Long> list = new ArrayList<>(); // 开始时间 Calendar calStart = Calendar.getInstance(); calStart.set(calStart.get(Calendar.YEAR),calStart.get(Calendar.MONTH), calStart.get(Calendar.DAY_OF_MONTH), 0, 0,0); calStart.set(Calendar.DAY_OF_MONTH,calStart.getActualMinimum(Calendar.DAY_OF_MONTH)); list.add(calStart.getTimeInMillis() / 1000);
// 结束时间 Calendar calEnd = Calendar.getInstance(); calEnd.set(calEnd.get(Calendar.YEAR),calEnd.get(Calendar.MONTH), calEnd.get(Calendar.DAY_OF_MONTH), 0, 0,0); calEnd.set(Calendar.DAY_OF_MONTH, calEnd.getActualMaximum(Calendar.DAY_OF_MONTH)); calEnd.set(Calendar.HOUR_OF_DAY, 24); list.add(calEnd.getTimeInMillis() / 1000 - 1); return list; }
/** * 返回上个月开始和结束的时间戳 * * @author fzr * @return List */ public static List<Long> lastMonth() { List<Long> list = new ArrayList<>(); // 开始时间 Calendar calStart = Calendar.getInstance(); calStart.add(Calendar.MONTH, -1); calStart.set(Calendar.DAY_OF_MONTH,1); calStart.set(Calendar.HOUR, 0); calStart.set(Calendar.MINUTE, 0); calStart.set(Calendar.SECOND, 0); calStart.set(Calendar.MILLISECOND, 0); list.add((calStart.getTimeInMillis() / 1000) - 43200);
// 结束时间 Calendar calEnd = Calendar.getInstance(); calEnd.set(calEnd.get(Calendar.YEAR),calEnd.get(Calendar.MONTH), calEnd.get(Calendar.DAY_OF_MONTH), 0, 0,0); calEnd.set(Calendar.DAY_OF_MONTH,calEnd.getActualMinimum(Calendar.DAY_OF_MONTH)); list.add((calEnd.getTimeInMillis() / 1000)-1); return list; }
/** * 返回今年开始和结束的时间戳 * * @author fzr * @return List */ public static List<Long> year() { List<Long> list = new ArrayList<>(); // 开始时间 Calendar calStart = Calendar.getInstance(); calStart.add(Calendar.YEAR, 0); calStart.add(Calendar.DATE, 0); calStart.add(Calendar.MONTH, 0); calStart.set(Calendar.DAY_OF_YEAR, 1); calStart.set(Calendar.HOUR_OF_DAY, 0); calStart.set(Calendar.MINUTE, 0); calStart.set(Calendar.SECOND, 0); calStart.set(Calendar.MILLISECOND, 0); list.add(calStart.getTimeInMillis() / 1000);
// 结束时间 Calendar calEnd = Calendar.getInstance(); int year = calEnd.get(Calendar.YEAR); calEnd.clear(); calEnd.set(Calendar.YEAR, year); calEnd.set(Calendar.HOUR_OF_DAY, 23); calEnd.set(Calendar.MINUTE, 59); calEnd.set(Calendar.SECOND, 59); calEnd.set(Calendar.MILLISECOND, 999); calEnd.roll(Calendar.DAY_OF_YEAR, -1); list.add(calEnd.getTimeInMillis() / 1000); return list; }
/** * 返回去年开始和结束的时间戳 * * @author fzr * @return List */ public static List<Long> lastYear() { List<Long> list = new ArrayList<>(); // 开始时间 Calendar calStart = Calendar.getInstance(); calStart.add(Calendar.YEAR, -1); calStart.set(Calendar.HOUR_OF_DAY, 0); calStart.set(Calendar.DAY_OF_YEAR, 1); calStart.set(Calendar.MINUTE, 0); calStart.set(Calendar.SECOND, 0); calStart.set(Calendar.MILLISECOND, 0); list.add(calStart.getTimeInMillis() / 1000);
// 结束时间 Calendar calEnd = Calendar.getInstance(); calEnd.add(Calendar.YEAR, -1); calEnd.set(Calendar.MONTH, calEnd.getActualMaximum(Calendar.MONTH)); calEnd.set(Calendar.DAY_OF_MONTH, calEnd.getActualMaximum(Calendar.DAY_OF_MONTH)); calEnd.set(Calendar.HOUR_OF_DAY, 23); calEnd.set(Calendar.MINUTE, 59); calEnd.set(Calendar.SECOND, 59); calEnd.set(Calendar.MILLISECOND, 999); list.add(calEnd.getTimeInMillis() / 1000); return list; }
/** * 获取几天前零点到现在/昨日结束的时间戳 * * @author fzr * @return List */ public static List<Long> dayToNow(int day) { List<Long> today = TimeUtils.today(); List<Long> list = new ArrayList<>(); list.add(today.get(0) - day * 86400L); list.add(today.get(0) -1); return list; }
/** * 返回几天前的时间戳 * * @author fzr * @param day (天) * @return Long */ public Long daysAgo(long day) { long currTime = System.currentTimeMillis() / 1000; return currTime - (day * 86400); }
/** * 返回几天后的时间戳 * * @author fzr * @param day (天) * @return Long */ public Long daysAfter(long day) { long currTime = System.currentTimeMillis() / 1000; return currTime + (day * 86400); }
/** * 返回月份第几天 * * @author fzr * @return int */ public static Integer monthDay(){ Date date = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(date); return cal.get(Calendar.DAY_OF_MONTH); }
/** * 获取几天前的日期列表 * * @author fzr * @param day 获取多少天 * @return [2022-03-29, 2022-03-30, 2022-03-31, 2022-04-01] */ public static List<String> daysAgoDate(Integer day) { long time = TimeUtils.today().get(0);
List<String> data = new ArrayList<>(); for (int i=0; i<day; i++) { if (i != 0) { time -= 86400; }
data.add(TimeUtils.timestampToDate(time, "yyyy-MM-dd")); }
Collections.reverse(data); return data; }
/** * 获取几天前的日期列表 * * @author fzr * @param day 获取多少天 * @return [1648483200, 1648569600, 1648656000, 1648742400] */ public static List<Long> daysAgoTime(Integer day) { long time = TimeUtils.today().get(0);
List<Long> data = new ArrayList<>(); for (int i=0; i<day; i++) { if (i != 0) { time -= 86400; }
data.add(time); }
Collections.reverse(data); return data; }
/** * 返回服务器启动时间 */ public static Date serverStartDate() { long time = ManagementFactory.getRuntimeMXBean().getStartTime(); return new Date(time); }
/** * 计算两个时间差 * * @author fzr * @param endDate 结束时间 * @param nowDate 开始时间 * @return String */ public static String datePoor(Date endDate, Date nowDate) { long nd = 1000 * 24 * 60 * 60; long nh = 1000 * 60 * 60; long nm = 1000 * 60; // long ns = 1000; // 获得两个时间的毫秒时间差异 long diff = endDate.getTime() - nowDate.getTime(); // 计算差多少天 long day = diff / nd; // 计算差多少小时 long hour = diff % nd / nh; // 计算差多少分钟 long min = diff % nd % nh / nm; // 计算差多少秒//输出结果 // long sec = diff % nd % nh % nm / ns; return day + "天" + hour + "小时" + min + "分钟"; }}获取系统信息
package com.sky.utils;
import com.sky.pono.server.*;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.lang.management.ManagementFactory;import java.text.SimpleDateFormat;import java.util.*;
/** * 服务器相关信息 */public class ServerUtils {
private static final int OSHI_WAIT_SECOND = 1000; private final Cpu cpu = new Cpu(); // CPU相关信息 private final Mem mem = new Mem(); // 內存相关信息 private final Jvm jvm = new Jvm(); // JVM相关信息 private final Sys sys = new Sys(); // 服务器相关信息 private final List<Disk> disk = new LinkedList<>(); // 磁盘相关信息
/** * 拷贝数据 */ public Map<String, Object> copyTo() { SystemInfo si = new SystemInfo(); HardwareAbstractionLayer hal = si.getHardware(); setCpuInfo(hal.getProcessor()); setMemInfo(hal.getMemory()); setSysInfo(); setJvmInfo(); setSysFiles(si.getOperatingSystem());
Map<String, Object> map = new LinkedHashMap<>(); map.put("cpu", this.cpu); map.put("mem", this.mem); map.put("sys", this.sys); map.put("disk", this.disk); map.put("jvm", this.jvm); return map; }
/** * 设置CPU信息 */ private void setCpuInfo(CentralProcessor processor) { 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 softer = 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 + softer + steal; cpu.setCpuNum(processor.getLogicalProcessorCount()); cpu.setTotal(ArithUtils.round(ArithUtils.mul(totalCpu, 100), 2)); cpu.setSys(ArithUtils.round(ArithUtils.mul(cSys / cpu.getTotal(), 100), 2)); cpu.setUsed(ArithUtils.round(ArithUtils.mul(user / cpu.getTotal(), 100), 2)); cpu.setWait(ArithUtils.round(ArithUtils.mul(ioWait / cpu.getTotal(), 100), 2)); cpu.setFree(ArithUtils.round(ArithUtils.mul(idle / cpu.getTotal(), 100), 2)); }
/** * 设置内存信息 */ private void setMemInfo(GlobalMemory memory) { int number = (1024 * 1024 * 1024); mem.setTotal(ArithUtils.div(memory.getTotal(), number, 2)); mem.setUsed(ArithUtils.div(memory.getTotal() - memory.getAvailable(), number, 2)); mem.setFree(ArithUtils.div(memory.getAvailable(), number, 2)); mem.setUsage(ArithUtils.mul(ArithUtils.div(mem.getUsed(), memory.getTotal(), 4), 100)); }
/** * 设置服务器信息 */ private void setSysInfo() { Properties props = System.getProperties(); sys.setComputerName(IpUtils.getHostName()); sys.setComputerIp(IpUtils.getHostIp()); sys.setOsName(props.getProperty("os.name")); sys.setOsArch(props.getProperty("os.arch")); sys.setUserDir(props.getProperty("user.dir")); }
/** * 设置Java虚拟机 */ private void setJvmInfo() { Properties props = System.getProperties(); jvm.setTotal(ArithUtils.div(Runtime.getRuntime().totalMemory(), (1024 * 1024), 2)); jvm.setMax(ArithUtils.div(Runtime.getRuntime().maxMemory(), (1024 * 1024), 2)); jvm.setFree(ArithUtils.div(Runtime.getRuntime().freeMemory(), (1024 * 1024), 2)); jvm.setUsage(ArithUtils.mul(ArithUtils.div(jvm.getTotal() - jvm.getFree(), jvm.getTotal(), 4), 100)); jvm.setVersion(props.getProperty("java.version")); jvm.setHome(props.getProperty("java.home")); jvm.setName(ManagementFactory.getRuntimeMXBean().getVmName()); jvm.setInputArgs(ManagementFactory.getRuntimeMXBean().getInputArguments().toString()); jvm.setRunTime(TimeUtils.datePoor(TimeUtils.nowDate(), TimeUtils.serverStartDate())); jvm.setStartTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(TimeUtils.serverStartDate())); }
/** * 设置磁盘信息 */ private void setSysFiles(OperatingSystem os) { FileSystem fileSystem = os.getFileSystem(); List<OSFileStore> fsArray = fileSystem.getFileStores(); for (OSFileStore fs : fsArray) { long free = fs.getUsableSpace(); long total = fs.getTotalSpace(); long used = total - free; Disk sysFile = new Disk(); 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(ArithUtils.mul(ArithUtils.div(used, total, 4), 100)); disk.add(sysFile); } }
/** * 字节转换 */ 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); } }}编写接口
@RestController@RequestMapping("/admin/monitor")public class MonitorServerController {
@GetMapping("/server") public Result<Map<String, Object>> info() { ServerUtils server = new ServerUtils(); return Result.success(server.copyTo()); }
}接口测试

前端代码
<template> <div class="system-environment" v-loading="loading"> <div class="cards-container"> <el-card class="card mb-4 card-margin-right" shadow="never"> <div>CPU</div> <div class="mt-4"> <div class="flex flex-wrap"> <div class="item mb-4"> <div class="text-4xl mb-3">{{ info.cpu.cpuNum }}</div> <div class="text-tx-regular">核心数</div> </div>
<div class="item mb-4"> <div class="text-4xl mb-3"> {{ info.cpu.used ? `${info.cpu.used}%` : '-' }} </div> <div class="text-tx-regular">用户使用率</div> </div>
<div class="item mb-4"> <div class="text-4xl mb-3"> {{ info.cpu.sys ? `${info.cpu.sys}%` : '-' }} </div> <div class="text-tx-regular">系统使用率</div> </div>
<div class="item mb-4"> <div class="text-4xl mb-3"> {{ info.cpu.free ? `${info.cpu.free}%` : '-' }} </div> <div class="text-tx-regular">当前空闲率</div> </div> </div> </div> </el-card> <el-card class="card mb-4" shadow="never"> <div>内存</div> <div class="mt-4"> <div class="flex flex-wrap"> <div class="item mb-4"> <div class="text-4xl mb-3">{{ info.mem.total }}</div> <div class="text-tx-regular">总内存</div> </div>
<div class="item mb-4"> <div class="text-4xl mb-3"> {{ info.mem.used ? `${info.mem.used}%` : '-' }} </div> <div class="text-tx-regular">已用内存</div> </div>
<div class="item mb-4"> <div class="text-4xl mb-3"> {{ info.mem.free ? `${info.mem.free}%` : '-' }} </div> <div class="text-tx-regular">剩余内存</div> </div>
<div class="item mb-4"> <div class="text-4xl mb-3"> {{ info.mem.usage ? `${info.mem.usage}%` : '-' }} </div> <div class="text-tx-regular">使用率</div> </div> </div> </div> </el-card> </div> <el-card class="card mb-4" shadow="never"> <div>服务器信息</div> <div class="mt-4"> <el-table :data="[info.sys]" size="large"> <el-table-column prop="computerName" label="服务器名称" min-width="150" /> <el-table-column prop="computerIp" label="服务器IP" min-width="120" /> <el-table-column prop="osName" label="操作系统" min-width="100" /> <el-table-column prop="osArch" label="系统架构" min-width="100" /> <el-table-column prop="userDir" label="项目路径" min-width="250" /> </el-table> </div> </el-card>
<el-card class="card mb-4" shadow="never"> <div>Java虚拟机信息</div> <div class="mt-4"> <el-table :data="[info.jvm]" size="large"> <el-table-column prop="name" label="Java名称" min-width="120" /> <el-table-column prop="startTime" label="启动时间" min-width="120" /> <el-table-column prop="home" label="安装路径" min-width="120" /> <el-table-column prop="inputArgs" label="运行参数" min-width="120" /> <el-table-column prop="version" label="Java版本" min-width="120" /> <el-table-column prop="runTime" label="运行时长" min-width="120" /> </el-table> </div> </el-card>
<el-card class="card mb-4" shadow="never"> <div>硬盘状态</div> <div class="mt-4"> <el-table :data="info.disk" size="large"> <el-table-column prop="dirName" label="盘符路径" min-width="100" /> <el-table-column prop="sysTypeName" label="文件系统" min-width="100" /> <el-table-column prop="typeName" label="盘符类型" min-width="100" /> <el-table-column prop="total" label="总大小" min-width="100" /> <el-table-column prop="free" label="可用大小" min-width="100" /> <el-table-column prop="used" label="已用大小" min-width="100" /> <el-table-column prop="usage" label="已用百分比" min-width="100"> <template #default="{ row }"> {{ row.usage }}%</template> </el-table-column> </el-table> </div> </el-card> </div></template>
<script lang="ts" setup name="environment">import { getSystemInfos } from '@/api/environment'import { ref } from 'vue'
const loading = ref(false)const info = ref({ cpu: {} as any, disk: [], jvm: {}, mem: {} as any, sys: {}})
const getSystemInfo = async () => { try { loading.value = true const data = await getSystemInfos() console.log(data.data.data) info.value = data.data.data
loading.value = false } catch (error) { loading.value = false }}
getSystemInfo()</script>
<style lang="scss" scoped>.system-environment { width: 100%;}
.cards-container { display: flex; flex-wrap: wrap; width: 100%;}
.card { border: none; flex: 1; margin-bottom: 16px; margin-right: 16px;
&:last-child { margin-right: 0; }}
.card-margin-right { margin-right: 16px;}
.item { flex: 1; width: 50%;}
.text-4xl { font-size: 2rem;}
.mb-3 { margin-bottom: 0.75rem;}
.text-tx-regular { font-size: 1rem;}
.mt-4 { margin-top: 1rem;}
@media (max-width: 1024px) { .card { width: 100%; margin-right: 0; }}</style>
评论