Files
UserclassService/.workbuddy/memory/2026-08-13.md
T
2026-08-13 17:04:23 +08:00

6.2 KiB
Raw Blame History

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 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,由框架 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 ...」。