ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

微信小程序+Java后端琴房系统毕业设计源码解析与避坑指南

微信小程序+Java后端琴房系统毕业设计源码解析与避坑指南 简介面向高校毕业设计场景的琴房管理系统完整项目包基于微信小程序与Java后端实现覆盖学生、管理员两类角色。学生端支持琴房信息浏览、在线留言、登录预约与个人中心管理端提供轮播公告、师生信息、留言审核及琴房类型与预约管理适合作为JavaWeb或微信小程序方向课程设计与毕业设计的改造参考。压缩包共1098个文件以png图片、java与class源码、vue前端页面、js脚本、xml配置及sql数据库脚本为主同时包含bat启动脚本、md说明与演示视频整体压缩包体积约18.76MB便于直接导入开发者工具运行。目前已吸引175人学习与浏览。资料内附完整数据库脚本、前后端源码、环境构建说明及操作演示可帮助快速梳理预约流程与管理后台逻辑是完成课题答辩和功能扩展的实用素材。1. 琴房管理系统毕业设计微信小程序Java后端这套源码包到底解决什么问题很多人下载“基于微信小程序java后端的琴房管理系统毕业设计(源码数据库说明演示视频).rar”都是因为毕设选题卡住了。这套东西解决的是琴房预约这个高频场景——学生打开微信小程序查看空闲琴房、选时间段、下单预约管理员登录Java后端维护琴房、处理订单和余额。交付给用户的不只是代码还有建库脚本、说明文档和演示视频理论上解压后按步骤就能跑起来。适合正在做毕设的本科生也适合想给自家琴行或培训教室搭一个预约小程序的人。下面从选型、目录结构、启动流程、核心代码改造和容易翻车的地方逐一拆。2. 微信小程序Java后端的选型逻辑和数据库落地把地基先铺对2.1 为什么是微信小程序Java后端毕设验收和简历面试的双重考量这些年还能看到大量“微信小程序Java”标题的毕设包不是因为旧而是这个组合在高校验收和企业招聘两个维度上都站得住。前端小程序在微信开发者工具里直接跑安卓、iOS都能用同一个入口不必单独打包后端用Java答辩时老师一听Spring Boot、MySQL、MyBatis默认你走的是主流技术栈。有人会问为什么不用uniapp跨一端毕设场景下小程序原生写起来更直接uniapp反而要多处理一层编译差异。常见后端结构是Spring Boot MyBatis MySQL也有用MyBatis Plus的。谈不上谁更优MyBatis Plus减少单表增删改查的重复代码订单时段冲突这类复杂查询还是原生MyBatis更好控制SQL。如果源码包里的Mapper XML结构完整Controller层很薄基本就是Controller→Service→Mapper三层小程序端对接REST接口。下面都按这个结构来聊。2.2 琴房预约系统的四张核心表字段设计、索引和一只可导入的SQL多数琴房毕设包里的MySQL脚本有4到6张表。命名习惯差异很大用户表可能是user、sys_user或t_user琴房表常见practice_room、room、qinfang预约表常见reservation、reserve、order。拿到包第一件事是打开SQL脚本确认有哪几张核心表。完整预约闭环需要用户、琴房、预约、充值记录四张表余额扣款才能串起来。下面这版按常规做法设计-- 用户表 CREATE TABLE sys_user ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键, wx_openid varchar(64) DEFAULT NULL COMMENT 微信openid小程序登录后写入, nickname varchar(32) DEFAULT NULL COMMENT 昵称, phone varchar(20) DEFAULT NULL COMMENT 手机号, role tinyint(4) NOT NULL DEFAULT 0 COMMENT 0-普通用户 1-管理员, balance decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT 账户余额, create_time datetime DEFAULT NULL COMMENT 注册时间, PRIMARY KEY (id), UNIQUE KEY uk_openid (wx_openid) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表; -- 琴房表 CREATE TABLE practice_room ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键, room_name varchar(50) NOT NULL COMMENT 琴房名称如A101, location varchar(100) DEFAULT NULL COMMENT 所在楼层位置, price_per_hour decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT 每小时价格, equipment varchar(255) DEFAULT NULL COMMENT 钢琴型号、音响、空调等设备描述, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 0-空闲 1-维护中 2-禁用, image_url varchar(255) DEFAULT NULL COMMENT 琴房实拍图, create_time datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT琴房表; -- 预约订单表 CREATE TABLE reservation ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键, user_id int(11) NOT NULL COMMENT 下单用户id, room_id int(11) NOT NULL COMMENT 琴房id, reserve_date date NOT NULL COMMENT 预约日期, start_time time NOT NULL COMMENT 开始时间如09:00, end_time time NOT NULL COMMENT 结束时间如10:00, amount decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT 订单金额, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 0-待支付 1-已支付 2-已取消 3-已完成 4-已退款, create_time datetime DEFAULT NULL COMMENT 下单时间, PRIMARY KEY (id), KEY idx_room_date (room_id, reserve_date), KEY idx_user (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT预约订单表; -- 充值记录表 CREATE TABLE recharge_record ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL, amount decimal(10,2) NOT NULL, pay_method varchar(20) DEFAULT wechat, create_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT充值记录表;设计理由要讲清楚。用户表里的wx_openid承担了账号职责微信小程序没有传统密码注册用户第一次登录时后端通过wx.login换来的code向微信服务器换openid再把它当作唯一身份。加UNIQUE KEY uk_openid防止同一微信号刷出多个账号。琴房表的status是停用或维修状态不是动态空闲状态——琴房是否有空时段要查预约表才能确定。预约表是绝对核心reserve_date、start_time、end_time必须拆开存否则后面冲突查询没法写。索引idx_room_date直接服务时段冲突判断几千行数据时没有这个索引会明显变慢。充值记录不是必须有但几乎所有琴房毕设都带上因为“虚拟余额”模式比真实微信支付简单得多用户先充值预约时从余额扣不需要商户号不需要支付回调答辩演示完全够用。源码包如果只有三张表没有余额大概率就是没做扣款闭环。2.3 后端接口清单和统一返回体让小程序端少写一套if-else数据库建好后接口不需要多完整琴房系统后端接口一般15个上下。常见这一组模块接口方法作用登录/api/user/loginPOST微信code换openid返回token用户/api/user/infoGET获取昵称、余额、角色琴房/api/room/listGET分页查询琴房列表琴房/api/room/detailGET琴房详情和当日占用时段预约/api/reserve/addPOST提交预约订单预约/api/reserve/listGET我的预约列表预约/api/reserve/cancelPOST取消未开始的预约余额/api/recharge/addPOST模拟充值入账管理/api/admin/room/savePOST新增/编辑琴房管理/api/admin/room/deletePOST删除琴房管理/api/admin/reserve/listGET管理员查全部预约后端返回体统一成下面这种结构小程序端处理起来才省心{ code: 0, msg: success, data: {} }code为0表示成功非零值携带错误文案。不要用HTTP状态码承载业务错误比如400、500wx.request在非2xx状态时走的是fail回调业务错误统一走success回调再判断code页面代码能少一半嵌套。这套约定就是前后端的最小成本契约。后端如果没有统一返回体类自己封装一个成本很低。另一件常被忽略的事是token校验很多毕设包在登录接口里返回了token但后续接口根本没实现拦截器前端把token带上了也没人校验。拿到源码先去WebMvcConfigurer里看有没有注册拦截器没有就自己补上否则换一个用户就能互相查订单答辩演示会十分出戏。3. 从.rar压缩包到本地跑通源码、数据库、说明文档的完整配置流程3.1 解压.rar之后压缩包里的内容各自扮演什么角色多数交付包的目录长这样琴房管理系统/ ├── frontend微信小程序源码用微信开发者工具打开 │ ├── app.js │ ├── app.json │ ├── pages/ │ │ ├── index/ │ │ ├── room/ │ │ ├── reserve/ │ │ └── user/ │ ├── utils/ │ └── project.config.json ├── backendJava后端工程IDEA直接打开 │ ├── pom.xml │ ├── src/main/java/com/example/qinfang/ │ ├── src/main/resources/ │ │ ├── application.yml │ │ └── mapper/xxx.xml ├── databaseSQL脚本文件 │ └── qinfang.sql ├── 说明文档.doc └── 演示视频.mp4先别急着打开演示视频。按顺序做三件事确认Java版本、确认MySQL版本、确认SQL脚本能否被当前MySQL执行。这三个变量和源码环境不一致后面代码再对也跑不起来。打开说明文档重点看作者写的环境版本JDK 1.8还是17MySQL 5.7还是8.0Spring Boot 2.x还是3.x。见过最多的翻车现场是拿MySQL 8.0去跑按MySQL 5.7语法写的脚本字符集设置特殊一点就报错反过来也一样。省事做法是装一个与文档同版本的MySQL单机实例不要拿公司或实验室已有环境的库硬套。3.2 后端本地启动JDK、MySQL、IDEA到application.yml的连贯配置后端启动链条不长装JDK → 导入IDEA → 建库导入SQL脚本 → 改配置 → 启动服务。最容易出错的就在改配置。我一般先把application.yml里用户名、密码、库名填对再一次性启动server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/qinfang?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: 123456 hikari: minimum-idle: 5 maximum-pool-size: 15 connection-timeout: 30000 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.qinfang.entity wx: appid: wx1234567890abcdef secret: abcdefghijklmnopqrstuvwxyz123456参数说明url这一行有三个关键参数。useUnicodetrue和characterEncodingutf8解决后续中文乱码serverTimezoneAsia/Shanghai解决时间差8小时这三个在MySQL 8.0驱动下基本是必须项少一个后面要花两小时查一个看似无解的问题。useSSLfalse去掉无意义的安全警告。driver-class-name用com.mysql.cj.jdbc.Driver这是MySQL 8.0驱动对应的类名老项目里写com.mysql.jdbc.Driver在8.0下会提示已过时但仍能跑。HikariCP四个参数是常见默认值。minimum-idle不要设成0毕设场景频繁起停服务空闲连接被回收后第一次请求会明显慢。maximum-pool-size本地开发15足够部署到服务器时结合MySQL的max_connections再调别超过数据库连接数的三分之一。connection-timeout默认30秒本地数据库连不上时不到30秒就会抛异常这个参数更多对生产有意义。wx.appid和wx.secret可以先用占位符。登录和充值接口会用到但如果暂时不跑完整登录流程先留空不影响普通接口联调。等到3.3节配小程序端时再把微信公众平台里的真实AppID填回来。配置改完在IDEA里直接运行启动类。日志最后出现“Started Application in xx seconds”算成功。如果卡在Mapper扫描检查启动类上有没有MapperScan(com.example.qinfang.mapper)或者每个Mapper接口加Mapper两者存在其一即可。3.3 小程序端导入AppID、baseUrl、真机预览的三角关系后端起来后前端配置简单很多。微信开发者工具导入frontend目录填入自己的测试号AppID或者选“测试号”也能预览。有一个细节必须改小程序源码里的请求地址写的是开发者的IP通常是http://localhost:8080。真机预览时localhost指向的是手机自己所以要用电脑局域网IP// utils/config.js module.exports { baseUrl: http://192.168.1.100:8080/api }改完baseUrl还要在微信开发者工具“详情 → 本地设置”勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”。这个勾选只对开发调试有效。真机预览要保证手机和电脑连同一个Wi-Fi并确认Windows防火墙允许Java进程监听8080端口对外访问。如果列表还是空白先去Console面板看有没有“不在以下合法域名列表中”的红字有就说明没勾选不校验合法域名或baseUrl写错。再看Network面板里请求返回多少请求返回400或500把后端控制台异常栈贴出来查多数是Mapper XML里查询的列名和数据库脚本建出来的列名对不上。MyBatis默认开启驼峰映射数据库的price_per_hour映射到实体pricePerHour如果实体字段写的是price查询结果会静默变成null。这类问题后端不报错、前端显示0排查最快的方式是在日志里直接打印查询结果。4. 预约流程的核心代码改造冲突检测、订单状态机和小程序端落单4.1 预约冲突检测为什么跨时段判断远比等值判断容易漏琴房预约最核心的业务规则一个琴房同一时间段只能被一个人预约。新手最容易写成“查一下有没有相同开始时间和结束时间”但用户预约09:30到10:30时系统已存在09:00到10:00的订单按等值判断查不出来结果就是重复预约。正确判断重叠区间的条件新预约的开始时间小于已存在的结束时间且新预约的结束时间大于已存在的开始时间。MyBatis的Mapper XML里对应一段不算复杂的SQLselect idselectExistReserve resultTypecom.example.qinfang.entity.Reservation SELECT id, user_id, room_id, reserve_date, start_time, end_time, status FROM reservation WHERE room_id #{roomId} AND reserve_date #{reserveDate} AND status IN (0, 1) AND start_time lt; #{endTime} AND end_time gt; #{startTime} LIMIT 1 /selectXML里的小于号和大于号必须转义成lt;和gt;直接写会被当成XML标签开头导致启动报错。状态过滤条件status IN (0, 1)表示待支付和已支付的预约都占着时间已取消订单不占时间已完成历史记录也不影响未来时段。业务方法里配合事务再叠加一次校验防止两个用户同时提交万事冲突数据写入Transactional public ReserveResult createReserve(ReserveRequest request, Long userId) { // 1. 查该琴房该日期是否存在时间重叠的预约 Reservation existed reservationMapper.selectExistReserve( request.getRoomId(), request.getReserveDate(), request.getStartTime(), request.getEndTime()); if (existed ! null) { throw new BusinessException(该时段已被预约请换个时间); } // 2. 查余额够不够 User user userMapper.selectById(userId); BigDecimal hours calcHours(request.getStartTime(), request.getEndTime()); BigDecimal amount roomMapper.selectById(request.getRoomId()) .getPricePerHour().multiply(hours); if (user.getBalance().compareTo(amount) 0) { throw new BusinessException(余额不足请先充值); } // 3. 插入订单并扣减余额 Reservation reservation new Reservation(); reservation.setUserId(userId); reservation.setRoomId(request.getRoomId()); reservation.setReserveDate(request.getReserveDate()); reservation.setStartTime(request.getStartTime()); reservation.setEndTime(request.getEndTime()); reservation.setAmount(amount); reservation.setStatus(0); reservationMapper.insert(reservation); userMapper.deductBalance(userId, amount); return ReserveResult.of(reservation.getId()); }逻辑说明方法加Transactional从查冲突到扣款插单任何一步抛异常都会回滚避免出现“订单没插进去但余额扣了”或“余额扣了但订单重复”。校验余额时用compareTo而不是subtract后判断是否小于0后者会多一次BigDecimal对象创建这在金额计算里属于不必要的操作。这个方案在极高并发下仍有小概率两个请求同时通过校验。答辩被问如何防止超卖可以回答在reservation表加唯一索引兜底或者用SELECT ... FOR UPDATE锁行。真实项目更推荐加一个room_date字段并建唯一索引包含琴房ID、日期、开始时间三列让数据库做最后一道防线。时间段生成的另一处细节是统一单位。后端接口返回startTime09:00、endTime10:00时前端生成时间段列表和后端解析都不要用字符串截取比较。Java里用LocalTime.parse转成时间对象再比较前端也统一24小时制避免“09:00”和“9:00”这两个相同时间不同字符串的坑。4.2 订单状态机取消、失效、退款的状态流转设计预约订单的status字段决定取消、支付、管理端操作如何流转。常规状态机是四态循环0-待支付 → 1-已支付 → 3-已完成用户主动取消走0或1 → 2退款从1 → 4。最容易设计乱的就是“取消”这个动作。铁律是未开始的预约可以取消已开始或已完成的不允许取消。合法性判断可以简化为“当前时间小于预约的开始时间”但start_time不包含日期必须把reserve_date拼成完整的LocalDateTime再比较public void cancelReserve(Long reserveId, Long userId) { Reservation reservation reservationMapper.selectByIdForUpdate(reserveId); if (reservation null || !reservation.getUserId().equals(userId) || !Arrays.asList(0, 1).contains(reservation.getStatus())) { throw new BusinessException(订单状态不允许取消); } // reserve_date与start_time拼成完整时间再比较 LocalDateTime reserveStart LocalDateTime.of( reservation.getReserveDate(), reservation.getStartTime().toLocalTime()); if (LocalDateTime.now().isAfter(reserveStart)) { throw new BusinessException(预约已经开始无法取消); } // 先记住原状态再改成已取消 int oldStatus reservation.getStatus(); reservation.setStatus(2); reservationMapper.updateById(reservation); // 原状态是已支付才退款 if (oldStatus 1) { userMapper.addBalance(reservation.getUserId(), reservation.getAmount()); } }两个要点selectByIdForUpdate会把该记录行锁住防止同一用户连点多次取消导致退款重复执行退款判断必须用改动前保存的oldStatus如果先setStatus(2)再判断getStatus() 1判断结果永远是false退款永远不会发生。代码里这个顺序错了功能会在答辩当天翻车。待支付订单一直不付款会一直占着琴房时段。成熟做法是定时任务扫表Scheduled(fixedDelay 60000)每分钟把创建超15分钟且状态为0的订单改成已取消。毕设不一定要求做定时任务但至少要给管理端一个手动将过期订单置为取消的按钮。答辩时主动提这个设计比被动说没考虑过要稳很多。4.3 小程序端预约提交从选琴房、选时段到收到响应的完整走查小程序预约页面交互一般分三步选琴房、选日期和时段、确认提交。页面数据源是琴房列表接口和当日可用时段接口。技术难点在时间段生成——毕设包里常常写死一个字符串数组比如[09:00,10:00,11:00]真实需求很难这么简单。更可持续的做法是后端给“起始时间时长分钟数”前端循环生成时段列表并把已占用的时段标记为不可预约。提交订单的核心代码// pages/reserve/submit.js const config require(../../utils/config.js); Page({ data: { roomId: null, date: , startTime: , endTime: , amount: 0 }, submitReserve() { const { roomId, date, startTime, endTime } this.data; if (!roomId || !date || !startTime || !endTime) { wx.showToast({ title: 请补全预约信息, icon: none }); return; } const token wx.getStorageSync(token); wx.request({ url: config.baseUrl /reserve/add, method: POST, header: { Authorization: token }, data: { roomId, date, startTime, endTime }, success: (res) { const body res.data; if (body.code 0) { wx.showToast({ title: 预约成功, icon: success }); wx.navigateTo({ url: /pages/order/order }); } else { wx.showToast({ title: body.msg || 预约失败, icon: none }); } }, fail: () { wx.showToast({ title: 网络异常, icon: none }); } }); } });参数说明header里的Authorization是登录后存入Storage的token每次请求带给后端后端拦截器解析出userId实现“用户只能操作自己的订单”。data中所有字段必须在data()里先声明否则this.data.roomId永远是undefined点击提交永远停在“请补全预约信息”。更完整一点的体验是用户选了时段后临时想改页面加一个“重新选择”按钮重置date、startTime、endTime即可琴房不用重新选。后端返回“余额不足”或“时段被占用”时前端不应只弹一个toast最好重新拉取琴房详情接口把新被占的时段用disabled样式置灰这是答辩时老师常追问的交互细节。5. 常见问题和避坑排查启动失败、白屏、乱码的高频事故5.1 后端启动报错端口占用、Maven依赖超时、驱动类找不到现象IDEA启动日志最后出现APPLICATION FAILED TO START提示Port 8080 was already in use。原因本机某个软件或上一次没关掉的Java进程占了8080。解决先执行netstat -ano | findstr 8080找到PID在任务管理器结束进程或改server.port: 8081。毕设阶段改端口更省事但小程序端baseUrl要同步改。现象Maven导入依赖时一直卡在Downloading from central然后超时。原因默认的中央仓库下载速度很不稳定超时很常见。解决在~/.m2/settings.xml里配置镜像仓库再把IDEA的Maven设置指向这个settings文件依赖下载速度会明显改善。现象启动后抛ClassNotFoundException: com.mysql.cj.jdbc.Driver或日志提示Loading class com.mysql.jdbc.Driver... deprecated。原因pom.xml里MySQL驱动版本过老或依赖缺失。解决Spring Boot 2.7左右的项目使用mysql-connector-j8.0.33并保持driver-class-name和artifactId匹配。5.2 小程序白屏或请求卡死域名校验、baseUrl指向localhost、导航栏安全区现象Console报“不在以下request合法域名列表中”。原因微信平台限制request只能访问配置过的HTTPS域名本地开发没有合法域名。解决在开发者工具“详情 → 本地设置”勾选“不校验合法域名”这设置只管开发调试。现象开发者工具里请求能通真机预览不通。原因baseUrl写的是localhost或某台开发机IP手机访问不到。解决改成电脑当前局域网IP例如http://192.168.1.100:8080/api并保证手机与电脑在同一Wi-Fi。不在同一子网时还要检查Windows防火墙是否放行了8080。现象页面加载出来但顶部内容被刘海屏挡住。原因项目用了navigationStyle: custom但没适配安全区。解决// 获取状态栏和安全区信息动态计算顶部内边距 const info wx.getWindowInfo(); const navHeight 44 info.statusBarHeight; const topPadding (info.safeArea.top || info.statusBarHeight) px; this.setData({ topPadding });页面根节点加padding-top: {{topPadding}}px。注意wx.getWindowInfo在基础库2.20.0以上才可用旧项目用getSystemInfoSync兼容。默认导航栏不需要处理只有自定义导航栏才需要。5.3 中文乱码和时间差8小时字符集、时区与表编码的三处配置现象后端返回中文正常但数据库存进去变成??。原因表结构和连接串字符集不一致典型是表用了latin1而连接串没有characterEncodingutf8。解决建库时显式指定字符集。CREATE DATABASE qinfang DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;application.yml的url里加characterEncodingutf8。已建错的库可以执行ALTER TABLE reservation CONVERT TO CHARACTER SET utf8mb4;补救但已经存坏的乱码不会恢复所以要先改配置再继续开发。现象数据库时间比北京少8小时。原因Java默认时区与MySQL驱动时区不一致。解决JDBC url加serverTimezoneAsia/Shanghai同时把jackson时区设为GMT8。只配一处后端返回给前端的JSON字符串仍可能带错偏移量两处配置要对齐。5.4 说明文档与演示视频对不上源码按文档跑不通的典型现场现象按说明文档写的MySQL账号、库名导入SQL脚本后启动后端仍然连不上库仔细比对发现文档里的URL和application.yml里的实际库名完全不同。原因交付包里的说明文档、演示视频和源码经常不是同一时间同一机器上做的文档可能是早期模板。解决一切以源码和SQL脚本为准文档只作参考。先打开SQL脚本看建库名再打开application.yml看连接串把这两处弄一致。演示视频的作用是让你知道最终效果长什么样而不是教你怎么配环境。注意同一套交付包里的三个产物未必在同一时刻生成看到三者矛盾时源码和SQL脚本的优先级最高。5.5 HikariCP连接池参数乱调死等与连接爆掉的两种异常表现现象后端启动后第一次访问接口卡住20秒然后报Connection is not available, request timed out。原因minimum-idle设成0后连接池里没有空闲连接第一次请求要新建连接恰好MySQL慢一点等待就超过了connection-timeout。解决本地开发把minimum-idle设成5连接超时保持默认30秒不要为了追求“快速失败”把它改成1秒。现象前端并发点了几次预约后端日志出现Too many connections。原因maximum-pool-size设得太夸张比如500而MySQL默认max_connections只有151连接池把所有连接都建出来把数据库压垮了。解决本地把maximum-pool-size控制在20以内生产环境先查show variables like max_connections再按总连接数的五分之一到三分之一设置。连接池默认参数就是一个风险很低的组合真不需要把它当玄学调来调去。遇到连接不够用先看show processlist确认是不是真的不够再决定改参数不要一上来就放大连接数。6. 答辩前的最后一轮自测用边界用例把琴房预约系统验一遍整套功能跑通之后答辩前最值得做的不是加新功能而是拿几个边界用例验证核心逻辑。第一开两个开发者工具或两个浏览器窗口同时提交同一个琴房同一时段看是否只有一个成功这验证冲突检测的有效性。第二在凌晨零点前后连续操作看跨天日期处理是否正确很多毕设把日期当字符串拼接凌晨之后预约时间全错。第三把余额扣到接近零再下单看后端是否拒绝欠费预约。这三个用例全过预约闭环基本没有大问题。另一个容易忽视的自测点是取消后退费。先用余额下单再取消看余额是否回到原值然后取消一个待支付订单看余额是否被错误增加。这两个小操作比完整演示一遍预约更能展示对业务的理解。顺便检查一下“可选时段”在后端被占用后前端是否更新了可预约列表——这个联动经常被写成只弹提示不刷新页面的半成品。我自己的一个习惯是给小程序端留一个“环境切换”入口平时开发指到测试IP答辩现场指到演示IP避免临场改代码。把这个细节写进说明文档答辩当天会顺很多。一个技术方案能不能被信任往往就体现在这些边界处理上。希望这份启动步骤、参数说明和踩坑记录能帮到你也帮你少熬几个晚上。本文还有配套的精品资源点击获取
返回列表