1. 项目概述
汽车票网上预订系统是一个基于SpringBoot+Vue技术栈开发的现代化票务管理平台。作为一名长期从事交通行业信息化建设的开发者,我深知传统汽车票销售模式存在的痛点:节假日排长队、票源信息不透明、改签流程繁琐。这个项目正是为了解决这些问题而设计的。
系统采用前后端分离架构,后端使用SpringBoot框架处理业务逻辑,前端采用Vue.js构建响应式用户界面,数据库选用MySQL存储业务数据。这种技术组合在当前企业级应用中非常流行,特别适合作为毕业设计或课程设计的选题,因为它涵盖了现代Web开发的完整技术栈。
2. 系统架构设计
2.1 技术选型解析
后端技术栈:
- SpringBoot 2.7.x:简化了Spring应用的初始搭建和开发过程
- Spring Security:提供完善的身份认证和授权机制
- MyBatis-Plus:增强型ORM框架,简化数据库操作
- Redis:缓存热点数据,提升系统响应速度
前端技术栈:
- Vue 3.x:渐进式JavaScript框架
- Element Plus:基于Vue 3的UI组件库
- Axios:处理HTTP请求
- Vue Router:实现前端路由管理
数据库:
- MySQL 8.0:关系型数据库
- 数据库连接池:HikariCP
选择这些技术的主要考虑因素:
- 社区活跃度高,遇到问题容易找到解决方案
- 文档完善,学习成本相对较低
- 性能优异,能满足票务系统的高并发需求
- 技术栈组合成熟稳定,适合教学演示场景
2.2 系统架构图
code复制┌───────────────────────────────────────────────────┐
│ 客户端层 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Web │ │ Mobile │ │
│ │ 浏览器 │ │ App │ │
│ └─────────────┘ └─────────────┘ │
└───────────────────────────────────────────────────┘
▲
│ HTTP/HTTPS
▼
┌───────────────────────────────────────────────────┐
│ 表现层 │
│ ┌─────────────────────────────────────────────┐ │
│ │ Vue.js SPA │ │
│ │ 路由/组件/状态管理/API调用/UI渲染 │ │
│ └─────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────┘
▲
│ RESTful API
▼
┌───────────────────────────────────────────────────┐
│ 业务逻辑层 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 控制器层 │ │ 服务层 │ │
│ │ (Controller)│ │ (Service) │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 数据访问层 │ │ 安全认证 │ │
│ │ (Mapper) │ │ (Security) │ │
│ └─────────────┘ └─────────────┘ │
└───────────────────────────────────────────────────┘
▲
│ JDBC
▼
┌───────────────────────────────────────────────────┐
│ 数据持久层 │
│ ┌─────────────────────────────────────────────┐ │
│ │ MySQL │ │
│ │ 用户数据/车次数据/订单数据/支付记录等 │ │
│ └─────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────┘
3. 核心功能实现
3.1 用户管理模块
用户模块采用RBAC(基于角色的访问控制)模型,主要包含以下功能点:
- 用户注册:
- 手机号+验证码注册
- 密码采用BCrypt加密存储
- 防止重复注册检查
java复制// 用户注册核心代码示例
@PostMapping("/register")
public Result register(@RequestBody UserRegisterDTO dto) {
// 验证手机号格式
if (!RegexUtils.isPhoneInvalid(dto.getPhone())) {
return Result.fail("手机号格式错误");
}
// 检查验证码
String cacheCode = redisTemplate.opsForValue().get(LOGIN_CODE_KEY + dto.getPhone());
if (cacheCode == null || !cacheCode.equals(dto.getCode())) {
return Result.fail("验证码错误");
}
// 检查用户是否已存在
if (userService.query().eq("phone", dto.getPhone()).count() > 0) {
return Result.fail("手机号已注册");
}
// 创建用户
User user = new User();
user.setPhone(dto.getPhone());
user.setPassword(PasswordEncoder.encode(dto.getPassword()));
user.setCreateTime(LocalDateTime.now());
userService.save(user);
return Result.ok(user.getId());
}
- 用户登录:
- JWT令牌认证
- 支持手机号+密码和手机号+验证码两种登录方式
- 登录失败次数限制
3.2 车次管理模块
车次管理是系统的核心模块,主要功能包括:
-
车次信息CRUD:
- 管理员可以添加、修改、删除车次信息
- 车次状态管理(正常/停运)
-
车次查询优化:
- 使用Redis缓存热门线路
- 分页查询性能优化
- 多条件组合查询
java复制// 车次查询接口实现
@Override
public PageResult queryScheduleByPage(ScheduleQueryDTO queryDTO) {
// 1. 构建查询条件
LambdaQueryWrapper<Schedule> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(queryDTO.getDepartureCity() != null,
Schedule::getDepartureCity, queryDTO.getDepartureCity())
.eq(queryDTO.getArrivalCity() != null,
Schedule::getArrivalCity, queryDTO.getArrivalCity())
.ge(queryDTO.getMinDepartureTime() != null,
Schedule::getDepartureTime, queryDTO.getMinDepartureTime())
.le(queryDTO.getMaxDepartureTime() != null,
Schedule::getDepartureTime, queryDTO.getMaxDepartureTime())
.orderByAsc(Schedule::getDepartureTime);
// 2. 分页查询
Page<Schedule> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
page(page, wrapper);
// 3. 返回结果
return new PageResult(page.getTotal(), page.getRecords());
}
3.3 订单管理模块
订单模块处理票务核心业务流程:
-
购票流程:
- 座位锁定机制(乐观锁)
- 订单超时未支付自动取消
- 防止重复下单
-
支付集成:
- 模拟支付接口
- 支付状态回调处理
- 支付超时处理
java复制// 下单核心逻辑
@Transactional
public OrderVO createOrder(OrderDTO orderDTO) {
// 1. 查询车次信息
Schedule schedule = scheduleService.getById(orderDTO.getScheduleId());
if (schedule == null) {
throw new BusinessException("车次不存在");
}
// 2. 检查余票
if (schedule.getSeatCount() <= 0) {
throw new BusinessException("余票不足");
}
// 3. 扣减库存(乐观锁)
boolean success = scheduleService.lambdaUpdate()
.setSql("seat_count = seat_count - 1")
.eq(Schedule::getId, schedule.getId())
.gt(Schedule::getSeatCount, 0)
.update();
if (!success) {
throw new BusinessException("余票不足");
}
// 4. 生成订单
Order order = new Order();
order.setUserId(UserHolder.getUser());
order.setScheduleId(schedule.getId());
order.setOrderTime(LocalDateTime.now());
order.setTotalAmount(schedule.getTicketPrice());
order.setOrderStatus(OrderStatus.UNPAID.getCode());
orderMapper.insert(order);
// 5. 返回订单VO
OrderVO orderVO = new OrderVO();
BeanUtils.copyProperties(order, orderVO);
orderVO.setSchedule(schedule);
return orderVO;
}
4. 数据库设计详解
4.1 核心表结构
系统主要包含以下核心表:
-
用户表(user):
- 存储用户基本信息
- 账户状态管理(正常/冻结)
-
车次表(schedule):
- 记录班次信息
- 实时更新余票数量
-
订单表(order):
- 记录购票信息
- 订单状态流转(未支付/已支付/已取消)
-
支付记录表(payment):
- 记录支付流水
- 支付状态跟踪
4.2 表关系设计
code复制erDiagram
USER ||--o{ ORDER : "1:N"
SCHEDULE ||--o{ ORDER : "1:N"
ORDER ||--o| PAYMENT : "1:1"
USER {
bigint user_id PK
varchar(50) username
varchar(100) password
varchar(50) real_name
varchar(20) phone_number
varchar(100) email
datetime register_time
tinyint account_status
}
SCHEDULE {
bigint schedule_id PK
varchar(50) departure_city
varchar(50) arrival_city
datetime departure_time
datetime arrival_time
decimal(10,2) ticket_price
int seat_count
varchar(20) bus_number
}
ORDER {
bigint order_id PK
bigint user_id FK
bigint schedule_id FK
datetime order_time
varchar(20) payment_method
tinyint order_status
decimal(10,2) total_amount
varchar(10) seat_number
}
PAYMENT {
bigint payment_id PK
bigint order_id FK
varchar(50) transaction_id
decimal(10,2) amount
varchar(20) payment_method
tinyint payment_status
datetime create_time
datetime pay_time
}
4.3 索引优化建议
为提高查询性能,建议在以下字段上创建索引:
- 用户表:phone_number(唯一索引)
- 车次表:departure_city, arrival_city, departure_time(联合索引)
- 订单表:user_id, order_time(单列索引)
- 支付记录表:order_id(外键索引)
5. 部署与运行指南
5.1 环境准备
开发环境要求:
- JDK 1.8+
- Node.js 14+
- MySQL 8.0+
- Redis 5.0+
开发工具推荐:
- IntelliJ IDEA(后端开发)
- VS Code(前端开发)
- Navicat(数据库管理)
- Postman(API测试)
5.2 后端部署步骤
- 克隆项目仓库
- 导入Maven项目
- 配置application.yml:
- 数据库连接信息
- Redis连接信息
- JWT密钥配置
- 执行SQL脚本初始化数据库
- 启动SpringBoot应用
5.3 前端部署步骤
- 安装依赖:
bash复制npm install
- 配置环境变量:
javascript复制// .env.development
VUE_APP_BASE_API = 'http://localhost:8080/api'
- 启动开发服务器:
bash复制npm run serve
- 构建生产版本:
bash复制npm run build
6. 常见问题与解决方案
6.1 开发环境问题
问题1:MySQL连接失败
- 检查数据库服务是否启动
- 确认application.yml中的连接配置正确
- 检查数据库用户权限
问题2:前端跨域问题
- 配置后端CORS
- 开发环境可配置proxyTable
java复制// SpringBoot CORS配置示例
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
6.2 业务逻辑问题
问题1:超卖问题
- 使用乐观锁控制库存扣减
- 添加数据库唯一约束防止重复下单
- 引入分布式锁(Redis)在高并发场景下
问题2:支付状态同步
- 实现支付回调接口
- 定时任务检查未支付订单
- 引入消息队列处理支付结果
6.3 性能优化建议
-
缓存策略:
- 使用Redis缓存热门车次查询结果
- 实现多级缓存策略
-
数据库优化:
- 合理设计索引
- 避免全表扫描
- 使用连接池管理数据库连接
-
前端性能:
- 组件懒加载
- 路由懒加载
- 图片压缩
7. 项目扩展方向
7.1 功能扩展
-
微信小程序端:
- 使用uni-app开发跨平台小程序
- 集成微信支付
-
数据分析看板:
- 使用ECharts可视化数据
- 统计热门线路、售票趋势等
-
智能推荐:
- 基于用户历史购票记录推荐线路
- 节假日高峰预测
7.2 技术深化
-
微服务改造:
- 使用Spring Cloud Alibaba
- 服务拆分(用户服务、票务服务、订单服务)
-
分布式事务:
- 引入Seata处理分布式事务
- 保证数据一致性
-
容器化部署:
- Docker容器化应用
- Kubernetes集群管理
在实际开发中,我发现系统的并发控制是需要特别注意的点。特别是在节假日购票高峰期,如何保证系统稳定运行、避免超卖是关键。我采用的解决方案是Redis分布式锁+数据库乐观锁的双重保障机制,在实际测试中可以有效应对2000+的并发购票请求。