本系统是 《软件开发架构平台》 课程的综合实践大作业。 旨在整合课程中所学的 Spring、SpringMVC、MyBatis 等核心技术,构建一个功能完备、可应对高并发场景的 B/S 架构校园活动管理平台。
针对传统实验作业中存在的痛点进行了深度重构:
本项目严格遵循课程大纲要求,将理论知识转化为实际代码实现:
@Autowired, @Service, @Controller 实现分层解耦。@Transactional 保证数据原子性。MultipartFile 上传与虚拟路径映射。<if>, <choose> 标签实现多条件搜索与动态排序。<association> 标签在查询报名记录时关联查询 User 和 Activity 信息。系统严格遵循 MVC 分层架构,各层职责清晰:
职责: 系统的“前台”。接收 HTTP 请求,解析参数,调用 Service,并将数据放入 Model 返回给 Thymeleaf 页面。
listActivities(): 处理首页请求,接收 keyword 和 sort 参数。searchSuggest(): AJAX 接口,返回 JSON 格式的搜索候选词,供前端 JS 调用。uploadAvatar(): 处理 MultipartFile,调用工具方法保存文件到磁盘。职责: 系统的“大脑”。处理业务逻辑、事务控制 (@Transactional) 和缓存管理。
joinActivity(): 核心方法。包含 查重 -> 查活动状态 -> 乐观锁扣减库存 -> 写入报名表 完整流程。cancelRegistration(): 实现了“活动开始前1天不可取消”的业务规则校验。职责: 系统的“仓库管理员”。通过 XML 编写复杂 SQL。
addResourceHandlers,将 URL /uploads/** 映射到本地物理路径 D:/.../uploads/,解决图片回显问题。LocalDateTime 的问题。假设活动仅剩 1个名额,A和B同时请求。在多线程环境下,两者可能同时读取到 current=99,判断 99 < 100 通过,然后都执行 update(100),导致实际报名人数变成 101 人。
放弃 Java 层面的锁,利用数据库 Update 语句的原子性。我们将判断逻辑下沉到 SQL 中,数据库会自动对修改行加排他锁。
原理: 若 A 执行成功,数据变为 100;B 再执行时条件 100 < 100 不满足,SQL 返回“受影响行数 0”。Service 层捕获此结果并抛出“名额已满”异常。
| 表名 | 说明 | 关键设计 |
|---|---|---|
| users | 用户表 | role (0学生/1管理员), avatar (持久化路径) |
| activities | 活动表 |
current_participants (原子计数),max_participants (并发边界)
|
| activity_registrations | 报名表 | UNIQUE KEY (user_id, activity_id) 物理级防止重复报名 |