☰
SpringBoot+MyBatis-Plus构建大学生体质测试管理系统设计与实现
2026/10/10 18:24:56 网站建设 项目流程

1. 先搞清楚这个系统到底在解决什么问题

每年一到大三体测季,体育学院和教务处的老师就开始头疼。纸质表格一张张收集,Excel汇总一层层合并,成绩录入错误率居高不下,学生想查个成绩只能等到期末看总表。更麻烦的是,免测申请、缓测申请、成绩复核这些流程全靠线下跑腿,一个学生因为体测成绩和奖学金挂钩,会反反复复找不同老师签字确认。

这类基于SpringBoot的大学生体质测试管理系统,本质上是把“国家学生体质健康标准”的测试-录入-计算-统计-反馈全流程搬到线上。我在做这个题目前先做了业务调研,发现它不只是给老师一个录成绩的后台,而是涉及教务处管理员、体育教师、辅导员、学生四类角色的协同平台。系统核心要处理的不是简单的增删改查,而是“每学年一次体测计划-按班级排期-按项目采集成绩-按性别年龄分组计算得分-自动评定等级-输出班级/年级统计报表-异常体质预警”这样一条完整的业务链。

这个题目特别适合作为SpringBoot方向的项目实战或者毕业设计,因为它覆盖面恰到好处:技术上覆盖了权限管理、数据导入、流程审批、统计报表、微信通知等常见企业级功能;业务上又有明确的标准规则(男女生测试项目不同、年级分组不同、评分标准不同),能让代码写出层次感而不是一马平川的CRUD。如果你的目标是短时间内掌握SpringBoot项目的完整开发套路,或者需要一份拿得出手的毕业设计,这个题目都值得认真做一遍。

1.1 体测管理业务的真实流程

先把这个系统的业务全景画清楚。按照国家体质健康标准,大学生体测项目分为两类:男生测身高、体重、肺活量、50米跑、坐位体前屈、立定跳远、1000米跑、引体向上;女生测身高、体重、肺活量、50米跑、坐位体前屈、立定跳远、800米跑、仰卧起坐。每个项目都有对应的权重系数,总分是各项目得分乘权重后累加,再根据总分评定优秀、良好、及格、不及格四个等级。

这里有个容易被忽略的细节:评分标准不是全校统一一张表,而是按“年级分组”和“性别”划分。大学阶段通常分为大一、大二、大三、大四四个年级段,每段男女各一套标准,也就是说系统里至少要有8套评分标准数据。如果再做细一点,部分学校还会区分“室内项目”和“室外项目”的测试批次,室内项目由仪器自动采集,室外项目由教师手工录入。这些业务细节直接决定了数据库表怎么设计、成绩计算模块怎么写,我建议动手前先花一周时间把规则吃透。

1.2 四类用户到底想要什么

我在初期需求分析时列了一个表格,做完后发现系统的功能边界一下子清楚了:

用户角色核心诉求对应系统功能
教务处管理员一键创建体测计划、查看全校达标率计划管理、统计报表、数据大屏
体育教师快速录入全班成绩、处理免测申请成绩批量导入、审批中心
辅导员掌握本班体测情况、督促未测学生班级视图、未测名单导出
学生查看个人成绩、提交免测/缓测申请成绩查询、在线申请

很多人在设计系统时容易只盯着“成绩管理”这一个环节,结果做出来的东西就是个Excel在线化改版,答辩时被老师问“你的系统解决了什么线下解决不了的问题”一下就卡住了。实际上,免测审批的线上化流转、体测成绩自动达标判断、历年成绩趋势对比这几个点,才是这个系统区别于普通管理系统的价值所在。做之前把这些想清楚,后面的表结构设计和代码实现都会顺很多。

2. 技术栈选型:用最稳的方案撑起论文和答辩

SpringBoot项目的技术选型有个原则:不求新,但求稳;不求多,但求够用。不少同学喜欢堆技术,把Redis、RabbitMQ、ElasticSearch全塞进去,结果项目跑不通、论文写不深,答辩时一问三不知。我建议按下面这套组合来做,既主流又不失技术含量。

2.1 SpringBoot版本选择与配置要点

版本这块推荐用SpringBoot 2.7.x。为什么不推荐3.x?因为3.0开始基于Jakarta EE规范,很多老教程和老项目代码不能直接复用,网上搜到的问题解决方案大多是针对2.x的。2.7.x是目前社区资料最丰富、踩坑率最低的版本,对毕业设计和技术学习都是稳妥选择。

关于SpringBoot,我多说几句它背后那个核心机制——自动装配。很多面试题和论文理论部分都会考这个。SpringBoot启动类上的@SpringBootApplication注解,本质上是组合了@Configuration、@EnableAutoConfiguration和@ComponentScan。其中@EnableAutoConfiguration通过spring.factories(2.7及以前)或AutoConfiguration.imports(3.0以后)文件加载所有候选自动配置类,再通过@ConditionalOnClass、@ConditionalOnMissingBean等条件注解按需生效。比如引入了spring-boot-starter-web依赖,DispatcherServletAutoConfiguration就会在classpath中存在DispatcherServlet类时自动配置SpringMVC。理解了这个原理,你在写论文“技术选型”那一章时就能写出深度,而不是干巴巴写一句“SpringBoot简化了配置”。

配置上几个容易忽略的服务端参数,我直接给出来:

server: port: 8080 servlet: context-path: / encoding: charset: UTF-8 force: true spring: datasource: url: jdbc:mysql://localhost:3306/fitness_test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: yourpassword # 阿里的Druid或HikariCP连接池都可以,2.7默认是HikariCP,不用额外引入 servlet: multipart: max-file-size: 20MB max-request-size: 50MB jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mybatis-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: auto

map-underscore-to-camel-case这个配置务必要开,否则数据库字段create_time映射不到实体类的createTime属性上,排查起来很隐蔽。

2.2 持久层框架为什么选MyBatis-Plus

这个题目里SpringBoot + MyBatis是绝配,但建议直接上MyBatis-Plus而非原生MyBatis。理由很简单:MyBatis-Plus提供了BaseMapper泛型接口,单表CRUD根本不用写SQL和XML,内置的分页插件PaginationInnerInterceptor一条配置就能搞定分页查询,这些能把开发周期缩短一半以上,把节省的时间投入到核心业务逻辑上。

MyBatis-Plus有个很实用的功能是条件构造器LambdaQueryWrapper,查询某个班级某次体测计划的所有成绩时,代码非常简洁:

LambdaQueryWrapper<FitnessResult> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(FitnessResult::getPlanId, planId) .eq(FitnessResult::getStudentId, studentId); FitnessResult result = fitnessResultMapper.selectOne(wrapper);

如果你需要在论文里体现技术深度,可以写MyBatis-Plus的分页插件本质是对MyBatis执行器Executor的拦截,通过@Intercepts注解声明Signature来拦截Executor.query方法,在SQL执行前通过Page对象拼接分页参数。这里就体现了SpringBoot+MyBatis整合时“插件机制”的扩展思路,比单纯写CRUD更有讲头。

2.3 前端与打包部署:Vue构建产物放进SpringBoot

前端用Vue 3 + Element Plus,这个组合上手快、组件全,做后台管理类系统效率很高。关键问题是Vue工程和SpringBoot工程怎么配合。开发阶段可以用前后端分离模式:Vue跑在5173端口,通过开发服务器的proxy代理把/api开头的请求转发到SpringBoot的8080端口。打包部署阶段就不一样了,推荐把Vue构建产物放进SpringBoot的src/main/resources/static目录,这样最终打出来的jar包里静态资源和后端接口在同一个端口下,部署时只需跑一个jar包,省去配置Nginx的麻烦。

我在做的时候踩过一个坑:Vue打包后的默认路径是/,如果SpringBoot接口的context-path配置成了/api,就会出现页面能打开但接口401或404的诡异问题。解决办法是统一约定接口前缀,前后端都叫/api,Vue的axios请求路径写成全路径相对路径,来访地址直接指向请求的URL地址,然后SpringBoot配置里不做额外的context-path设置。

还有一个经典的坑是Vue路由模式。如果使用history模式,页面刷新时SpringBoot会去尝试匹配对应的路径返回404,而hash模式没有这个问题。项目规模不大时建议直接用hash模式,省心;如果想用history模式,需要在SpringBoot里配置资源映射或者在Controller里添加一个转发逻辑,处理前端路由时返回index.html。

2.4 权限框架与缓存选型

权限认证是这个项目绕不开的模块,也是论文里的一个加分点。这里有两个选择:Spring Security和Sa-Token。考虑到项目复杂度不高,我推荐Sa-Token,它是一个轻量级的Java权限认证框架,API设计对新手极其友好。登录成功后一句StpUtil.login(userId)就完成了登录会话,校验权限用@SaCheckPermission("fitness:result:add")注解搞定,远比Spring Security的过滤器链和配置类好理解。

缓存方面引入Redis用来缓存体测标准数据和登录token,这里能和白月光的优化思路扣上。体测评分标准是读多写少的典型数据,每次成绩计算都去查库显然不经济。可以在标准数据变更时清缓存,查询时优先从Redis取,取不到再查库并回填。同时Sa-Token支持把session存储到Redis中,这样应用重启后用户的登录状态不会丢失,这也是一处可以在论文里讲清楚的技术细节。

Redis不是必需项,但如果项目里没有Redis,论文的“系统优化”章节会显得单薄。我的建议是加上,而且要在论文里明确写清楚缓存了什么、缓存策略是什么、为什么这些数据适合缓存,而不是笼统写一句“引入了Redis”。

3. 数据库设计:一张成绩表藏了哪些门道

表结构设计是整个项目的地基,地基没打对,后期写业务代码会处处难受。我这个项目一共设计了8张核心表,下面把关键设计思路展开讲,你直接仿照这个思路来做就行。

3.1 核心表结构一览

先说用户体系。这里用一个sys_user表统一存储账号信息,再分学生表和教师表存各自的业务属性。为什么不给学生和教师各建一张独立的登录表?因为两个角色都有username、password、status这些共同字段,如果分开设计会有大量重复逻辑。合理的做法是:

  • sys_user:id、username、password(BCrypt加密)、real_name、role(1管理员 2教师 3学生)、status
  • student_info:id、user_id、student_no、class_id、gender、birthday、grade、enrollment_year、physical_condition
  • teacher_info:id、user_id、teacher_no、department

然后是业务表:

  • fitness_plan:体测计划表,一次体测活动的元信息,字段有academic_year、semester、plan_name、start_date、end_date、status(0草稿 1进行中 2已结束)、create_by
  • fitness_project:测试项目表,字段有project_code、project_name、unit、weight(权重系数,如肺活量权重0.15)、applicable_gender(1男2女3通用)
  • fitness_standard:评分标准表,字段有project_id、gender、grade_group(一年级组/二年级组等)、level(90/80/60等分数档位)、excellent_line、good_line、pass_line,或者直接定义分段规则
  • fitness_result:体测成绩记录表,这个表是核心,后面单独讲
  • exemption_apply:免测/缓测申请表,字段有student_id、plan_id、apply_type(1免测 2缓测)、reason、certificate_url、teacher_audit_status、admin_audit_status、final_status
  • health_alert:健康预警表,记录BMI异常、肺活量偏低等需要关注的学生

3.2 成绩表设计的三个关键决策

第一,成绩表的粒度。一次体测计划下,一个学生会有多个项目的成绩。这里有两种设计方案:一是“一次体测一条记录”,用json串存所有项目成绩;二是“一个学生一个项目一条记录”。我强烈推荐后者,因为成绩计算、单项统计分析都需要按项目维度来查数据,如果存在json里,要查询单项成绩时还得解析json,性能和代码可读性都很差。

第二,标准快照字段。这是这个项目最重要的一个设计细节。体测评分标准不是永远不变的,学校可能每年微调,国家也可能几年更新一版标准。如果成绩表只存了分数和原始测试数据,将来标准更新后,历史成绩的“是否达标”就没办法追溯了。所以fitness_result表中除了存score(换算后的标准分)外,还要存一个standard_snapshot字段,把当时使用的评分标准的版本号和关键规则序列化为JSON保存下来。这样无论标准怎么改,历史成绩的评定逻辑永远可以复现。论文里把这个设计写出来,是个实打实的加分项。

第三,状态字段。成绩录入不是一次完成的,要设计状态流转。fitness_result里加一个status字段:0待提交、1已提交待审核、2已审核通过。教师录入成绩时可以先保存在草稿状态,确认无误后再提交,管理员复核后正式生效。这样“已生效”的成绩才能进入统计报表,避免半成品数据污染统计结果。

fitness_result表核心字段示意:

CREATE TABLE fitness_result ( id BIGINT PRIMARY KEY AUTO_INCREMENT, plan_id BIGINT NOT NULL COMMENT '体测计划ID', student_id BIGINT NOT NULL COMMENT '学生ID', project_id BIGINT NOT NULL COMMENT '测试项目ID', test_value VARCHAR(50) COMMENT '原始测试值,如8.5(秒)、210(厘米)', score DECIMAL(5,2) COMMENT '该项目标准分', standard_snapshot TEXT COMMENT '评分标准快照JSON', status TINYINT DEFAULT 0 COMMENT '0草稿 1已提交 2已审核', evaluator_id BIGINT COMMENT '评分教师ID', create_time DATETIME, update_time DATETIME, UNIQUE KEY uk_plan_student_project (plan_id, student_id, project_id) ) COMMENT '体测成绩记录表';

3.3 免测申请状态机的设计

免测业务看起来只是“提交-审批”,实际上状态机要设计清楚才不会乱。我设计的流程是:

学生提交免测申请 -> 辅导员初审(确认学生确实无法参加测试)-> 体育教师复审(确认是否符合免测条件)-> 管理员终审通过/驳回。

四个状态:0草稿、1待初审、2待复审、3免测通过、4免测驳回、5缓测、6已撤销。

这里要注意“驳回”不是终态。学生补充材料后可以重新提交,所以exemption_apply表里要加一个reapply_count字段,用于记录重新提交次数,防止学生反复提交无意义的申请。同时,免测通过的学生,系统要自动为他生成对应体测项目的“免测通过”记录,成绩按“免测”标记处理,不参与评分统计但也不计入不及格名单。这个小细节很多人想不到,做出来后会显得你的业务逻辑很完整。

4. 核心模块实现:批量录入、达标判断、免测审批与统计报表

这一章是项目的技术重头戏。我把几个核心模块的实现思路和关键代码写出来,你可以直接用,边写边理解为什么这么做。

4.1 学生数据与成绩批量导入

没有批量导入功能的体测系统是一个不合格的系统。一个老师可能要录两三百个学生的成绩,如果让他一条条在表单里填,项目做完也不会有人用。批量导入的实现方案用EasyExcel,这是阿里开源的Excel解析工具,比Apache POI上手简单太多,内存占用也更优。

导入的流程是:上传Excel -> 解析(逐行读取)-> 逐条校验(学号是否存在、测试值是否在合理范围)-> 封装成实体类 -> 分批插入数据库。这里最关键的细节是校验不能放在插入数据库时做,否则会产生大量垃圾数据。我当时的实现是先用一个ImportErrorDTO收集每条数据的错误信息,等所有行解析校验完,如果有错误就返回一个错误报告Excel让老师下载查看,一行没错了才真正批量入库。

上传接口的核心代码思路:

@PostMapping("/import") public Result<String> importResult(@RequestParam("file") MultipartFile file, @RequestParam("planId") Long planId) { // 1. 校验文件格式 String originalFilename = file.getOriginalFilename(); if (!originalFilename.endsWith(".xlsx") && !originalFilename.endsWith(".xls")) { return Result.error("请上传Excel格式的文件"); } // 2. 使用EasyExcel解析,同步表头映射 EasyExcel.read(file.getInputStream(), ResultImportDTO.class, new ResultDataListener(resultService, planId)) .sheet() .doRead(); return Result.success("导入完成,共导入" + resultService.getImportCount() + "条数据"); }

用监听器模式的好处是EasyExcel每解析一行数据都会回调invoke方法,可以在回调里做逐行校验、汇总错误、最终批量插入,避免一次性把整个Excel读进内存导致OOM。这里在ResultDataListener的doAfterAllAnalysed方法里做最终统计和批量落库,是很标准的写法。

4.2 成绩自动达标判断与标准匹配

拿到一个学生的测试原始值之后,要判断它对应哪个评分等级,这就涉及到“标准匹配”。比如男生1000米跑,大一大二学生的及格标准是4分32秒,大三大四是4分45秒。同样一个成绩,放在不同年级标准下,及格状态完全不同。

我的实现方式是写一个ScoreEvaluator组件,根据学生信息去标准表中定位对应性别、对应年级组的fitness_standard数据,然后按项目类型分别计算。这里用到了策略模式,因为不同项目的判定方向不一样:跑步类是“时间越短越好”(测试值要小于等于标准线),立定跳远和引体向上是“数值越大越好”(测试值要大于等于标准线),肺活量和坐位体前屈则是数值越大越好但属于正向指标,处理逻辑也有细微差别。

策略接口的定义:

public interface ScoreEvaluatorStrategy { // 返回该项目的换算得分 BigDecimal evaluate(String testValue, FitnessStandard standard); // 判断该策略是否支持此项目 boolean supports(String projectCode); }

实现类示例,比如跑步类项目的策略逻辑:

@Component public class TimingProjectStrategy implements ScoreEvaluatorStrategy { @Override public BigDecimal evaluate(String testValue, FitnessStandard standard) { // testValue形如"4'32""或者"272"(秒数) int seconds = convertToSeconds(testValue); if (seconds <= standard.getExcellentLine()) { return new BigDecimal("90"); } else if (seconds <= standard.getGoodLine()) { return new BigDecimal("80"); } else if (seconds <= standard.getPassLine()) { return new BigDecimal("60"); } else { return new BigDecimal("50"); } } }

SpringBoot会自动把策略实现类注册到Map里,在业务层调用时根据项目代码找到对应的策略,这就是依赖注入的Map<String, Strategy>注入玩法。论文里写这个设计模式,能让答辩老师觉得你有设计意识,而不是在“堆代码”。

4.3 免测审批流程的状态流转

免测审批流程用状态机实现比用复杂的工作流引擎快得多。我当时的Controller设计是:学生端提交申请接口、教师端审核接口。审核接口里通过applyType和当前状态判断是进入下一级还是退回重填。

核心代码思路:

@SaCheckPermission("fitness:exemption:audit") @PostMapping("/audit") public Result<Void> audit(@RequestBody ExemptionAuditDTO dto) { ExemptionApply apply = exemptionApplyService.getById(dto.getApplyId()); if (apply == null) { return Result.error("申请记录不存在"); } // 断言当前状态与操作人角色匹配 exemptionApplyService.assertCanAudit(apply, StpUtil.getLoginIdAsLong()); apply.setStatus(dto.getPass() ? apply.getStatus() + 1 : 4); apply.setAuditRemark(dto.getRemark()); // 如果审核通过且到达终态,自动生成免测成绩记录 exemptionApplyService.audit(apply); return Result.success(); }

这里有一个细节值得注意:状态值用了“审核通过就把status加一”的做法,相当于用状态数值表示流转进度,前提是数据库里对status字段加check约束或者枚举校验,防止人为改成非法值。代码里写的assertCanAudit方法作用很关键,它校验当前登录用户是否有权限审核这个申请(比如教师不能审核自己班级之外的申请)。这个学号范围校验在真实业务里很重要——不同班级的老师只能处理自己班学生的免测申请,这个权限冲突很多人一开始想不到,等到测试不同角色时才暴露出来。

4.4 统计报表与可视化大屏

报表模块决定了这个系统在答辩时给人“专业性”的第一印象。这里除了输出班级体测通过率、年级平均分、项目及格率这些常规统计外,我强烈建议加一个可视化大屏页面。用ECharts画雷达图展示学生各项目均衡性,用柱状图对比不同年级的体测达标率,用折线图展示近几年的体测成绩趋势。

ECharts使用本身不复杂,核心是后端要把统计数据按前端需要的格式组装好。一个常用的接口设计是返回这样的结构:

public class StatisticsVO { private List<String> categories; // 班级名称列表 private List<BigDecimal> excellentRate; // 优秀率 private List<BigDecimal> goodRate; // 良好率 private List<BigDecimal> passRate; // 及格率 private List<BigDecimal> failRate; // 不及格率 private List<ProjectStat> projectStats; // 各项目均值 }

SQL层用一个聚合查询就能拿到班级维度数据:

SELECT c.class_name, ROUND(SUM(CASE WHEN r.score >= 90 THEN 1 ELSE 0 END) / COUNT(r.id) * 100, 2) AS excellent_rate FROM fitness_result r JOIN student_info s ON r.student_id = s.id JOIN class_info c ON s.class_id = c.id WHERE r.plan_id = #{planId} GROUP BY c.id

不建议往数据库里塞统计结果表,实时查询即可——体测数据量级最多几万条,MySQL做这种聚合计算毫无压力,不用过度设计。如果真想做性能优化,可以给plan_id和score建一个联合索引,MySQL执行聚合时走索引覆盖扫描,查询速度会有明显提升。

健康预警这个模块很多版本不会做,我建议做进去。规则不复杂:如果学生BMI指数小于18.5或大于28、肺活量体重指数偏低、1000/800米跑成绩接近不及格线,系统自动把学生标记为“重点关注对象”,生成预警记录。这个功能的价值在于体现系统从“数据采集”到“健康干预”的延伸,也是论文里能写“系统创新点”的好素材。

5. 从选题到答辩:进度安排、创新点与高频踩坑

最后这部分写给正在规划和执行项目的人。一个SpringBoot体测管理系统,从零开始做,合理周期是8到12周。时间怎么分配、创新点怎么提炼、最容易在哪些地方翻车,下面都给你整理好。

5.1 八到十二周的项目推进时间表

我给一份参考进度表,你可以对照自己的周期来调整:

时间里程碑交付物
第1周业务调研与技术选型需求分析文档、技术方案文档
第2周数据库设计与SpringBoot项目初始化建表SQL、工程骨架、基础三层结构
第3周用户登录、角色权限、基础数据管理可登录的后台系统
第4-5周体测计划、学生信息、班级信息管理基础CRUD功能完整可用
第6-7周成绩录入(手动+导入)、自动评分核心业务闭环跑通
第8周免测申请与审批流程流程模块全部可用
第9周统计报表、可视化大屏、健康预警报表功能上线
第10周前后端联调、单元测试、Bug修复可演示的完整系统
第11周论文主线撰写、系统截图整理论文初稿
第12周答辩PPT、演示环境准备全部材料就绪

这个节奏看着宽松,实际执行中第4-5周最容易拖延,因为基础管理功能虽然技术简单,但页面量和字段校验很多,很磨人。我的经验是基础CRUD不要过度追求完美,先把页面能跑通,把核心流程打通后再回头补细节校验。

5.2 创新点怎么提炼才不落俗套

答辩时老师最常问的问题是:“你这个系统除了常规增删改查,有什么特别的?”提前梳理好创新点,答案就有了层次。

我建议从三个角度提炼。一是批量导入与自动评分的完整链路,强调从Excel上传到成绩自动计算、自动评定等级的一体化流程,节省人工核对时间。二是标准快照机制,强调系统能自动追溯历史体测成绩是按照哪一版标准评定的,这是很多管理系统忽略的数据治理问题。三是数据可视化和健康预警,强调系统不只是记录数据,还能给体育教学提供决策支持和健康干预建议。

如果学有余力,可以再加一个二维码或微信公众号的“体测成绩通知”功能,学生体测成绩出来后自动推送到微信。这个功能技术上是调用第三方模板消息接口,但演示效果很好,答辩时非常有记忆点。

5.3 Maven依赖冲突、Vue集成和事务回滚三个经典坑

最后说几个我从这个项目里“踩出来的”具体问题,每个都是真实开发中高频出现的。

第一个是Maven依赖冲突。引入MyBatis-Plus后如果报ClassNotFoundException: org.mybatis.logging.Logger之类的错误,通常是MyBatis-Plus内置的MyBatis版本和项目里手动引入的MyBatis版本冲突了。解决办法是去掉手动引入的mybatis依赖,只保留mybatis-plus-boot-starter,让MyBatis-Plus管理版本。

第二个是Vue开发环境的接口跨域。Vue跑在5173端口,SpringBoot跑在8080端口,开发环境下axios跨域请求会被浏览器拦截。解决办法推荐在Vue的vite.config.js里配置proxy代理,前缀带/api的请求自动转发到http://localhost:8080。这样开发和打包都不用改一行代码。这个配置在Vite中大概是这样:

server: { host: '0.0.0.0', port: 5173, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }

第三个是事务回滚失效。成绩批量导入时,如果中间某条数据插入失败,希望前面的数据也全部回滚,这就需要@Transactional注解。但要注意,只有public方法上的@Transactional才会生效,而且同一个类内部自调用不会走代理,事务不生效。这个问题很隐蔽,我当时在Service里写了一个private方法处理批量保存逻辑,结果每条成绩都出现“部分成功部分失败”的脏数据状态。后来把批量保存逻辑提取到独立的public方法上,事务才正常回滚。这个坑在SpringBoot源码和面试题里也经常出现,理解了代理机制就能明白原理。

以我自己的体会来说,做完这个项目最大的收获不是学会了一门框架的使用方法,而是摸清楚了“从业务需求到数据库设计,再到功能实现”这条完整链路中,每一个决策会怎样影响后面的开发工作量。做体测系统时你想清楚的标准快照、状态流转、批量导入校验,放到任何企业管理系统里都是同样的问题。这套思考方式练出来了,换一个选题、换一套业务,你也能在一周内把系统设计得清清楚楚。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询