This commit is contained in:
2026-08-13 17:04:23 +08:00
parent 0501dec9b0
commit 6f957cad93
+43
View File
@@ -0,0 +1,43 @@
# 2026-08-13
## 项目:bschclassmanage — UserContext 重构(去掉 authUserWithDept / curRole 参数)
### 目标
从所有 controller 方法签名中移除 `BoaUser authUserWithDept` 与 `UserSysRole curRole` 两个参数,身份改为通过 `UserContext` ThreadLocal 工具类获取。Service 层约定:「显式接收 `UserContext.UserInfo user` 参数」(沿用用户示例 `saveSchSub(UserContext.getCurrentUser(), model)`)。
### 改动清单(已落地)
- `utils/UserContext.java`:新增 `type` 字段(ThreadLocal<Integer> TYPE)+ `setType/getType`,`@Value UserInfo` 加 `Integer type`,`getCurrentUser()` 改 6 参构造,`setUserInfo()`/`clear()` 同步处理 TYPE。原因:`SchsystemController` 原用 `authUserWithDept.getType()` 做超管判断,无对应字段。
- 17 个 `controller/api/*Controller.java`:删除两个参数,调用处 getter 改为 `UserContext.getUserId/getUserName/getType/getRoleId/getSchId`;`getUserInfo()` 返回类型 `BoaUser` → `UserContext.UserInfo`;清理失效 `BoaUser`/`UserSysRole` import,补 `UserContext` import。由临时 Python 脚本批量转换。
- `aspect/ControllerUserContextAspect.java`:populate 逻辑补 `UserContext.setType(...)`;删除一处指向已删解析器的过时注释。
- `interceptor/UserContextInterceptor.java`:修正原 `UserContext.se(...)`(不存在)编译错误,改为 `setUserId/setUserName/setType`。
- `config/DWebMvcConfig.java`:移除已废弃的 `UserSysRoleArgumentResolver` 装配及其 import/@Autowired/addArgumentResolvers。
- 删除 `controller/Handler/UserSysRoleArgumentResolver.java`(仅被 DWebMvcConfig 与 aspect 注释引用)。
### 回归修复
- `SchGradeController`:去掉 `curRole` 后两个 `getGradeSelect(@RequestParam Integer …)` 重载签名撞车(编译错误)。已重命名为 `getGradeSelectBySchsystemId` 与 `getGradeSelectBySchId`,no-arg 版保留 `getGradeSelect`。
### 验证
- 脚本扫描 17 个 controller:**方法签名碰撞 NONE**、**authUserWithDept/curRole 残留 NONE**、**死 import NONE**。
- `pom.xml` 已还原为仅 `spring-boot-maven-plugin`(曾临时加 maven-compiler-plugin annotationProcessorPaths 试图让 mvn 跑 Lombok,无效且非本次范围,已回退)。
### 环境注意(非本次范围)
- 本机 `mvn compile` 因 Lombok annotation processing 未在命令行生效而失败(仅 IntelliJ Lombok 插件可编译),属既有环境限制,未处理。
- 临时文件 `C:\Users\Allen\refactor_usercontext.py` / `build*.log` / `verify_refactor.py` 因安全策略拦截未能自动清理,仍在用户 home 目录,待用户确认后删除。
### 线上 500(code 6 内部服务错误)根因与修复
- 现象:`POST http://192.168.10.166:8086/api/subject/save` 返回 `{"code":6,"msg":"内部服务错误"}`(yunhai `yh-api-std` 的全局异常包装,真实栈在服务器日志)。
- 根因:重构去掉 `BoaUser authUserWithDept` 参数后,`ControllerUserContextAspect` 改为从 **request attribute**(`boaUser/currentUser/...`)取身份,但框架 yunhai 从来不把 BoaUser 放进 request attribute。原 `authUserWithDept` 由框架 `BoaUserArgumentResolver` 解析,其 `resolveArgument` 直接返回 `com.yunhai.platform.auth.BoaUserContext.get()`(一个静态 ThreadLocal<BoaUser>,由框架 `PathBasedAuthInterceptor.preHandle` 每请求 `set`、afterCompletion `clear`)。
- 后果:`UserContext` 的 userId/type 拿不到 → `OtherUtil.setBaseEntityValue` 把 `create_user_id` 写成 null → `schDicSubjectRepository.save` 触发 NOT NULL 约束 → `DataIntegrityViolationException` → code 6。
- 修复:`ControllerUserContextAspect.setUserContext` 改为优先 `BoaUserContext.get()`(try/catch 包住),失败再回退 request attribute;`currentrole`(UserSysRole→schId/roleId)仍由 aspect 从 Header/Query 解析(等价于被删的 `UserSysRoleArgumentResolver`)。新增 import `com.yunhai.platform.auth.BoaUserContext`(yh-auth-core,yh-auth-spring-boot-starter 的非 optional 传递依赖,编译期可达)。
- 验证:`mvn compile` 仍受 Lombok 环境限制跑不起来;正确性通过对 yunhai jar 反编译(javap)确认 `BoaUserContext` 来源与 `PathBasedAuthInterceptor` 的 set 调用。临时解压目录 `C:\Users\Allen\_jarx`、`_jarx2` 为分析用,待清理。
- 若修复后该接口仍 500:下一步排查前端是否发送 `currentrole`(提供 schId);可由 `saveSchSub` 在 `user.getSchId()==null` 时抛明确 `IllegalArgumentException` 来定位。
### @RequestBody 反序列化 500(与身份回归无关,另一独立问题)
- 现象:用户对照实验证明——`saveSchSub()` 无参能跑通(身份/服务正常);`saveSchSub(@Valid @RequestBody SchDicSubject model)` 或去掉 @Valid 后仍 500,断点不进方法体。
- 结论:异常发生在进入方法体之前,即 `@RequestBody` JSON 反序列化阶段(`HttpMessageNotReadableException`)或 Content-Type 不匹配(`HttpMediaTypeNotSupportedException`),二者未被项目异常处理捕获 → 冒泡到 `yh-api-std` 兜底成 `code:6`。
- 排查:实体 `SchDicSubject`(+`BaseEntity`)字段全为标准类型(Integer/String/Boolean/Date),用户所贴 JSON(id,name,schSystemId,enable,source,sort)字段与类型完全匹配,默认 Jackson 不应失败 → 真因是「前端实际请求没带 `Content-Type: application/json`」或「真实请求含实体没有的字段(如 $$hashKey)触发 `FAIL_ON_UNKNOWN_PROPERTIES`」。
- `application.yml` 仅设 `spring.jackson.time-zone/date-format`,无 `fail-on-unknown-properties` → 默认 true。
- 修复(双保险):
1. `entity/SchDicSubject.java` 的 `@JsonIgnoreProperties` 加 `ignoreUnknown = true`(容忍前端多余字段)。
2. `ValidationExceptionHandler` 新增 `@ExceptionHandler(HttpMessageNotReadableException)` 与 `@ExceptionHandler(HttpMediaTypeNotSupportedException)`,把真实原因透出(不再被 code:6 吞掉),返回 `code=ErrorCode.ERROR`、`msg` 含具体原因。
- 验证手段:用 `curl -H "Content-Type: application/json" -d '{...}'` 直连;或部署后看返回 msg 是否直接点出「Content-Type 不被支持」/「JSON 解析失败: Unrecognized field ...」。