From 96087d8daca51b339480a6e193691ae642600ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=8E=E4=BD=97?= Date: Fri, 12 Jun 2026 13:10:47 +0800 Subject: [PATCH] =?UTF-8?q?docs(bug):=20=E8=AF=B8=E8=91=9B=E4=BA=AE?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E5=88=86=E6=9E=90=E6=8A=A5=E5=91=8A=20Bug=20?= =?UTF-8?q?#741=20(LLM=E6=B7=B1=E5=BA=A6=E5=88=86=E6=9E=90)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MD/bugs/BUG_741_ANALYSIS.md | 73 +++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/MD/bugs/BUG_741_ANALYSIS.md b/MD/bugs/BUG_741_ANALYSIS.md index 8efe0c9ec..b93128a76 100644 --- a/MD/bugs/BUG_741_ANALYSIS.md +++ b/MD/bugs/BUG_741_ANALYSIS.md @@ -14,12 +14,71 @@ --- -(LLM 失败,关键词分析) -Bug: 【住院医生工作站】打开门诊医生工作站会有代码列表报错 -模块: 住院医生工作站 +### 一、Bug 理解 ---- +用户登录 doctor1 账号进入**住院医生工作站**页面时,页面加载过程中某个 API 请求返回了 500 错误,错误信息为 `class java.util.ArrayList cannot be cast to class com.fasterxml.jackson.databind.JsonNode`。这个 Java ClassCastException 被前端 `request.js` 拦截器捕获并弹出错误提示,导致页面功能异常。期望是页面能正常加载,患者列表和各 Tab 页正常工作。 -## 路由决策 -- **修复 Agent**: guanyu -- **原因**: 降级: guanyu +### 二、根因分析 + +**直接原因**:后端某个 API 接口在处理请求或序列化响应时,抛出了 `ClassCastException: ArrayList cannot be cast to JsonNode`。异常被 `GlobalExceptionHandler` 捕获后返回 `{code:500, msg:"class java.util.ArrayList cannot be cast to class com.fasterxml.jackson.databind.JsonNode"}`。 + +**根因定位**:commit `68cfa4882` 修改了 `ApplicationConfig`,将 `Jackson2ObjectMapperBuilderCustomizer` 替换为直接创建 `new ObjectMapper()` 的 `@Bean`。 + +```java +// 旧代码 — 定制 Spring Boot 自动配置的 ObjectMapper +@Bean +public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() { + return builder -> { ... }; +} + +// 新代码 — 直接覆盖 Spring Boot 自动配置的 ObjectMapper +@Bean +public ObjectMapper objectMapper() { + ObjectMapper mapper = new ObjectMapper(); + ... +} +``` + +**问题机制**: +1. 定义 `@Bean ObjectMapper` 会**替换** Spring Boot 自动配置的 `ObjectMapper`,丢失大量自动配置(模块注册、类型解析器、序列化注解处理等) +2. Spring Boot 4.x 的 `MappingJackson2HttpMessageConverter` 使用此 Bean 做响应序列化 +3. 当 `DictAspect`(拦截所有 `@GetMapping`/`@PostMapping`)处理 `R>` 响应时,`IPage` 的泛型信息在新 `ObjectMapper` 下无法正确解析 +4. Jackson 内部在序列化过程中尝试将 `ArrayList`(`IPage` 内部的 records 列表)强转为 `JsonNode`,导致 `ClassCastException` + +**涉及文件**: +- `core-framework/.../ApplicationConfig.java` — **根因所在**,ObjectMapper Bean 配置不当 +- `healthlink-his-common/.../DictAspect.java` — 拦截所有 Controller 方法,触发序列化链路 +- `regdoctorstation/.../AdviceManageController.java` — `/reg-patient-zk` 端点 +- `regdoctorstation/.../AdviceManageAppServiceImpl.java` — `getRegPatientMainInfo()` 返回 `IPage` +- `utils/request.js` — 前端拦截器,line 186 抛出 Promise reject + +### 三、修复方案 + +**修改文件**:`core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java` + +**修复方式**:将 `@Bean ObjectMapper` 回退为 `Jackson2ObjectMapperBuilderCustomizer`,这样 Spring Boot 自动配置的 ObjectMapper 保持不变,只在其基础上追加自定义配置: + +```java +@Bean +public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() { + return builder -> { + builder.timeZone(TimeZone.getDefault()); + builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss"); + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addDeserializer(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER); + javaTimeModule.addSerializer(LocalDateTime.class, + new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + builder.modules(javaTimeModule); + }; +} +``` + +**验证步骤**: +1. `mvn clean compile -DskipTests` — 编译通过 +2. 启动应用 → 以 doctor1 登录 → 进入住院医生工作站 → 确认无报错 +3. 验证患者列表正常加载、诊断/医嘱 Tab 页正常切换 + +### 四、路由决策 + +- **修复 Agent**: guanyu(后端开发) +- **原因**: 修复点在 `ApplicationConfig.java` 的 ObjectMapper Bean 配置,属于后端 Spring 配置问题,需要回退 Jackson 序列化配置并验证编译通过。