1. 项目概述
这个设备管理系统是我去年为一家制造业客户开发的内部管理工具,主要解决他们生产设备台账混乱、维保记录缺失的问题。系统采用前后端分离架构,后端基于SpringBoot+MyBatis实现业务逻辑,前端使用Vue.js构建交互界面,数据库选用MySQL 8.0。整个开发周期约3个月,上线后设备故障响应时间缩短了60%,维保成本降低35%。
关键数据:系统日均处理2000+设备状态更新,支持50人并发操作,查询响应时间<500ms
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 后端技术栈选型
选择SpringBoot 2.7作为基础框架主要考虑:
- 内嵌Tomcat简化部署
- 自动配置减少XML配置
- 丰富的Starter依赖(特别是MyBatis和MySQL驱动)
- 与MyBatis的天然集成优势
数据库连接池使用HikariCP而非Druid,实测在200连接数下性能提升15%。MyBatis配置了二级缓存,对设备基础信息这类低频变更数据特别有效。
2.2 前端架构方案
Vue 3组合式API相比选项式API更适合我们的场景:
- 设备状态看板需要大量响应式数据
- 自定义指令简化权限按钮控制
- Pinia状态管理替代Vuex,代码量减少30%
- 采用Element Plus组件库加速开发
3. 核心功能实现
3.1 设备全生命周期管理
java复制// 设备状态变更示例
@Transactional
public void updateDeviceStatus(Long deviceId, Status newStatus) {
Device device = deviceMapper.selectById(deviceId);
if(device == null) throw new BizException("设备不存在");
device.setStatus(newStatus);
device.setUpdateTime(LocalDateTime.now());
deviceMapper.updateById(device);
// 记录状态变更日志
DeviceLog log = new DeviceLog(deviceId, "状态变更",
device.getStatus() + "->" + newStatus);
deviceLogMapper.insert(log);
}
3.2 动态权限控制
前端路由配置示例:
javascript复制const routes = [
{
path: '/device',
component: Layout,
meta: { requiresAuth: true, roles: ['admin','maintainer'] },
children: [
{
path: 'add',
component: () => import('@/views/device/Add'),
meta: { title: '新增设备', icon: 'plus' }
}
]
}
]
4. 数据库设计要点
设备主表关键字段:
sql复制CREATE TABLE `device` (
`id` bigint NOT NULL AUTO_INCREMENT,
`code` varchar(32) NOT NULL COMMENT '设备编码',
`name` varchar(100) NOT NULL,
`type_id` int NOT NULL COMMENT '设备类型',
`status` enum('NORMAL','MAINTAINING','SCRAPPED') DEFAULT 'NORMAL',
`purchase_date` date NOT NULL,
`warranty_period` int COMMENT '保修月数',
`location_id` int NOT NULL,
`qr_code` varchar(255) COMMENT '二维码路径',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
5. 性能优化实践
5.1 查询优化方案
针对设备列表页的典型慢查询:
xml复制<select id="selectDeviceList" resultMap="DeviceResult">
SELECT d.*, t.name as type_name, l.name as location_name
FROM device d
LEFT JOIN device_type t ON d.type_id = t.id
LEFT JOIN location l ON d.location_id = l.id
<where>
<if test="status != null"> AND d.status = #{status} </if>
<if test="typeId != null"> AND d.type_id = #{typeId} </if>
<if test="keyword != null">
AND (d.name LIKE CONCAT('%',#{keyword},'%')
OR d.code LIKE CONCAT('%',#{keyword},'%'))
</if>
</where>
ORDER BY d.create_time DESC
</select>
优化措施:
- 为status/type_id字段添加索引
- 使用覆盖索引优化COUNT查询
- 大文本字段(如remark)单独存储
5.2 缓存策略设计
采用多级缓存架构:
- 基础数据:Redis缓存 + MyBatis二级缓存
- 实时状态:Caffeine本地缓存(有效期30s)
- 统计报表:定时任务预生成
6. 典型问题解决方案
6.1 批量导入性能问题
初始方案直接循环insert导致1000条数据导入需要25秒。改进方案:
java复制// 使用MyBatis批量插入
@Transactional
public void batchImport(List<Device> devices) {
SqlSession session = sqlSessionTemplate.getSqlSessionFactory()
.openSession(ExecutorType.BATCH);
try {
DeviceMapper mapper = session.getMapper(DeviceMapper.class);
for (Device device : devices) {
mapper.insert(device);
}
session.commit();
} finally {
session.close();
}
}
优化后1000条数据仅需3.2秒。
6.2 二维码生成瓶颈
使用Google ZXing库同步生成二维码时,100张图片生成耗时8秒。改用异步线程池后:
java复制@Async("taskExecutor")
public CompletableFuture<String> generateQrCodeAsync(String content) {
String path = qrCodeService.generate(content);
return CompletableFuture.completedFuture(path);
}
配合ThreadPoolTaskExecutor配置,吞吐量提升5倍。
7. 部署注意事项
-
MySQL配置建议:
ini复制[mysqld] innodb_buffer_pool_size = 2G max_connections = 300 thread_cache_size = 32 -
JVM参数优化:
bash复制
-Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -
Nginx前端配置关键点:
nginx复制location /api { proxy_pass http://backend; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 75s; proxy_read_timeout 600s; }
8. 扩展功能建议
- 设备预测性维护:接入振动传感器数据,使用Spring Boot集成Python ML模型
- 移动端适配:基于Uniapp开发微信小程序版本
- 语音控制:集成百度语音识别实现语音查询
- 数字孪生:Three.js实现3D设备模型展示
踩坑提醒:MyBatis的
<和>符号在XML中必须转义为<和>,否则会导致解析错误。建议使用CDATA块包裹复杂SQL。
