2026/9/16 6:29:22

SpringBoot+Uniapp博物馆预约系统开发实践

SpringBoot+Uniapp博物馆预约系统开发实践 1. 项目概述去年帮学弟做的这个博物馆预约小程序项目上线后日均访问量稳定在3000后台管理也经受住了五一黄金周的流量考验。这个基于SpringBootUniapp的多平台解决方案最大的优势在于一套代码同时适配微信小程序和H5页面维护成本直接减半。博物馆场景的预约系统有几个特殊需求需要实时同步各时段余票、支持分时段预约、证件信息OCR识别、黑名单防黄牛机制等。我们通过SpringBoot的定时任务Redis分布式锁解决了库存同步问题利用Uniapp的跨端特性实现多平台覆盖整个开发周期控制在6周内完成。2. 技术架构设计2.1 后端SpringBoot选型考量选择SpringBoot 2.7.x版本主要基于内置Tomcat简化部署Actuator端点方便监控与MyBatis-Plus的完美配合丰富的Starter生态特别是Spring Security和Redis数据库采用MySQL 8.0关键表设计CREATE TABLE reservation ( id bigint NOT NULL AUTO_INCREMENT, user_id varchar(32) NOT NULL COMMENT 微信openid, museum_id int NOT NULL, time_slot datetime NOT NULL COMMENT 预约时段, visitor_count tinyint NOT NULL DEFAULT 1, id_card varchar(18) NOT NULL COMMENT 身份证号, status tinyint NOT NULL DEFAULT 0 COMMENT 0-待核销 1-已使用 2-已取消, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user (user_id), KEY idx_museum_time (museum_id,time_slot) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;2.2 前端跨端方案对比调研过Taro和原生小程序开发后最终选择Uniapp的原因更接近Vue的语法习惯完善的插件市场特别是uView UI真机调试体验更好一键打包多端的便捷性实际开发中需要注意页面路径需要兼容H5和小程序两种模式组件库要选用跨端兼容的版本微信API需要条件编译// 条件编译示例 // #ifdef H5 import h5Module from ./h5-module.js // #endif // #ifdef MP-WEIXIN import wxModule from ./wx-module.js // #endif3. 核心功能实现3.1 预约时段管理采用分时段的库存桶设计每个时段作为独立库存单元Redis存储实时余量MySQL持久化总配额关键代码逻辑Transactional public boolean makeReservation(ReservationDTO dto) { // 获取分布式锁 String lockKey museum: dto.getMuseumId() : dto.getTimeSlot(); try { boolean locked redisTemplate.opsForValue() .setIfAbsent(lockKey, 1, 10, TimeUnit.SECONDS); if (!locked) throw new BusException(当前时段预约火爆); // 检查余量 Integer remain redisTemplate.opsForValue() .get(inventory: lockKey); if (remain null || remain 0) { throw new BusException(该时段已约满); } // 扣减库存 redisTemplate.opsForValue() .decrement(inventory: lockKey); // 创建预约记录 Reservation entity convertToEntity(dto); mapper.insert(entity); return true; } finally { redisTemplate.delete(lockKey); } }3.2 微信登录与身份核验微信小程序登录流程优化点前端静默获取code后端用code换openid关联手机号需要用户主动授权安全防护措施接口签名验证敏感信息加密传输操作日志全记录// Uniapp登录实现 uni.login({ provider: weixin, success: async (res) { const { code } res; const { data: token } await this.$http.post(/auth/login, { code }); uni.setStorageSync(token, token); } });4. 典型问题解决方案4.1 高并发库存超卖我们采用三级防护前端提交防重按钮禁用loading后端Redis原子操作数据库最终一致性校验实测可支撑3000 TPS的预约请求。4.2 跨平台样式适配Uniapp样式处理经验使用rpx替代px条件编译处理平台差异关键组件做多套样式方案/* 通用样式 */ .container { padding: 20rpx; } /* 仅微信小程序生效 */ /* #ifdef MP-WEIXIN */ .custom-navbar { height: 90rpx; } /* #endif */4.3 微信审核常见被拒原因实际内容与类目不符 → 选择政务民生-博物馆类目缺少隐私政策 → 在关于我们添加条款表单收集身份证信息 → 必须提供隐私说明虚拟支付问题 → 免费预约不涉及支付5. 部署与运维实践5.1 后端服务部署采用Docker Compose编排version: 3 services: app: image: openjdk:11-jre ports: - 8080:8080 volumes: - ./app.jar:/app.jar command: [java, -jar, /app.jar] depends_on: - redis - mysql redis: image: redis:6 ports: - 6379:6379 volumes: - redis_data:/data mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: 123456 ports: - 3306:3306 volumes: - mysql_data:/var/lib/mysql volumes: redis_data: mysql_data:5.2 小程序发布流程开发版本测试 → 体验版审核 → 正式发布关键路径检查清单所有API域名已备案隐私协议可访问核心功能无报错页面加载时间1s6. 项目扩展方向智能推荐时段基于历史数据预测人流虚拟展厅导览WebGL集成3D展品会员积分体系增加用户粘性大数据看板实时监控参观流量这个项目给我最深的体会是跨端开发一定要从项目初期就统一设计规范特别是接口数据结构要保持一致。我们中途因为H5和小程序字段不统一导致的重构浪费了整整3天工时。