把“语言考试信息报名系统”从需求到上线完整过了一遍,技术栈就是SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0这一套。报名系统听起来简单,无非是几张列表页、一个报名按钮、一个后台管理,但真正跑起来要解决的问题一点都不少:场次怎么排、考位怎么扣、重复提交怎么防、考生级别怎么审核、报表怎么导出、前后端权限怎么对得上。这套源码连同部署文档我已经一起整理了,下面把整个项目从设计、开发到部署、排错的过程拆开来说,踩过的坑都会点到。适合两类人看:一类是刚学完SpringBoot和Vue、想拿一个完整项目练手的同学,另一类是公司要临时接报名类需求、想快速落地又少走弯路的开发者。
1. 项目整体设计与技术选型思路
1.1 为什么选SpringBoot2+Vue3而不是其他组合
选这套组合,首先考虑的是交付稳定性。SpringBoot2目前仍然是企业里存量最多的版本,第三方组件适配资料丰富,很多项目组现有的中间件、监控平台都对它很熟,接手成本最低。团队里如果还有一批人守着Spring Boot 1.5的老项目,切换过来也几乎没学习障碍。
Vue3这边我当时对比过Vue2,最终还是定了Vue3。原因很实际:组合式API把逻辑聚合能力提升了一个量级。报名系统的表单校验、倒计时、步骤条、列表筛选这些逻辑一旦复杂起来,Options API里会散落在data、methods、computed、watch各个角落,而composables可以按业务维度把相关状态和方法收在一个函数里。页面里引用三个组合函数,代码立刻清爽。
ORM选型上,我认真比较过Spring Data JPA和MyBatis-Plus。JPA在单表CRUD和实体关联上确实省事,但报名系统有大量动态条件列表查询、多表关联统计、XML里写复杂SQL的场景,MyBatis-Plus的QueryWrapper和自定义Mapper XML混合写法明显更顺手。JPA的懒加载和N+1问题在这种报表型页面上也很容易翻车,MyBatis-Plus至少能明确看到每条SQL在做什么。
1.2 报名系统的核心业务模块拆解
考试报名信息系统的核心用户其实只有两类:管理员和考生,但权限边界必须分清楚。管理员这边负责场次管理、语种维护、报名记录审核、考位余量查看、报名数据导出。考生这边负责注册登录、浏览可报名场次、提交报名、取消报名、查看审核状态。不要小看这个看起来简单的模型,它把“资源管理+预约申请+审核流程”这三个最常见的后台业务全部覆盖了。
所以我在拆模块时完全按资源领域划分:用户模块、场次模块、报名模块、审核模块、统计导出模块。用户模块管账号、角色、资料;场次模块管考试时间、地点、语种、考位总数;报名模块管报名记录的增删查和状态流转;审核模块管资格核验与状态回写;统计导出模块管报名人数汇总和Excel导出。这样划分的好处是将来扩展特别方便,比如给场次模块加一个价格字段和支付回调,整个系统就能变成收费考试报名平台;把场次换成课程,就变成了选课系统。
1.3 前后端分离的项目结构
项目工程上分成server和web两个目录。server是Maven多模块结构,按common、entity、mapper、service、controller分层;web是用Vite创建的Vue3工程,按api、views、components、router、store、utils组织。重点说两个细节:
第一,前后端分离不等于微服务。这个项目就是两个工程、一套HTTP约定,开发时由Vite代理转发到后端端口,部署时由Nginx统一入口反向代理到SpringBoot,能省掉大量跨域和网络配置的麻烦。
第二,entity和VO不要混用。数据库实体类只放持久层字段,返回给前端的对象单独建VO类,字段按页面需要裁剪。比如用户表里存了密码哈希,VO里绝对不能出现这个字段;报名列表页面需要显示考生姓名、场次名称,就在VO里冗余这两个展示字段,不要每次让前端自己联表。接口返回值统一用Result
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据库设计与后端接口实现
2.1 MySQL8.0的表结构设计思路
MySQL8.0安装后第一件事就是确认字符集。不要用默认的latin1或utf8mb3,报名表里可能出现考生姓名、考试语种、特殊备注这种含emoji或生僻字的场景,必须用utf8mb4。Linux下修改my.cnf,加上character-set-server=utf8mb4和collation-server=u
