基于 Java 21 + Spring Boot 3.4 + React 18 的本机硬件监控系统,通过 OSHI 采集硬件指标,WebSocket 实时推送至前端仪表盘,支持历史数据持久化与趋势分析。
| 层 | 技术 |
|---|---|
| 后端 | Java 21, Spring Boot 3.4.4, Spring WebSocket, Spring Data JPA, OSHI 6.6.5 |
| 数据库 | H2 (嵌入式文件存储) |
| 缓存 | Caffeine |
| 前端 | React 18, TypeScript, Ant Design 5, ECharts 5, Zustand, Vite 6 |
| 构建 | Maven, Vite |
| 类别 | 指标 |
|---|---|
| CPU | 使用率、各核心负载、温度、频率、缓存 |
| 内存 | 使用率、已用/可用/总量、交换分区 |
| 磁盘 | 容量、读写速率、接口类型、S.M.A.R.T. 健康状态 |
| GPU | 型号、显存、温度 |
| 网络 | 上下行速率、接口详情、MAC/IP 脱敏 |
| 系统 | 主板、BIOS、OS 版本 |
| 页面 | 路由 | 功能说明 |
|---|---|---|
| 仪表盘总览 | / |
6 个核心指标卡片,异常告警高亮 |
| CPU 详情 | /cpu |
各核心柱状图 + 温度 + 频率 |
| 内存详情 | /memory |
环形图 + 交换分区 + 内存条表格 |
| 磁盘详情 | /disk |
容量饼图 + 读写速率 + S.M.A.R.T. |
| GPU 详情 | /gpu |
仪表盘 + 温度 + 显存 |
| 网络详情 | /network |
实时速率对比 + 接口详情 |
| 系统信息 | /system |
主板/BIOS/OS 静态信息 |
| 历史趋势 | /history |
时间范围 + 指标类型筛选 |
| 依赖 | 版本 | 说明 |
|---|---|---|
| JDK | 21+ | 后端运行环境 |
| Maven | 3.9+ | 后端构建工具 |
| Node.js | 18+ | 前端构建工具(仅开发/构建时需要) |
| 操作系统 | Windows / Linux / macOS | 支持主流桌面系统 |
Windows:
# 双击 start.bat 即可启动
start.bat
Linux / macOS:
chmod +x start.sh
./start.sh
启动后浏览器自动打开 http://127.0.0.1:9988。
java -Xms256m -Xmx512m -jar target/hw-monitor-1.0.0.jar
# 1. 构建前端
cd frontend
npm install
npm run build
# 2. 复制前端产物到后端 static 目录(Windows PowerShell)
cd ..
Copy-Item -Recurse .\frontend\dist .\src\main\resources\static -Force
# 2. 复制前端产物到后端 static 目录(Linux / macOS)
cp -r frontend/dist/* src/main/resources/static/
# 3. 打包
mvn clean package -DskipTests
# 4. 启动
java -jar target/hw-monitor-1.0.0.jar
# 终端 1:启动后端
mvn clean package -DskipTests
java -jar target/hw-monitor-1.0.0.jar
# 终端 2:启动前端开发服务器(支持热更新)
cd frontend
npm install
npm run dev
访问 http://127.0.0.1:3000,API 请求自动代理到 9988 端口。
| 命令 | 说明 |
|---|---|
java -jar target/hw-monitor-1.0.0.jar |
直接启动 |
java -Xms256m -Xmx512m -jar target/hw-monitor-1.0.0.jar |
指定内存限制启动 |
java -jar target/hw-monitor-1.0.0.jar --server.port=8080 |
指定端口启动 |
start.bat |
Windows 一键启动脚本 |
./start.sh |
Linux/macOS 一键启动脚本 |
Header 右侧提供 30 秒 / 60 秒 两档切换按钮,点击即时生效,无需重启。也可通过 API 修改:
curl -X PUT http://127.0.0.1:9988/api/v1/config/interval \
-H "Content-Type: application/json" \
-d '{"intervalSeconds": 60}'
仪表盘页面顶部提供 "实时刷新" 按钮,点击后立即触发一次全量采集并通过 WebSocket 推送最新数据,无需等待定时周期。
仪表盘卡片在以下情况下自动红色高亮边框:
| 指标 | 阈值 |
|---|---|
| CPU 使用率 | > 90% |
| 内存使用率 | > 85% |
| 磁盘使用率 | > 90% |
| 温度 | > 80°C |
| 方法 | 端点 | 说明 |
|---|---|---|
| GET | /api/v1/overview |
获取所有硬件概览数据 |
| GET | /api/v1/cpu |
获取 CPU 详情 |
| GET | /api/v1/memory |
获取内存详情 |
| GET | /api/v1/disk |
获取磁盘详情 |
| GET | /api/v1/gpu |
获取 GPU 详情 |
| GET | /api/v1/network |
获取网络详情 |
| GET | /api/v1/system |
获取系统信息 |
| GET | /api/v1/history |
获取历史数据(支持 ?start=&end=&category= 筛选) |
| POST | /api/v1/refresh |
触发即时采集 |
| GET | /api/v1/config/interval |
获取当前采集间隔 |
| PUT | /api/v1/config/interval |
修改采集间隔(body: {"intervalSeconds": 30}) |
| GET | /api/v1/health |
健康检查 |
ws://127.0.0.1:9988/ws/metrics消息格式:
{
"type": "metrics",
"timestamp": 1700000000000,
"data": {
"cpu": { "usagePercent": 23.0, "temperature": 45.0 },
"memory": { "usagePercent": 74.2, "usedBytes": 25125584896 },
"disk": { "partitions": [{"usagePercent": 21.6, "usedBytes": 214255665152}] },
"gpu": { "name": "Intel(R) Arc(TM) 130T GPU" },
"network": { "interfaces": [] },
"system": { "osName": "Windows 11" }
}
}
所有可配置参数位于 src/main/resources/application.yml:
server:
port: 9988 # 监听端口
address: 127.0.0.1 # 仅监听本地,实现网络隔离
spring:
threads:
virtual:
enabled: true # 启用虚拟线程
hwmonitor:
collect-interval-seconds: 30 # 采集间隔(30/60)
history:
retention-days: 7 # 历史数据保留天数
alert:
cpu-threshold: 90 # CPU 告警阈值 (%)
memory-threshold: 85 # 内存告警阈值 (%)
disk-threshold: 90 # 磁盘告警阈值 (%)
temp-threshold: 80 # 温度告警阈值 (°C)
security:
allowed-origins: http://localhost:9988
enable-token: false # Token 认证(默认关闭)
read-only: true # 只读模式
| 措施 | 说明 |
|---|---|
| 网络隔离 | 服务仅监听 127.0.0.1,不对外暴露 |
| 只读原则 | 所有数据采集 API 均为 GET 请求 |
| 数据脱敏 | MAC 地址掩码、公网 IP 仅显示前两段、磁盘序列号脱敏 |
| 日志安全 | 不输出敏感硬件信息 |
| H2 Console | 已禁用 |
./data/hwmonitor.mv.db./data 目录后重启即可使用 WinSW 将 jar 注册为 Windows 服务:
<!-- hw-monitor-service.xml -->
<service>
<id>hw-monitor</id>
<name>Hardware Monitor</name>
<description>本机硬件监控服务</description>
<executable>java</executable>
<arguments>-jar hw-monitor-1.0.0.jar</arguments>
<workingdirectory>D:\ideaFactory\hw-monitor</workingdirectory>
<log mode="roll-by-size">
<sizeThreshold>10240</sizeThreshold>
<keepFiles>8</keepFiles>
</log>
</service>
# 安装服务
hw-monitor-service.exe install
# 启动服务
hw-monitor-service.exe start
# /etc/systemd/system/hw-monitor.service
[Unit]
Description=Hardware Monitor Service
After=network.target
[Service]
Type=simple
User=monitor
WorkingDirectory=/opt/hw-monitor
ExecStart=/usr/bin/java -jar /opt/hw-monitor/hw-monitor-1.0.0.jar
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable hw-monitor
sudo systemctl start hw-monitor
hw-monitor/
├── start.bat # Windows 一键启动脚本
├── start.sh # Linux/macOS 一键启动脚本
├── pom.xml # Maven 配置
├── README.md # 项目文档
├── .gitignore # Git 忽略规则
├── src/main/java/com/hwmonitor/
│ ├── HwMonitorApplication.java # Spring Boot 启动类
│ ├── collector/ # 硬件采集器(6个)
│ │ ├── CpuCollector.java # CPU 采集
│ │ ├── MemoryCollector.java # 内存采集
│ │ ├── DiskCollector.java # 磁盘采集
│ │ ├── GpuCollector.java # GPU 采集
│ │ ├── NetworkCollector.java # 网络采集(含 IP 脱敏)
│ │ └── SystemCollector.java # 系统信息采集
│ ├── config/ # 配置类
│ │ ├── BrowserLauncher.java # 启动自动打开浏览器
│ │ ├── CacheConfig.java # Caffeine 缓存
│ │ ├── MonitorConfig.java # 采集频率动态配置
│ │ └── WebSocketConfig.java # WebSocket 配置
│ ├── controller/ # 控制器
│ │ ├── MetricsController.java # REST API + 刷新端点
│ │ ├── ConfigController.java # 配置管理 API
│ │ ├── HistoryController.java # 历史数据 API
│ │ └── MetricsWebSocketHandler.java # WebSocket 推送
│ ├── model/ # 数据模型
│ │ ├── dto/ # 7 个数据传输对象
│ │ └── entity/ # 1 个 JPA 实体
│ ├── repository/ # JPA Repository
│ ├── scheduler/ # 定时调度(动态 TaskScheduler)
│ └── service/ # 业务服务
├── src/main/resources/
│ ├── application.yml # 全局配置
│ └── static/ # 前端打包产物
└── frontend/ # 前端源码
├── package.json # 前端依赖
├── vite.config.ts # Vite 配置
└── src/
├── App.tsx # 根组件 + 路由
├── main.tsx # 入口
├── types.ts # TypeScript 类型
├── components/ # 页面组件(8个)
│ ├── Dashboard/ # 仪表盘总览
│ ├── CpuDetail/ # CPU 详情
│ ├── MemoryDetail/ # 内存详情
│ ├── DiskDetail/ # 磁盘详情
│ ├── GpuDetail/ # GPU 详情
│ ├── NetworkDetail/ # 网络详情
│ ├── SystemInfo/ # 系统信息
│ ├── History/ # 历史趋势
│ └── Layout/ # 布局(含频率切换 + 连接状态)
├── services/api.ts # API 封装
└── store/metricsStore.ts # Zustand 状态管理
Q: 启动后浏览器显示"连接断开"? A: 等待 3-5 秒,WebSocket 会自动重连。若持续断开,检查后端是否正常启动在 9988 端口。
Q: 磁盘使用率显示 0%? A: 以管理员身份运行可解决部分权限问题。本项目已修复 Windows 下分区匹配逻辑,正常情况应显示非零值。
Q: GPU 信息显示 "--"? A: OSHI 在某些平台无法获取 GPU 使用率,型号和显存信息正常即可。
Q: 如何修改采集频率?
A: 方式一:点击前端 Header 右侧 30秒/60秒 按钮即时切换;方式二:通过 API 修改;方式三:修改 application.yml 后重启。
Q: 历史数据占用空间大吗? A: 按默认 30 秒采集间隔,每条记录约 100 字节,7 天约产生 2MB 数据,可忽略不计。
Q: 如何卸载服务?
A: Windows: hw-monitor-service.exe uninstall;Linux: sudo systemctl stop hw-monitor && sudo systemctl disable hw-monitor。