Files
TARE-Learn/exams/exam-kit/reference-answer.md
T
smart 67837df8d0 docs: 更新TRA编程培训课程材料、课件与AI技能交付包
- 新增全套考试卷、评估卷、参考答案与考试培训包模板
- 修正slidev培训课件:调整模块标题、链路图缩放,替换工单示例为通用业务对象
- 修正课堂红线表述为证据红线,将小组作业调整为个人作业要求
- 新增权限、状态流转、审计日志、看板指标四类可复用业务规则块
- 整理AI工程技能交付包,迁移旧资产至客户专属交付包并统一术语
- 新增考试输出模板与TRAE使用记录文档
2026-08-08 11:00:36 +08:00

13 KiB
Raw Blame History

TRAE 编程培训考试评估卷 - 阅卷参考答案

阅卷专用。对应 jeecgboot/JeecgBoot 标签 v3.9.2、提交 7df07a823fd558be857d0208ccae96342539fbc1 及 review-diff.patch。学生不需要逐字复述本答案,但所有核心结论都必须有等价的源码依据。

A 卷

任务 1:Prompt 改写(15 分)

下列内容是一份达到满分要求的参考 Prompt。允许更换表述,但不能省略范围、约束、交付格式和验收条件。

你是负责 JeecgBoot 系统用户模块的后端工程师。请基于 GitHub 仓库
jeecgboot/JeecgBoot 的 v3.9.2(提交 7df07a823fd558be857d0208ccae96342539fbc1),
审查“批量冻结/解冻用户”的后端链路是否允许非法状态值进入数据层。

范围:只分析
1. SysUserController.frozenBatch;
2. ISysUserService.updateStatus 和 SysUserServiceImpl.updateStatus;
3. CommonConstant 中的用户状态常量;
4. 与本接口直接相关的权限、管理员保护、缓存和测试入口。

目标:给出最小改造建议,使 status 只允许 1(解冻)或 2(冻结),并在数据库写入前拒绝
空白或其他值。不要修改接口路径、权限 system:user:frozenBatch、管理员保护或缓存失效策略。

请按以下格式输出:
- 调用链和每个结论的“文件路径 + 方法/符号”;
- 变更位置、伪代码和不改动项;
- 空白/非法状态、冻结、解冻、无权限、管理员保护和缓存回归的测试矩阵;
- 仍需人工确认的问题。事实、推断和待确认项必须分别标识。

验收:每个结论均可回溯到上述固定提交;不编造测试结果;信息不足时先提出待确认项。

判分关键:背景与目标(3 分)、范围(2 分)、约束(4 分)、输出格式(3 分)、验收和证据要求(3 分)。只写“帮我检查有没有问题”不能得高分。

任务 2:AI 输出辨析(15 分)

题干中的 AI 结论“页面已限制状态值,因此 Service 不需要校验;直接调用接口也不会有问题”应判为错误,理由如下:

  1. 前端限制不是服务端的可信边界。调用者可以绕过页面直接发送 PUT /sys/user/frozenBatch 请求。
  2. SysUserController.frozenBatch 从 JSON 读取 status 后逐个调用 sysUserService.updateStatus(id, status);原版 updateStatus 会直接执行 Integer.parseInt(status) 并更新数据库。
  3. Service 入口是数据写入前的最后业务保护点。正确做法是在 updateStatus 内、Integer.parseInt 和 userMapper.update 之前,仅允许 CommonConstant.USER_UNFREEZE(1)和 CommonConstant.USER_FREEZE(2)。null、空串、空白串、3 及其他值均应抛出业务异常。
  4. 不能因此删除接口权限、管理员保护或缓存注解;这些分别处理调用授权、关键账号保护和用户缓存一致性。

B 卷任务 1:项目理解与影响分析(25 分)

满分结论摘要

  1. 批量冻结/解冻的 HTTP 入口是 PUT /sys/user/frozenBatch,由 SysUserController.frozenBatch 处理,受 system:user:frozenBatch 权限保护。
  2. Controller 从请求体读取 ids、先调用 checkUserAdminRejectDel(ids),再读取 status,对每个非空 ID 调用 updateStatus(id, status)。
  3. updateStatus 是最终写入入口:它将状态转换为整数,通过 userMapper.update 更新 SysUser.status,并用 @CacheEvict(CacheConstant.SYS_USERS_CACHE, allEntries = true) 失效用户缓存。
  4. 用户状态常量中,1 表示解冻,2 表示冻结,3 表示注销;本题只允许前两种状态。
  5. 冻结状态会影响登录有效性判断:服务在读取到 USER_FREEZE 时返回“该用户已冻结”。

至少应出现的证据

结论 文件路径与符号 证明内容 判断类型
接口、HTTP 方法和权限 .../controller/SysUserController.java,frozenBatch @RequiresPermissions("system:user:frozenBatch") 与 @RequestMapping(... "/frozenBatch", PUT) 事实
Controller 到 Service 调用链 同文件 frozenBatch 读取 ids、管理员保护、读取 status,循环调用 updateStatus 事实
服务契约 .../service/ISysUserService.java,updateStatus(String id, String status) 状态更新是服务接口的一部分 事实
数据库与缓存副作用 .../service/impl/SysUserServiceImpl.java,updateStatus @CacheEvict、Integer.parseInt(status)、userMapper.update 事实
合法状态枚举 .../common/constant/CommonConstant.java,USER_UNFREEZE、USER_FREEZE、USER_QUIT 取值分别为 1、2、3 事实
管理员保护 .../service/impl/SysUserServiceImpl.java,checkUserAdminRejectDel 目标 ID 中含用户名 admin 时抛出业务异常;frozenBatch 会调用它 事实
登录影响 .../service/impl/SysUserServiceImpl.java,登录有效性检查中对 USER_FREEZE 的分支 冻结用户不能正常登录 事实

影响和保护边界

  • 非法状态若进入原版 Service,会在 Integer.parseInt 处异常,或在可解析但不受业务允许的值(如 3)场景写入不符合本题要求的状态;因此应在 Service 入口先拒绝。
  • 校验位于 userMapper.update 前;抛出异常时不会完成本次用户状态写入。@CacheEvict 默认在方法成功返回后生效,因此异常路径不应把一次失败校验伪装为成功变更。
  • 必须保持:接口路径和 PUT 方法、system:user:frozenBatch 权限、checkUserAdminRejectDel(ids) 调用、逐个用户更新的方式、缓存失效注解。
  • 可接受的待确认项:批量操作是否要求原子性、前端是否会发送 null 或空白状态、缓存是否有跨节点配置。不得把这些未查证项写成事实。

B 卷任务 2:最小改造与测试安全网(25 分)

改造位置和参考实现

文件:jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserServiceImpl.java。

方法:updateStatus(String id, String status)。

位置:保留已有 @Override 和 @CacheEvict,在 Integer.parseInt(status)、userMapper.update(...) 之前加入校验:

if (!String.valueOf(CommonConstant.USER_UNFREEZE).equals(status)
        && !String.valueOf(CommonConstant.USER_FREEZE).equals(status)) {
    throw new JeecgBootException("账号状态仅支持冻结或解冻");
}

该写法同时拒绝 null、空串、空白串、3 和其他非 1/2 的值;允许 "1" 与 "2"。它没有改变原有数据更新、缓存失效、权限或管理员保护路径。

必须明确的不改动项

不改动项 原因和代码依据
权限 SysUserController.frozenBatch 的 @RequiresPermissions("system:user:frozenBatch") 仍是接口授权边界。
管理员保护 Controller 继续先调用 sysUserService.checkUserAdminRejectDel(ids);状态校验不能替代该保护。
缓存失效 SysUserServiceImpl.updateStatus 的 @CacheEvict(value = {CacheConstant.SYS_USERS_CACHE}, allEntries = true) 保留,以保证成功修改后的用户缓存刷新。
数据写入方式 合法状态仍走原有 userMapper.update(new SysUser().setStatus(...), ...)。

参考测试矩阵

场景 预期结果 验证入口 执行状态的正确写法
null、空串、空白串、3 抛出 JeecgBootException;不调用 mapper,不成功失效缓存 SysUserServiceImpl.updateStatus 单元测试 未实际运行时必须写“未执行”和原因;不能凭空写通过
"1" 解冻 调用 mapper,写入状态 1;成功返回后缓存失效 Service 单元测试或集成测试 记录实际命令和结果
"2" 冻结 调用 mapper,写入状态 2;成功返回后缓存失效 Service 单元测试或集成测试 记录实际命令和结果
无权限请求 被权限框架拒绝,不能执行状态写入 PUT /sys/user/frozenBatch 的接口/集成测试 记录测试账号、HTTP 结果或未执行原因
目标包含 admin checkUserAdminRejectDel 拒绝,不能更新管理员 接口或 Controller 集成测试 记录结果或未执行原因
冻结后登录 读取冻结用户时走“该用户已冻结”分支 登录集成测试 可标为待环境验证,不得臆造

review-diff.patch 已提供一个针对 "3" 的最小单元测试。它覆盖非法数值在访问 mapper 前被拒绝;高质量答案还应补充空白值和两个合法值的测试。项目父 POM 默认配置 maven-surefire-plugin 跳过测试,因此学员若未调整本地测试配置,应如实标记“未执行”,并给出启用测试后的计划命令,而不是伪造成功结果。

B 卷任务 3:Review、PR 与资产沉淀(20 分)

参考 Review 结论

结论:可以合入,但建议在合入前补充测试用例。

检查范围是 review-diff.patch 的两处改动:SysUserServiceImpl.updateStatus 和新增的 SysUserServiceImplTest。

级别 结论 证据 建议
通过 校验位于 Integer.parseInt 和 userMapper.update 前,阻止非法状态写入 服务实现新增条件与业务异常 保持
通过 仅允许常量 1/2,null 和空白均不匹配,状态 3 也被拒绝 两个常量比较均通过 String.valueOf 保持
通过 没有删除缓存失效注解、接口权限或管理员保护 diff 只改 Service 校验和新增测试 保持
建议 新测试仅覆盖 "3",未直接覆盖 null、空白、"1"、"2" 和 mapper 未调用 新增测试类只有一个 assertThrows 加参数化负例和合法值的 mapper 交互断言
残余风险 Controller 对异常统一返回的语义、批量更新原子性和集群缓存行为不属于本 diff 的直接变更 原始 Controller 和框架配置 作为后续集成测试范围,不阻断本次最小修复

不能仅写“代码没问题”。若给出“未发现阻断问题”,仍须写清检查范围、证据和残余风险。

参考 PR 说明

背景:系统用户批量冻结/解冻接口会将请求中的 status 传入 Service。前端选项限制不能替代服务端边界,非法值应在数据写入前被拒绝。

实现:在 SysUserServiceImpl.updateStatus 增加状态白名单,仅允许解冻(1)和冻结(2);非法值抛出 JeecgBootException。保留原缓存失效、Controller 权限和管理员保护。

测试:新增非法状态 "3" 的单元测试。合入前建议补充 null、空白、"1"、"2" 及接口权限/管理员保护的测试;每项测试状态必须按实际执行情况填写。

风险与回退:该变更会拒绝过去可能被错误接受的状态值,属于预期的业务收紧。出现兼容性问题时可回退本次 Service 白名单提交;不能通过放宽为任意整数解决。

参考可复用 Prompt

基于指定 Git 提交审查一个状态更新 diff。先输出 Controller -> Service -> Mapper/缓存的调用链,
再判断校验是否发生在所有数据写入和可见副作用之前。只接受代码中已定义的状态常量;列出保留的
权限、关键账号保护、缓存和审计逻辑。最后按“阻断问题 / 建议 / 残余风险 / 测试矩阵”输出,
每项都给出文件路径和符号。没有执行的测试必须标为未执行,不能推断为通过。

验收方式:输出必须能标出校验位置、常量来源、未改动保护和至少一项负例及正例测试;不能凭空声称测试成功。

参考 Checklist 设计卡

项目 内容
名称 状态变更服务端边界 Checklist
适用场景 新增或修改“启用/停用/冻结/解冻/审批状态”等服务端状态写入逻辑时
输入 固定提交、变更 diff、状态常量定义、调用入口
检查项 1. 合法状态是否白名单化;2. 校验是否早于解析、写库和副作用;3. 权限和关键账号保护是否保留;4. 缓存/审计/事件是否明确;5. 正负例和接口授权测试是否如实记录
输出 Review 结论、证据表、测试矩阵、残余风险
边界 只辅助检查,不能替代实际权限配置、集成测试和人工业务审批
验收 每项结论都有文件路径和符号;未执行测试有原因与后续验证计划

AI 使用记录的判分口径

不提供统一的“标准 Prompt 列表”。满分记录应至少能够说明:使用 AI 或 TRAE 做了什么、建议是什么、哪些被采纳或否决、人工为什么这样判断、相应证据或测试是否真的执行。工具名称可以不同;缺少 trae-usage-record.md 时,本题“AI 使用记录”2 分为 0 分。