1. 项目概述
这个基于SpringBoot 1.16的企业物资库存进销存管理系统是我去年为一个中型制造企业开发的实战项目。当时客户面临的主要问题是手工管理导致库存数据不准确、采购和销售流程脱节、报表统计滞后等问题。通过这个系统,我们成功将企业的库存准确率从78%提升到99.5%,采购周期缩短了40%,现在我想把这个项目的完整开发过程和经验分享给大家。
系统采用B/S架构,前端使用LayUI+Bootstrap+JSP,后端基于SpringBoot+MyBatis,数据库选用MySQL 5.7。整个系统包含5大核心模块:基础数据管理、采购管理、库存管理、销售管理和报表统计,支持多角色权限控制,可以满足制造业、零售业等企业的日常物资管理需求。
2. 技术选型与架构设计
2.1 技术栈选择考量
选择SpringBoot 1.16而不是最新版本有几个实际考量:
- 客户生产环境JDK版本限制在1.8
- 项目需要与一些老系统对接,新版本兼容性风险较大
- 1.16版本社区支持完善,遇到问题容易找到解决方案
数据库选型时我们对比了MySQL和PostgreSQL:
- MySQL优势:运维简单、社区资源丰富、与SpringBoot集成成熟
- PostgreSQL优势:复杂查询性能更好、支持JSON类型
最终选择MySQL是因为客户IT团队对MySQL更熟悉
前端技术组合选择LayUI+Bootstrap主要基于:
- 开发效率高,适合快速交付的项目
- 组件丰富,能满足管理系统各种界面需求
- 响应式设计适配不同设备
2.2 系统架构设计
系统采用典型的三层架构:
code复制表现层:JSP + LayUI + Bootstrap
业务逻辑层:SpringBoot + Spring MVC
数据访问层:MyBatis + MySQL
关键架构决策:
- 引入Redis缓存高频访问的基础数据(如物资分类、供应商信息)
- 使用JWT替代Session做认证,便于后期扩展微服务
- 采用前后端轻度分离模式(JSP渲染而非纯API)
提示:在中小型管理系统中,这种轻度分离的架构比完全前后端分离更合适,开发效率更高,也更容易找到开发人员。
3. 核心功能模块实现
3.1 基础数据管理模块
这个模块是整个系统的基础,包含以下几个关键实体:
- 物资分类(多级树形结构)
- 物资信息(关联分类、供应商)
- 供应商管理
- 客户管理
- 仓库管理
物资分类表设计采用了闭包表模式,这是处理树形结构的经典方案:
sql复制CREATE TABLE `material_category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`code` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `category_closure` (
`ancestor` int(11) NOT NULL,
`descendant` int(11) NOT NULL,
`depth` int(11) NOT NULL,
PRIMARY KEY (`ancestor`,`descendant`)
);
3.2 采购管理模块
采购流程实现要点:
- 采购计划 → 采购订单 → 到货验收 → 入库
- 每个环节都有状态控制和操作日志
- 支持采购订单模板和批量导入
采购订单状态机设计:
java复制public enum PurchaseOrderStatus {
DRAFT("草稿"),
APPROVING("审批中"),
APPROVED("已审批"),
PART_RECEIVED("部分到货"),
COMPLETED("已完成"),
CANCELLED("已取消");
// 状态流转校验逻辑
public static boolean canTransfer(PurchaseOrderStatus from, PurchaseOrderStatus to) {
// 具体实现省略...
}
}
3.3 库存管理模块
核心功能包括:
- 实时库存查询(支持多维度筛选)
- 库存预警(低于安全库存自动提醒)
- 库存调拨(跨仓库转移)
- 库存盘点(周期性和临时盘点)
库存变更采用"事务+日志"双重记录:
java复制@Transactional
public void updateStock(StockChangeDTO dto) {
// 1. 更新实时库存
stockMapper.updateQuantity(dto);
// 2. 记录库存变更日志
StockLog log = new StockLog();
// 设置日志属性...
stockLogMapper.insert(log);
// 3. 检查是否需要触发预警
checkStockWarning(dto.getMaterialId());
}
4. 系统安全与性能优化
4.1 安全控制实现
系统安全主要从三个层面保障:
- 认证:JWT + 密码加盐
- 授权:RBAC模型 + 数据权限过滤
- 审计:关键操作日志记录
密码存储方案:
java复制public String encryptPassword(String rawPassword) {
// 生成随机盐值
String salt = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
// 加盐哈希
String hashed = DigestUtils.md5DigestAsHex((salt + rawPassword).getBytes());
// 存储格式:算法版本$盐值$哈希值
return "v1$" + salt + "$" + hashed;
}
4.2 性能优化实践
-
缓存策略:
- 基础数据:Redis缓存,过期时间2小时
- 报表数据:定时预生成,缓存24小时
-
SQL优化:
- 所有查询必须带索引
- 大数据量报表使用单独的分析库
-
前端优化:
- 静态资源CDN加速
- 表格数据分页加载
- 复杂页面按需渲染
5. 开发经验与避坑指南
5.1 开发环境搭建
推荐使用以下工具组合:
- IDE:IntelliJ IDEA Ultimate(学生可免费申请)
- 数据库工具:DBeaver(免费且功能强大)
- API测试:Postman
- 版本控制:Git + GitLab
Maven配置关键依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.22.RELEASE</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.3</version>
</dependency>
5.2 常见问题解决
-
日期时间处理:
- 数据库统一使用UTC时间
- 前端展示时转换为本地时区
- 使用Java 8的LocalDateTime替代Date
-
事务失效场景:
- 方法必须是public
- 不能自调用
- 异常要抛出不要捕获
-
MyBatis踩坑:
- 实体类属性名与数据库字段严格对应
- 批量操作使用BatchExecutor
- 复杂查询考虑使用注解+XML混合模式
6. 项目部署与运维
6.1 生产环境部署
推荐部署方案:
- 应用服务器:Tomcat 8.5
- 数据库:MySQL 5.7主从
- 缓存:Redis哨兵模式
- 监控:Prometheus + Grafana
关键部署配置:
properties复制# application-prod.properties
spring.datasource.druid.initial-size=5
spring.datasource.druid.max-active=20
spring.datasource.druid.validation-query=SELECT 1
spring.redis.timeout=3000
spring.redis.jedis.pool.max-active=50
6.2 系统监控与维护
必须监控的关键指标:
-
应用层:
- JVM内存使用率
- 线程池状态
- API响应时间
-
数据库层:
- 连接池使用率
- 慢查询数量
- 锁等待时间
-
业务层:
- 库存同步延迟
- 订单处理积压
- 预警消息堆积
我在项目上线后建立了一套完整的监控看板,通过Grafana可视化这些指标,当任何指标异常时自动触发告警。这套监控体系帮助我们提前发现了多次潜在问题,避免了生产事故。