基于Spring Boot的图书管理系统毕设实战指南!从需求到测试全流程详解✨
谁懂啊!去年做图书管理系统毕设时,光借阅归还和图书库存的关联就卡了4天——一开始没处理"借阅超期"逻辑,用户借书超期后系统没提醒,导师演示时直接发现了这个业务漏洞😫 经过反复修改优化,终于总结出了这套图书管理系统毕设实战经验,今天就把全流程细节分享给大家!
一、需求分析:抓住图书管理核心业务
刚开始我想做一个"万能图书馆系统",包含了读者管理、图书采购、财务统计等模块,结果导师说"重点不突出,核心借阅流程不清晰"。后来明白,图书管理系统要围绕图书-借阅-归还这个核心业务流程展开。
1. 核心用户角色与功能
系统主要面向两类用户,功能定位要精准:
-
管理员端(系统管理核心):
- 用户信息管理:维护读者信息、办理借阅证、重置密码
- 图书信息管理:录入图书信息、设置图书分类、管理图书库存
- 借阅信息管理:处理借阅申请、管理归还记录、计算超期费用
- 系统基础管理:管理图书分类、出版社、书架位置等基础数据
- 公告论坛管理:发布图书馆公告、管理读者交流论坛
-
用户端(读者服务核心):
- 图书查询:按条件检索图书、查看图书详情
- 借阅管理:查看个人借阅记录、续借图书
- 个人信息:维护个人资料、修改登录密码
- 论坛交流:在图书馆论坛发帖交流
2. 需求分析实战技巧
- 实地调研很重要:我去学校图书馆观察了真实的借阅流程,发现他们最需要"借阅超期提醒"功能,于是重点设计了借阅状态管理
- 绘制业务流程图:用DrawIO画出"读者查询→借阅图书→归还图书"的完整流程,答辩时清晰展示业务逻辑
- 明确业务规则:如"同一读者最多借5本书""借阅期限30天""超期每天罚款0.1元"等约束条件
3. 可行性分析要点
- 技术可行性:Spring Boot+MySQL技术成熟,SSM框架资料丰富
- 经济可行性:全部使用开源工具,零开发成本
- 操作可行性:界面设计参考主流图书馆系统,读者上手快
二、技术选型:稳定可靠的开发架构
曾经尝试用微服务架构,结果服务调用配置卡了2天,最终选择单体架构,开发效率大大提升!
1. 技术栈选择理由
| 技术组件 | 选择理由 | 避坑提醒 |
|---|---|---|
| Spring Boot 2.7 | 配置简单,快速开发 | 不要用3.x,兼容性问题多 |
| MySQL 8.0 | 数据关系明确,适合图书管理系统 | 记得配置时区和字符集 |
| SSM框架 | 技术成熟,资料丰富 | 注意MyBatis配置 |
| Bootstrap 3.x | 兼容性好,开发快速 | 不要用4.x,样式问题多 |
2. 开发环境搭建
# 创建Spring Boot项目
使用Spring Initializr
选择Web、MySQL、MyBatis依赖
# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/library_db?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
三、数据库设计:图书业务数据建模
最初设计时把图书信息和借阅记录放在同一张表,导致数据冗余严重。重新设计后按业务模块分表,系统性能大幅提升。
1. 核心数据表设计
借阅信息表(tushujieyue)
CREATE TABLE `tushujieyue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tushu_id` int(11) DEFAULT NULL COMMENT '图书ID',
`yonghu_id` int(11) DEFAULT NULL COMMENT '用户ID',
`tushujieyue_shijian` int(11) DEFAULT '30' COMMENT '借阅时间(天)',
`tushujieyue_types` int(11) DEFAULT '0' COMMENT '借阅状态:0借阅中/1已归还',
`jieyue_time` datetime DEFAULT NULL COMMENT '借阅时间',
`guihuan_time` datetime DEFAULT NULL COMMENT '应归还时间',
`shijiguihuan_time` datetime DEFAULT NULL COMMENT '实际归还时间',
`chaogi_fine` decimal(10,2) DEFAULT '0.00' COMMENT '超期罚款',
`insert_time` datetime DEFAULT NULL COMMENT '记录时间',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_tushu` (`tushu_id`),
KEY `fk_yonghu` (`yonghu_id`),
KEY `idx_guihuan` (`guihuan_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='借阅信息表';
图书信息表(tushu)
CREATE TABLE `tushu` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tushu_uuid_number` varchar(200) DEFAULT NULL COMMENT '图书编号',
`tushu_name` varchar(200) DEFAULT NULL COMMENT '图书标题',
`tushu_types` int(11) DEFAULT NULL COMMENT '图书类型',
`tushu_photo` varchar(200) DEFAULT NULL COMMENT '图书封面',
`tushu_zuozhe` varchar(100) DEFAULT NULL COMMENT '图书作者',
`chubanshe_types` int(11) DEFAULT NULL COMMENT '图书出版社',
`shujia_types` int(11) DEFAULT NULL COMMENT '所在书架',
`tushu_number` int(11) DEFAULT '1' COMMENT '图书数量',
`tushu_kucun` int(11) DEFAULT '1' COMMENT '图书库存',
`tushu_content` text COMMENT '图书详情',
`insert_time` datetime DEFAULT NULL COMMENT '发布时间',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tushu_number` (`tushu_uuid_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='图书信息表';
2. 表关系设计要点
- 状态字段设计:借阅状态(借阅中/已归还)、图书状态(在馆/借出)
- 库存管理:借阅时扣减库存,归还时恢复库存
- 超期计算:自动计算应归还时间和超期罚款
四、核心功能实现与代码详解
1. 借阅管理模块(核心业务功能)
Service层实现:
@Service
public class TushujieyueServiceImpl implements TushujieyueService {
@Autowired
private TushujieyueMapper tushujieyueMapper;
@Autowired
private TushuMapper tushuMapper;
@Override
@Transactional
public void jieyueTushu(Integer tushuId, Integer yonghuId) {
// 1. 检查图书库存
TushuEntity tushu = tushuMapper.selectById(tushuId);
if (tushu.getTushuKucun() <= 0) {
throw new RuntimeException("该图书库存不足,无法借阅");
}
// 2. 检查用户借阅数量
Integer jieyueCount = tushujieyueMapper.selectCount(
new EntityWrapper<TushujieyueEntity>()
.eq("yonghu_id", yonghuId)
.eq("tushujieyue_types", 0) // 借阅中的图书
);
if (jieyueCount >= 5) {
throw new RuntimeException("您已借阅5本书,达到最大借阅数量");
}
// 3. 检查是否重复借阅同一本书
Integer chongfuCount = tushujieyueMapper.selectCount(
new EntityWrapper<TushujieyueEntity>()
.eq("yonghu_id", yonghuId)
.eq("tushu_id", tushuId)
.eq("tushujieyue_types", 0)
);
if (chongfuCount > 0) {
throw new RuntimeException("您已借阅该图书,请勿重复借阅");
}
// 4. 创建借阅记录
TushujieyueEntity jieyue = new TushujieyueEntity();
jieyue.setTushuId(tushuId);
jieyue.setYonghuId(yonghuId);
jieyue.setTushujieyueTypes(0); // 借阅中
jieyue.setJieyueTime(new Date());
// 计算应归还时间(30天后)
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DAY_OF_MONTH, 30);
jieyue.setGuihuanTime(calendar.getTime());
tushujieyueMapper.insert(jieyue);
// 5. 扣减图书库存
tushu.setTushuKucun(tushu.getTushuKucun() - 1);
tushuMapper.updateById(tushu);
}
@Override
@Transactional
public void guihuanTushu(Integer jieyueId) {
TushujieyueEntity jieyue = tushujieyueMapper.selectById(jieyueId);
if (jieyue == null) {
throw new RuntimeException("借阅记录不存在");
}
// 更新借阅状态
jieyue.setTushujieyueTypes(1); // 已归还
jieyue.setShijiguihuanTime(new Date());
// 计算超期罚款
Date now = new Date();
if (now.after(jieyue.getGuihuanTime())) {
long days = (now.getTime() - jieyue.getGuihuanTime().getTime()) / (1000 * 60 * 60 * 24);
BigDecimal fine = new BigDecimal(days).multiply(new BigDecimal("0.1"));
jieyue.setChaogiFine(fine);
}
tushujieyueMapper.updateById(jieyue);
// 恢复图书库存
TushuEntity tushu = tushuMapper.selectById(jieyue.getTushuId());
tushu.setTushuKucun(tushu.getTushuKucun() + 1);
tushuMapper.updateById(tushu);
}
}
Controller层:
@Controller
@RequestMapping("/user/jieyue")
public class UserJieyueController {
@Autowired
private TushujieyueService tushujieyueService;
@PostMapping("/jieyue")
public String jieyueTushu(Integer tushuId, HttpServletRequest request) {
try {
// 设置当前登录用户
YonghuEntity user = (YonghuEntity) request.getSession().getAttribute("user");
tushujieyueService.jieyueTushu(tushuId, user.getId());
request.setAttribute("msg", "借阅成功");
} catch (Exception e) {
request.setAttribute("msg", "借阅失败:" + e.getMessage());
}
return "redirect:/user/tushu/list";
}
@PostMapping("/guihuan")
public String guihuanTushu(Integer jieyueId, HttpServletRequest request) {
try {
tushujieyueService.guihuanTushu(jieyueId);
request.setAttribute("msg", "归还成功");
} catch (Exception e) {
request.setAttribute("msg", "归还失败:" + e.getMessage());
}
return "redirect:/user/jieyue/list";
}
}
2. 图书查询模块(用户端核心功能)
Service层实现:
@Service
public class TushuServiceImpl implements TushuService {
@Autowired
private TushuMapper tushuMapper;
@Override
public PageUtils queryPage(Map<String, Object> params) {
Page<TushuEntity> page = new Page<>(
Integer.parseInt(params.get("page").toString()),
Integer.parseInt(params.get("limit").toString())
);
EntityWrapper<TushuEntity> ew = new EntityWrapper<>();
// 图书名称模糊查询
if (params.get("tushuName") != null) {
ew.like("tushu_name", params.get("tushuName").toString());
}
// 图书类型筛选
if (params.get("tushuTypes") != null) {
ew.eq("tushu_types", params.get("tushuTypes"));
}
// 作者模糊查询
if (params.get("zuozhe") != null) {
ew.like("tushu_zuozhe", params.get("zuozhe").toString());
}
// 只显示有库存的图书
ew.gt("tushu_kucun", 0);
IPage<TushuEntity> result = tushuMapper.selectPage(page, ew);
return new PageUtils(result);
}
@Override
public List<TushuEntity> getRecommendTushu() {
// 获取推荐图书(点击量高的图书)
return tushuMapper.selectList(
new EntityWrapper<TushuEntity>()
.gt("tushu_kucun", 0)
.orderBy("tushu_clicknum", false)
.last("limit 8")
);
}
}
3. 借阅统计模块(管理员功能)
Service层实现:
@Service
public class TongjiServiceImpl implements TongjiService {
@Autowired
private TushujieyueMapper tushujieyueMapper;
@Override
public Map<String, Object> getJieyueTongji() {
Map<String, Object> result = new HashMap<>();
// 今日借阅数量
Integer todayJieyue = tushujieyueMapper.selectCount(
new EntityWrapper<TushujieyueEntity>()
.eq("DATE(insert_time)", new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
);
// 当前借阅中数量
Integer jieyuezhong = tushujieyueMapper.selectCount(
new EntityWrapper<TushujieyueEntity>()
.eq("tushujieyue_types", 0)
);
// 超期未还数量
Integer chaogiWeihuan = tushujieyueMapper.selectCount(
new EntityWrapper<TushujieyueEntity>()
.eq("tushujieyue_types", 0)
.lt("guihuan_time", new Date())
);
result.put("todayJieyue", todayJieyue);
result.put("jieyuezhong", jieyuezhong);
result.put("chaogiWeihuan", chaogiWeihuan);
return result;
}
}
五、系统测试:确保借阅流程可靠
曾经以为功能实现就完成了,结果测试时发现同一用户能无限借书,紧急加了借阅数量限制。
1. 功能测试用例
借阅流程测试:
| 测试场景 | 操作步骤 | 预期结果 |
|---|---|---|
| 图书库存为0 | 用户借阅库存为0的图书 | 提示"库存不足" |
| 借阅数量超限 | 用户借阅第6本书 | 提示"达到最大借阅数量" |
| 重复借阅 | 用户借阅已借阅的图书 | 提示"请勿重复借阅" |
| 正常借阅 | 用户借阅有库存的图书 | 提示"借阅成功",库存减1 |
归还流程测试:
| 测试场景 | 操作步骤 | 预期结果 |
|---|---|---|
| 超期归还 | 用户超期归还图书 | 计算超期罚款,库存恢复 |
| 按时归还 | 用户按时归还图书 | 提示"归还成功",库存恢复 |
2. 数据一致性测试
- 借阅与库存:借阅时库存减少,归还时库存恢复
- 超期计算:自动计算应归还时间和超期天数
- 状态同步:图书状态与借阅状态实时同步
六、部署与演示准备
1. 数据库初始化脚本
-- 插入测试数据
INSERT INTO `tushu` VALUES
(1, 'TS001', 'Java编程思想', 1, '/images/tushu1.jpg', 'Bruce Eckel', 1, 1, 5, 5, 'Java经典图书...', NOW(), NOW()),
(2, 'TS002', 'Spring Boot实战', 1, '/images/tushu2.jpg', 'Craig Walls', 1, 1, 3, 3, 'Spring Boot实战指南...', NOW(), NOW());
INSERT INTO `yonghu` VALUES
(1, 'user1', '123456', '张三', '/images/user1.jpg', 1, '13800138000', '110101199001011234', 'user1@qq.com', 0, NOW());
2. 演示流程设计
按照真实借阅流程演示:
- 用户注册登录→查询图书→借阅图书
- 管理员登录→管理图书信息→查看借阅统计
- 用户归还图书→系统计算超期费用
3. 答辩重点准备
- 业务逻辑亮点:借阅数量控制、超期自动计算
- 技术实现亮点:Spring事务管理、数据一致性保障
- 系统特色:完整的借阅归还流程、智能统计功能
结语
基于Spring Boot的图书管理系统毕设成功的关键在于:抓住借阅业务核心,处理好库存同步,保证数据一致性。这套系统虽然业务逻辑相对复杂,但一旦掌握,无论是完成度还是技术含量都能得到导师认可。
记住:借阅库存同步、超期自动计算、借阅数量控制是三大得分点!需要完整源码、数据库脚本、部署文档的同学可以在评论区留言。
点赞收藏这篇指南,你的图书管理系统毕设一定能顺利通过! 📚✨