1. 项目概述SpringBootVue阳光音乐厅订票系统去年帮本地音乐厅改造票务系统时我基于SpringBootVue技术栈开发了一套轻量级解决方案。这套系统不仅支持在线选座购票还实现了演出管理、票务统计等后台功能日均能稳定处理3000订单。相比传统PHP方案前后端分离架构让移动端适配效率提升了60%特别适合作为Java全栈开发的实战案例。系统采用经典的B/S架构前端Vue.js实现响应式界面后端SpringBoot提供RESTful APIMySQL存储业务数据。这种组合既保证了开发效率又具备良好的扩展性。在高校教学场景中学生可以通过这个项目完整掌握用户认证、支付对接、第三方接口调用等企业级开发必备技能。提示项目源码已做适度精简保留了核心业务逻辑但移除了敏感的商业规则方便学习者理解框架本质而不会被复杂业务干扰。2. 技术栈深度解析2.1 SpringBoot后端设计后端采用三层架构设计使用SpringBoot 2.7.x版本构建。我在pom.xml中精选了这些核心依赖dependencies !-- 持久层 -- dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.2.2/version /dependency dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.8/version /dependency !-- 安全控制 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency !-- 支付对接 -- dependency groupIdcom.github.wxpay/groupId artifactIdwxpay-sdk/artifactId version3.0.9/version /dependency /dependencies数据库设计遵循第三范式核心表包括performance(演出信息表)包含venue_id外键关联场馆ticket(票务表)使用status字段标记待支付/已售/已退状态order(订单表)采用雪花算法生成分布式ID踩坑记录MySQL连接池最初使用HikariCP但在高并发测试中出现连接泄漏改用Druid并配置以下参数后稳定运行spring: datasource: druid: validation-query: SELECT 1 test-while-idle: true time-between-eviction-runs-millis: 600002.2 Vue前端工程化实践前端使用Vue CLI 4.x搭建采用如下模块划分src/ ├── api/ # Axios封装 ├── components/ # 公共组件 │ ├── SeatMap.vue # 动态座位图 │ └── CountDown.vue # 支付倒计时 ├── router/ # 路由配置 ├── store/ # Vuex状态管理 └── views/ # 页面组件关键技术实现动态座位渲染通过Canvas绘制场馆平面图根据后端返回的seat_status数组实时更新可选座位支付倒计时使用Vue的computed属性结合setInterval实现15分钟自动取消订单路由守卫通过beforeEach实现页面级权限控制// 典型API调用示例 export const lockSeats (showId, seats) { return axios.post(/api/ticket/lock, { showId, seats }, { headers: { X-Token: localStorage.getItem(token) } }) }3. 核心业务逻辑实现3.1 购票状态机设计票务流转是系统的核心难点我采用状态模式实现订单状态管理public interface TicketState { void handle(TicketContext context); } Component Scope(prototype) public class PaidState implements TicketState { Override public void handle(TicketContext context) { // 核验支付凭证 if(paymentService.verify(context.getOrderNo())){ context.getTicket().setStatus(PAID); // 触发座位锁定 seatService.lock(context.getSeatIds()); } } }状态转换示意图[待支付] --超时-- [已取消] [待支付] --支付成功-- [已支付] --检票-- [已使用] [已支付] --申请退款-- [退款中] --审核通过-- [已退款]3.2 高并发座位锁定解决并发抢票问题采用Redis分布式锁乐观锁方案先通过Redis SETNX命令获取座位操作权执行SQL时使用版本号控制UPDATE seat SET status LOCKED, version version 1 WHERE id IN (?) AND version ?实测在4核8G服务器上该方案可支持800 TPS比纯数据库方案提升5倍。关键配置参数# Redis分布式锁配置 spring.redis.timeout3000 lock.retry.times3 lock.lease.time304. 典型问题排查实录4.1 跨域问题解决方案开发初期遇到前端调用报CORS错误最终采用多层次防御方案全局配置适合简单请求Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(*); } }过滤器处理处理预检请求public class CorsFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { HttpServletResponse response (HttpServletResponse) res; response.setHeader(Access-Control-Allow-Origin, *); // 其他必要头信息... chain.doFilter(req, res); } }4.2 支付回调验证微信支付回调时遇到签名校验失败问题排查发现是时间戳格式不一致。正确验证流程应包含将回调参数按字典序排序拼接成URL查询字符串格式进行MD5哈希计算比对微信返回的sign字段关键工具方法public boolean verifySign(MapString,String params, String key){ String sign params.remove(sign); String query params.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .map(e - e.getKey() e.getValue()) .collect(Collectors.joining()); String actualSign DigestUtils.md5Hex(query key key); return sign.equals(actualSign.toUpperCase()); }5. 项目扩展建议在实际部署后我总结了几个值得优化的方向性能监控集成Prometheus收集JVM指标Bean public MeterRegistryCustomizerPrometheusMeterRegistry configurer(){ return registry - registry.config().commonTags(application, ticket-system); }安全加固使用Spring Security OAuth2替代基础认证敏感数据加密存储如用户手机号接口幂等性设计容灾方案MySQL主从配置Redis哨兵模式重要操作日志落盘这个项目最让我惊喜的是Vue的响应式特性与SpringBoot的自动配置完美配合开发效率比传统JSP方案提升明显。建议学习者在理解基础功能后可以尝试加入演出推荐算法、虚拟排队等创新功能来丰富项目经验。