SpringBoot+Vue电影院订票系统全栈开发实战
1. 项目架构设计与技术选型
现代电影院订票系统需要处理高并发选座、实时支付等复杂场景,这对技术架构提出了更高要求。我们采用前后端分离架构,结合以下技术栈:
后端技术栈:
- SpringBoot 3.x:简化配置的微服务框架,内置Tomcat服务器
- Spring Data JPA:ORM框架简化数据库操作
- Redis:处理高并发座位锁定
- MySQL 8.0:关系型数据库存储核心业务数据
- Spring Security:认证与授权管理
前端技术栈:
- Vue 3:响应式前端框架
- Pinia:状态管理库替代Vuex
- Element Plus:UI组件库
- Axios:HTTP请求库
开发环境:
- JDK 17:SpringBoot 3.x推荐版本
- Node.js 18+:Vue开发环境
- IDEA Ultimate:集成开发环境
- Navicat:数据库管理工具
// 示例:SpringBoot主启动类
@SpringBootApplication
public class CinemaApplication {
public static void main(String[] args) {
SpringApplication.run(CinemaApplication.class, args);
}
}
2. 数据库设计与优化
电影院系统的核心在于高效的数据模型设计。我们采用规范化设计原则,主要包含以下表结构:
核心表关系图:
- 用户表(t_user)
- 电影表(t_film)
- 放映厅表(t_hall)
- 场次表(t_schedule)
- 座位表(t_seat)
- 订单表(t_order)
- 支付记录表(t_payment)
-- 场次表示例DDL
CREATE TABLE t_schedule (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
film_id BIGINT NOT NULL,
hall_id BIGINT NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
price DECIMAL(10,2) NOT NULL,
status TINYINT DEFAULT 1,
FOREIGN KEY (film_id) REFERENCES t_film(id),
FOREIGN KEY (hall_id) REFERENCES t_hall(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
索引优化策略:
- 为所有外键字段建立索引
- 为高频查询字段(如start_time)建立组合索引
- 使用覆盖索引减少回表查询
缓存设计:
- 使用Redis缓存热门电影信息
- 采用Redis的Sorted Set实现座位状态实时更新
- 订单状态变更使用Redis发布订阅模式
3. 核心功能实现
3.1 高并发选座解决方案
电影院订票系统最关键的挑战是高并发下的座位冲突问题。我们采用分布式锁+乐观锁双重保障机制:
// 选座核心逻辑
public Result selectSeats(Long scheduleId, List<Long> seatIds) {
// 1. 获取分布式锁
String lockKey = "lock:schedule:" + scheduleId;
try {
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
if (!locked) {
return Result.fail("系统繁忙,请稍后再试");
}
// 2. 验证座位状态
List<Seat> seats = seatService.getSeats(scheduleId, seatIds);
if (seats.stream().anyMatch(s -> s.getStatus() != 0)) {
return Result.fail("部分座位已被预订");
}
// 3. 锁定座位(乐观锁)
int updated = seatService.lockSeats(scheduleId, seatIds);
if (updated != seatIds.size()) {
return Result.fail("座位状态已变更");
}
// 4. 生成临时订单(15分钟有效期)
String orderNo = orderService.createTempOrder(scheduleId, seatIds);
return Result.success(orderNo);
} finally {
redisTemplate.delete(lockKey);
}
}
3.2 支付状态同步机制
支付成功后的状态同步需要保证数据一致性:
- 支付平台回调通知
- 系统验证支付真实性
- 更新订单状态为已支付
- 持久化座位状态变更
- 发送订票成功通知
// 支付回调处理
@Transactional
public Result handlePaymentNotify(PaymentNotifyDTO dto) {
// 1. 验证支付签名
if (!paymentService.verifySign(dto)) {
return Result.fail("签名验证失败");
}
// 2. 查询临时订单
Order order = orderService.getByOrderNo(dto.getOrderNo());
if (order == null || order.getStatus() != 0) {
return Result.fail("订单状态异常");
}
// 3. 更新订单状态
order.setStatus(1); // 已支付
order.setPayTime(LocalDateTime.now());
order.setPaymentAmount(dto.getAmount());
orderService.updateOrder(order);
// 4. 确认座位
seatService.confirmSeats(order.getScheduleId(), order.getSeatIds());
// 5. 发送通知
notificationService.sendOrderSuccess(order.getUserId(), order);
return Result.success();
}
4. 前端关键组件实现
4.1 选座组件开发
使用Canvas实现高性能的影院座位图渲染:
<template>
<div class="seat-map">
<canvas ref="canvas" @click="handleSeatClick"></canvas>
<div class="legend">
<span class="available">可选</span>
<span class="selected">已选</span>
<span class="sold">已售</span>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useSeatStore } from '@/stores/seat';
const props = defineProps({
scheduleId: Number
});
const canvas = ref(null);
const seatStore = useSeatStore();
// 初始化座位图
const initSeatMap = async () => {
const seats = await seatStore.fetchSeats(props.scheduleId);
const ctx = canvas.value.getContext('2d');
// 绘制座位图逻辑
seats.forEach(seat => {
drawSeat(ctx, seat);
});
};
// 处理座位点击
const handleSeatClick = (event) => {
const rect = canvas.value.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
// 计算点击的座位坐标
const seat = findSeatByPosition(x, y);
if (seat && seat.status === 0) {
seatStore.toggleSelect(seat);
redrawSeatMap();
}
};
onMounted(() => {
initSeatMap();
});
</script>
4.2 支付流程实现
集成主流支付方式,确保支付流程顺畅:
<script setup>
import { ref } from 'vue';
import { useOrderStore } from '@/stores/order';
const orderStore = useOrderStore();
const paymentType = ref('wechat');
const isPaying = ref(false);
const handlePayment = async () => {
try {
isPaying.value = true;
const orderNo = orderStore.currentOrder.no;
// 调用支付接口
const paymentUrl = await orderStore.createPayment({
orderNo,
type: paymentType.value
});
// 跳转支付页面
if (paymentType.value === 'wechat') {
window.location.href = paymentUrl;
} else {
// 支付宝支付处理
const div = document.createElement('div');
div.innerHTML = paymentUrl;
document.body.appendChild(div);
document.forms[0].submit();
}
} catch (error) {
console.error('支付失败:', error);
} finally {
isPaying.value = false;
}
};
</script>
5. 系统安全与性能优化
5.1 安全防护措施
- 接口安全:
- 所有API启用HTTPS
- 敏感接口增加限流(如登录、支付)
- 使用JWT进行身份验证
// JWT认证配置
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
- 数据安全:
- 敏感字段加密存储(如用户手机号)
- 支付密码使用BCrypt加密
- 定期审计数据库权限
5.2 性能优化方案
前端优化:
- 使用Vue的异步组件实现路由懒加载
- 静态资源CDN加速
- 关键API请求预加载
后端优化:
- Nginx配置Gzip压缩
- 启用HTTP/2协议
- 热点数据多级缓存
# Nginx性能优化配置示例
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript;
upstream backend {
server 127.0.0.1:8080;
keepalive 32;
}
server {
listen 443 ssl http2;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location /api {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
}
6. 部署与监控
6.1 容器化部署
使用Docker Compose编排服务:
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: cinema
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:6
ports:
- "6379:6379"
volumes:
- redis_data:/data
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
volumes:
mysql_data:
redis_data:
6.2 监控方案
监控指标:
- 系统指标:CPU、内存、磁盘使用率
- 业务指标:并发用户数、订单成功率
- 异常监控:接口错误率、慢查询
监控工具栈:
- Prometheus + Grafana:指标收集与可视化
- ELK:日志收集与分析
- Sentry:前端错误监控
# Prometheus配置示例
scrape_configs:
- job_name: 'springboot'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['backend:8080']
- job_name: 'node'
static_configs:
- targets: ['frontend:9100']
7. 项目演进方向
-
微服务化改造:
- 按业务拆分服务(用户服务、订单服务、支付服务)
- 引入Spring Cloud生态组件
- 服务网格化治理
-
智能化升级:
- 基于用户行为的电影推荐
- 动态定价策略
- 观影热度预测
-
用户体验优化:
- 虚拟选座3D可视化
- 无障碍访问支持
- 多语言国际化
// 电影推荐服务示例
@Service
public class RecommendationService {
@Cacheable(value = "recommendations", key = "#userId")
public List<Film> recommendFilms(Long userId) {
// 基于协同过滤算法实现推荐
List<UserBehavior> behaviors = behaviorService.getUserBehaviors(userId);
// 推荐逻辑实现...
return recommendedFilms;
}
}
实际开发中,我们还需要建立完善的CI/CD流程,编写全面的单元测试和集成测试,确保系统稳定可靠。对于电影院这类有明显高峰时段的业务场景,还需要考虑弹性扩容方案,如Kubernetes的HPA自动扩缩容。

58

被折叠的 条评论
为什么被折叠?



