根因: - ** - `core-framework/.../ApplicationConfig.java:39` — `LocalDateTimeDeserializer` 只配置了 `yyyy-MM-dd HH:mm:ss` 格式 - 前端发送 ISO 8601 格式日期字符串 `"2026-06-01T01:45:06.439Z"`(含毫秒 + `Z` 时区后缀),Jackson 反序列化失败抛出 `JsonParseException` 修复: - ** - 修改 `ApplicationConfig.java`,将单一格式的 `LocalDateTimeDeserializer` 替换为自定义多格式反序列化器 - 新反序列化器依次尝试:ISO 8601(`yyyy-MM-ddTHH:mm:ss.SSS`)→ 简单格式(`yyyy-MM-dd HH:mm:ss`)→ 斜杠格式(`yyyy/M/d HH:mm:ss`) - 自动剥离 `Z`/`z` 时区后缀和 `+HH:MM` 偏移量(`LocalDateTime` 不含时区信息) - 6 环验证:** - ①前端 → ②Controller:`@RequestBody` 反序列化现在支持 ISO 8601 格式 ✅ - ③Service:无需修改,DTO 字段类型未变 ✅ - ④Mapper:无需修改,SQL 映射未变 ✅ - ⑤DB:无需修改,字段类型未变 ✅ - ⑥关联模块:全局生效,所有使用 `LocalDateTime` 的实体均受益 ✅ - 编译验证:** `mvn compile -pl openhis-application -am` → BUILD SUCCESS ✅ - 变更文件:** `core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java`
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
package com.core.framework.config;
|
package com.core.framework.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||||
@@ -9,6 +11,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@@ -24,6 +27,36 @@ import java.util.TimeZone;
|
|||||||
// 指定要扫描的Mapper类的包的路径
|
// 指定要扫描的Mapper类的包的路径
|
||||||
@MapperScan({"com.core.**.mapper", "com.openhis.**.mapper"})
|
@MapperScan({"com.core.**.mapper", "com.openhis.**.mapper"})
|
||||||
public class ApplicationConfig {
|
public class ApplicationConfig {
|
||||||
|
|
||||||
|
/** 支持多种日期格式的反序列化器 */
|
||||||
|
private static final JsonDeserializer<LocalDateTime> LOCAL_DATE_TIME_DESERIALIZER = new JsonDeserializer<LocalDateTime>() {
|
||||||
|
private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||||
|
private static final DateTimeFormatter SIMPLE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
private static final DateTimeFormatter SLASH_FORMATTER = DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||||
|
String text = p.getText();
|
||||||
|
if (text == null || text.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 去除时区后缀 Z/z 和偏移量 +HH:MM/+HHMM(LocalDateTime 不含时区信息)
|
||||||
|
String cleaned = text.replaceAll("[Zz]$", "").replaceAll("[+-]\\d{2}:?\\d{2}$", "");
|
||||||
|
// 尝试 ISO 8601 格式(yyyy-MM-ddTHH:mm:ss.SSS)
|
||||||
|
try {
|
||||||
|
return LocalDateTime.parse(cleaned, ISO_FORMATTER);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
// 尝试简单格式(yyyy-MM-dd HH:mm:ss)
|
||||||
|
try {
|
||||||
|
return LocalDateTime.parse(cleaned, SIMPLE_FORMATTER);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
// 尝试斜杠格式(yyyy/M/d HH:mm:ss)
|
||||||
|
return LocalDateTime.parse(cleaned, SLASH_FORMATTER);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 时区配置
|
* 时区配置
|
||||||
*/
|
*/
|
||||||
@@ -36,7 +69,7 @@ public class ApplicationConfig {
|
|||||||
builder.simpleDateFormat("yyyy/M/d HH:mm:ss");
|
builder.simpleDateFormat("yyyy/M/d HH:mm:ss");
|
||||||
// 添加JavaTimeModule支持,用于LocalDateTime
|
// 添加JavaTimeModule支持,用于LocalDateTime
|
||||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||||
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
javaTimeModule.addDeserializer(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER);
|
||||||
builder.modules(javaTimeModule);
|
builder.modules(javaTimeModule);
|
||||||
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss")));
|
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss")));
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user