1. 项目概述
电影售票系统是当前影院管理中最核心的信息化工具之一。这个基于Java的毕业设计项目,完整实现了从影片管理、场次排期到在线选座购票的全流程功能。系统采用经典的B/S架构,前端使用JSP+HTML5技术,后端基于Spring+SpringMVC+MyBatis框架组合,数据库选用MySQL 5.7版本。
在实际开发过程中,我特别注重系统的实用性和稳定性。比如在座位锁定环节,采用了Redis缓存+数据库事务的双重保障机制;在支付模块接入了模拟的第三方支付接口;在后台管理部分实现了基于RBAC模型的权限控制系统。整个项目代码量约8500行,包含42个Java类文件、18个JSP页面和28张数据表。
提示:系统源码已托管在Gitee平台,文末会提供获取方式。建议先通读本文了解设计思路后再查看具体实现。
2. 核心需求解析
2.1 功能性需求
系统主要划分为三大模块:
-
前台购票模块:
- 影片分类浏览(正在热映/即将上映)
- 场次查询与座位可视化选择
- 在线支付与电子票生成
- 订单历史查询与退票
-
后台管理模块:
- 影片信息CRUD管理
- 放映厅与座位模板配置
- 场次排期与价格策略设置
- 销售统计与财务报表
-
系统基础模块:
- 用户注册/登录/找回密码
- 角色权限管理
- 系统日志审计
- 数据备份恢复
2.2 非功能性需求
-
性能要求:
- 首页加载时间≤1.5秒
- 并发购票请求响应时间≤3秒
- 支持500+用户同时在线
-
安全要求:
- 密码采用BCrypt加密存储
- SQL注入防护
- XSS攻击过滤
- 支付接口HTTPS加密
-
兼容性要求:
- 支持Chrome/Firefox/Edge主流浏览器
- 适配移动端浏览器基础功能
3. 技术架构设计
3.1 系统分层架构
code复制表现层:JSP + Bootstrap + jQuery
↓
控制层:Spring MVC
↓
业务层:Spring + 自定义业务组件
↓
持久层:MyBatis + PageHelper分页
↓
数据层:MySQL + Redis缓存
3.2 关键技术选型
-
Spring框架:
- IoC容器管理所有Bean
- AOP实现日志记录和事务管理
- 声明式事务控制@Transactional
-
MyBatis优化:
- 二级缓存配置
- 动态SQL生成
- 结果集自动映射
-
Redis应用:
- 使用String类型缓存热门影片
- 使用Hash类型存储座位状态
- 设置30分钟自动过期策略
-
安全控制:
- Shiro实现身份认证
- 自定义Realm处理权限
- 密码加盐哈希处理
4. 数据库设计
4.1 核心表结构
| 表名 | 字段数 | 主要字段 | 索引设计 |
|---|---|---|---|
| film | 18 | id,title,duration,type | 主键id, 联合索引(type,status) |
| cinema_hall | 9 | id,name,seat_template | 主键id |
| schedule | 12 | id,film_id,hall_id,start_time | 外键film_id,hall_id |
| seat | 6 | id,schedule_id,row_num,column_num | 联合索引(schedule_id,status) |
| order | 15 | order_no,user_id,total_amount | 唯一索引order_no |
4.2 关键关系设计
-
影片-场次一对多:
sql复制ALTER TABLE schedule ADD CONSTRAINT fk_film FOREIGN KEY (film_id) REFERENCES film(id) -
场次-座位一对多:
java复制// Schedule实体类中 private List<Seat> seatList; -
用户-订单一对多:
xml复制<resultMap id="userWithOrders" type="User"> <collection property="orders" ofType="Order"/> </resultMap>
5. 核心功能实现
5.1 座位锁定机制
java复制// 伪代码示例
public synchronized boolean lockSeats(List<Integer> seatIds) {
// 1. 检查座位是否可用
if(redisTemplate.opsForHash().get("schedule:123", seatIds) != "available") {
return false;
}
// 2. 开启数据库事务
TransactionStatus status = transactionManager.getTransaction();
try {
// 3. 更新数据库状态
seatMapper.updateStatus(seatIds, "locked");
// 4. 更新Redis缓存
seatIds.forEach(id ->
redisTemplate.opsForHash().put("schedule:123", id, "locked"));
// 5. 设置15分钟过期
redisTemplate.expire("schedule:123", 15, TimeUnit.MINUTES);
transactionManager.commit(status);
return true;
} catch (Exception e) {
transactionManager.rollback(status);
redisTemplate.opsForHash().delete("schedule:123", seatIds);
return false;
}
}
5.2 支付流程设计
-
正常流程:
code复制
用户选座 → 生成待支付订单 → 跳转支付页面 → 支付成功 → 更新订单状态 → 生成电子票 → 短信/邮件通知 -
异常处理:
- 支付超时:30分钟后自动释放座位
- 重复支付:通过订单号幂等性校验
- 支付失败:保留座位锁定状态,允许重新支付
5.3 票房统计实现
sql复制/* 日票房统计SQL示例 */
SELECT
f.title,
COUNT(o.id) AS sales_count,
SUM(o.total_amount) AS total_amount
FROM
order o
JOIN
schedule s ON o.schedule_id = s.id
JOIN
film f ON s.film_id = f.id
WHERE
o.status = 'paid'
AND o.create_time BETWEEN '2023-06-01' AND '2023-06-02'
GROUP BY
f.id
ORDER BY
total_amount DESC
6. 系统部署方案
6.1 环境要求
| 组件 | 版本 | 配置要求 |
|---|---|---|
| JDK | 1.8+ | 内存≥2GB |
| Tomcat | 9.0+ | 线程数≥200 |
| MySQL | 5.7+ | 缓冲池≥512MB |
| Redis | 5.0+ | 内存≥1GB |
6.2 部署步骤
-
数据库初始化:
bash复制
mysql -u root -p < cinema_db.sql -
Redis配置:
properties复制# application-redis.properties spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.timeout=3000 -
项目打包:
bash复制mvn clean package -Dmaven.test.skip=true -
Tomcat部署:
xml复制<!-- conf/server.xml 添加Context --> <Context path="/cinema" docBase="/opt/cinema-system.war"/>
7. 测试与优化
7.1 压力测试结果
使用JMeter模拟测试:
| 并发用户数 | 平均响应时间 | 错误率 | TPS |
|---|---|---|---|
| 100 | 1.2s | 0% | 85 |
| 300 | 2.8s | 1.2% | 142 |
| 500 | 4.5s | 3.8% | 167 |
7.2 性能优化措施
-
SQL优化:
- 为所有外键添加索引
- 使用EXPLAIN分析慢查询
- 优化JOIN操作避免全表扫描
-
缓存策略:
java复制@Cacheable(value = "films", key = "#type + '-' + #status") public List<Film> getFilmsByType(String type, String status) { // 数据库查询 } -
前端优化:
- 合并CSS/JS文件
- 启用Gzip压缩
- 使用CDN加载公共库
8. 常见问题解决
8.1 座位并发冲突
现象:多个用户同时选择同一座位
解决方案:
- 使用synchronized方法锁
- Redis分布式锁
- 乐观锁版本号控制
8.2 支付状态同步
现象:支付成功但订单状态未更新
解决方案:
- 引入消息队列异步处理
- 定时任务补偿检查
- 提供手动状态同步接口
8.3 内存泄漏排查
步骤:
- 使用jmap生成堆转储文件
bash复制
jmap -dump:format=b,file=heap.hprof <pid> - 通过MAT工具分析
- 定位到是未关闭的Redis连接
9. 项目扩展方向
-
移动端适配:
- 开发微信小程序版本
- 响应式布局优化
-
智能推荐:
- 基于用户历史的协同过滤
- 热门影片实时计算
-
大数据分析:
- 用户行为分析
- 上座率预测模型
-
微服务改造:
- 按功能模块拆分服务
- 引入Spring Cloud组件
源码获取方式:访问Gitee仓库(需替换为实际地址)克隆项目,导入IDE前请确保配置好Maven环境。建议使用IntelliJ IDEA打开项目,数据库脚本位于/sql目录下。