1. 项目背景与核心需求
去年帮学弟调试他的毕业设计时,发现很多计算机专业同学在选题阶段就陷入了误区——要么选择过于陈旧的技术栈,要么盲目追求前沿技术导致无法落地。这个基于SpringBoot的展览馆综合管理系统恰好是个"甜区"选题:既有足够的业务复杂度来展示专业能力,又不会因技术选型问题导致项目烂尾。
这类系统本质上要解决展览馆的数字化管理痛点:传统的纸质登记、人工排期、线下售票等方式效率低下,且难以应对突发情况(比如2020年后普遍需要的预约限流功能)。我们设计的系统需要覆盖以下核心模块:
- 展品管理:解决文物/展品信息电子化建档难题,支持多维检索(按年代、材质、出土地等)
- 票务系统:实现线上购票、分时段预约、二维码核销的闭环
- 客流监控:通过闸机数据实时计算馆内人数,超限自动预警
- 活动管理:临时展览的场地预约、设备调配、人员排班一体化
提示:毕业设计切忌贪大求全,建议选择2-3个核心模块深度实现,其余功能用Mock数据演示。比如优先做实票务系统和展品管理,客流监控用定时器模拟数据上报。
2. 技术选型与架构设计
2.1 为什么选择SpringBoot
对比传统SSM框架,SpringBoot的自动配置特性让毕业生能避开这些坑:
- 不用手动配置Tomcat插件版本与JDK的兼容性问题
- 内置的starter依赖解决常见的jar包冲突(比如Jackson不同版本的兼容问题)
- Actuator端点天然适合做毕业答辩演示(直接调用/actuator/health展示系统状态)
典型技术栈组合:
markdown复制- 核心框架:SpringBoot 2.7.x(LTS版本)
- 持久层:MyBatis-Plus + PageHelper(避免手写分页逻辑)
- 安全控制:Sa-Token(比Shiro配置更简单)
- 前端模板:Thymeleaf(服务端渲染方案,比Vue+axios更易调试)
- 数据库:MySQL 8.0(必须配置大小写敏感,避免Windows开发→Linux部署时的表名问题)
2.2 分层架构设计
建议采用改良版三层架构,特别注意DTO的运用:
code复制com.example.exhibition
├── config # 统一异常处理、Swagger配置
├── controller # 接口层(返回统一Result包装)
├── service
│ ├── impl # 业务实现(事务注解在此层)
├── dao # Mapper接口+XML
├── model
│ ├── entity # 数据库实体
│ ├── dto # 数据传输对象(如TicketOrderDTO)
│ └── vo # 视图对象(如ExhibitionVO)
└── util # 工具类(验证码生成等)
踩坑记录:Entity不要直接用于接口返回!一定要通过DTO隔离数据库字段变更。曾有同学修改了表结构导致所有接口报错,就是因为前端直接依赖了Entity字段。
3. 核心模块实现细节
3.1 展品管理模块
数据库设计要点:
sql复制CREATE TABLE `exhibit` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '展品名称',
`era` varchar(20) DEFAULT NULL COMMENT '年代(夏商周...)',
`material` varchar(30) DEFAULT NULL COMMENT '材质',
`is_fragile` tinyint(1) DEFAULT '0' COMMENT '是否易碎品',
`current_location` varchar(50) DEFAULT NULL COMMENT '当前位置',
`image_urls` json DEFAULT NULL COMMENT '图片JSON数组',
PRIMARY KEY (`id`),
FULLTEXT KEY `ft_idx` (`name`,`era`,`material`) WITH PARSER `ngram`
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
特色功能实现:
- 多条件筛选:使用MyBatis-Plus的LambdaQueryWrapper构建动态查询
java复制public Page<ExhibitVO> queryByCondition(ExhibitQueryDTO dto) {
return lambdaQuery()
.like(StringUtils.isNotBlank(dto.getKeyword()), Exhibit::getName, dto.getKeyword())
.eq(StringUtils.isNotBlank(dto.getEra()), Exhibit::getEra, dto.getEra())
.eq(dto.getIsFragile() != null, Exhibit::getIsFragile, dto.getIsFragile())
.page(new Page<>(dto.getPageNum(), dto.getPageSize()))
.convert(this::toVO);
}
- 图片存储:建议使用本地存储开发(节省OSS费用),但要做好路径隔离
yaml复制# application-dev.yml
file:
upload-dir: /tmp/exhibition/upload/
access-prefix: /upload/**
3.2 票务系统实现
关键业务流程:
- 用户选择日期时段 → 2. 系统校验余票 → 3. 生成待支付订单 → 4. 支付回调后出票
并发控制方案:
- 乐观锁解决超卖问题(比Redis分布式锁更轻量)
java复制@Transactional
public boolean createOrder(TicketOrderDTO dto) {
// 1. 查询场次库存
Session session = sessionMapper.selectById(dto.getSessionId());
// 2. 校验并扣减库存
int update = sessionMapper.updateStock(session.getId(), session.getVersion());
if (update == 0) {
throw new BusinessException("票已售罄");
}
// 3. 创建订单...
}
对应的SQL语句:
sql复制UPDATE exhibition_session
SET remain = remain - 1, version = version + 1
WHERE id = #{id} AND version = #{version} AND remain > 0
4. 毕业设计加分项实现
4.1 数据可视化大屏
使用ECharts实现馆长视图(无需复杂前端技术):
- 后端提供聚合数据接口
java复制@GetMapping("/dashboard")
public Result<DashboardVO> getDashboardData() {
return Result.success(new DashboardVO(
ticketService.getTodayVisitors(),
exhibitService.getCategoryStats(),
// 其他统计数据...
));
}
- 前端用Thymeleaf渲染基础HTML
html复制<div id="chart" style="width:600px;height:400px;"></div>
<script th:inline="javascript">
const chart = echarts.init(document.getElementById('chart'));
fetch('/dashboard').then(res => res.json()).then(data => {
chart.setOption({
series: [{
type: 'pie',
data: data.exhibitStats
}]
});
});
</script>
4.2 微信小程序对接
使用混合开发方案快速实现:
- 复用现有后端API
- 小程序端使用Uniapp框架
- 关键代码示例(获取展品列表):
javascript复制uni.request({
url: 'https://api.example.com/exhibit/list',
success: (res) => {
this.exhibitList = res.data;
}
});
5. 答辩准备与源码规范
5.1 文档撰写要点
- 系统流程图:用PlantUML绘制(比Visio更程序员友好)
plantuml复制@startuml
start
:用户访问小程序;
if (是否登录?) then (否)
:跳转登录页;
else (是)
:加载首页数据;
endif
@enduml
- 接口文档:Swagger UI + 中文注解
java复制@ApiOperation("根据ID查询展品详情")
@GetMapping("/exhibit/{id}")
public Result<ExhibitDetailVO> getExhibitDetail(
@ApiParam(value = "展品ID", example = "1")
@PathVariable Long id) {
//...
}
5.2 源码管理建议
标准的Git提交规范:
code复制feat: 新增展品删除功能
fix: 修复票务超卖问题
docs: 更新README部署说明
.gitignore必须包含:
code复制/target/
.idea/
*.iml
logs/
6. 避坑指南与经验总结
-
日期处理坑:
- MySQL8默认时区问题:在连接串添加
serverTimezone=Asia/Shanghai - 前端传日期字符串要用
@DateTimeFormat注解:
java复制@GetMapping("/session") public List<SessionVO> querySession( @DateTimeFormat(pattern = "yyyy-MM-dd") Date date) { //... } - MySQL8默认时区问题:在连接串添加
-
事务失效场景:
- 自调用问题:同一个类中A方法调用B方法,B方法的事务注解失效
- 解决方案:将B方法抽到新Service类,或使用
AopContext.currentProxy()
-
性能优化技巧:
- 展品列表接口添加二级缓存:
java复制@Cacheable(value = "exhibit", key = "#dto.pageNum + '-' + #dto.pageSize") public Page<ExhibitVO> queryByCondition(ExhibitQueryDTO dto) { //... } -
答辩常见问题准备:
- "为什么不用Redis?" → 回答:"考虑到单机部署场景,优先采用JVM缓存方案,但保留了缓存接口便于扩展"
- "系统能承受多少并发?" → 回答:"压测环境下Tomcat默认配置可支持200+ QPS,可通过调整线程池参数优化"
这个项目我在GitHub上开源了基础版(不含核心业务代码),包含Maven多模块配置、统一异常处理等基础设施,学弟学妹们可以基于此快速开发。记住毕业设计的核心是展示你的工程化能力——规范的代码、清晰的文档、可验证的功能,远比堆砌技术名词更重要。
