SpringBoot+Vue电影院订票系统实战:从数据库设计到选座支付全流程

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;

索引优化策略

  1. 为所有外键字段建立索引
  2. 为高频查询字段(如start_time)建立组合索引
  3. 使用覆盖索引减少回表查询

缓存设计

  • 使用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 支付状态同步机制

支付成功后的状态同步需要保证数据一致性:

  1. 支付平台回调通知
  2. 系统验证支付真实性
  3. 更新订单状态为已支付
  4. 持久化座位状态变更
  5. 发送订票成功通知
// 支付回调处理
@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 安全防护措施

  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();
    }
}
  1. 数据安全
    • 敏感字段加密存储(如用户手机号)
    • 支付密码使用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. 项目演进方向

  1. 微服务化改造

    • 按业务拆分服务(用户服务、订单服务、支付服务)
    • 引入Spring Cloud生态组件
    • 服务网格化治理
  2. 智能化升级

    • 基于用户行为的电影推荐
    • 动态定价策略
    • 观影热度预测
  3. 用户体验优化

    • 虚拟选座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自动扩缩容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值