From 43394dd402e86762d6ece5df568ff248cab41f0b Mon Sep 17 00:00:00 2001 From: "Ray.Hao" <1490493387@qq.com> Date: Mon, 12 Jan 2026 11:25:52 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20OpenAPI=20=E6=8E=A5=E5=8F=A3=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=85=83=E6=95=B0=E6=8D=AE=E5=89=8D=E7=AB=AF=E8=BE=93?= =?UTF-8?q?=E5=87=BA=20base64=20=E5=AD=97=E7=AC=A6=E4=B8=B2=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E6=96=87=E6=A1=A3=E6=97=A0=E6=B3=95=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spring Boot 4 / Spring Framework 7 中不建议通过 WebMvcConfigurer 手工替换/重建 MVC 的 HttpMessageConverters 列表(相关回调已标记废弃且计划移除)。此类只负责提供全局 JsonMapper配置,保持 Spring Boot 默认 converters(例如 ByteArrayHttpMessageConverter)不被误删。出现的接口文档 Base64 问题根因:springdoc 的 /v3/api-docs/** 可能以 byte[] 形式输出 JSON。当默认的 ByteArrayHttpMessageConverter 缺失时,byte[] 会被 Jackson 当作普通对象序列化为Base64 字符串,导致浏览器/Knife4j 看到一整段 "eyJ..."。保持默认 converters + 仅配置 ObjectMapper 是最稳妥的修复方式。 --- .../com/youlai/boot/config/JacksonConfig.java | 47 +++++++++++ .../com/youlai/boot/config/WebMvcConfig.java | 79 ------------------- 2 files changed, 47 insertions(+), 79 deletions(-) create mode 100644 src/main/java/com/youlai/boot/config/JacksonConfig.java delete mode 100644 src/main/java/com/youlai/boot/config/WebMvcConfig.java diff --git a/src/main/java/com/youlai/boot/config/JacksonConfig.java b/src/main/java/com/youlai/boot/config/JacksonConfig.java new file mode 100644 index 00000000..f9ed47af --- /dev/null +++ b/src/main/java/com/youlai/boot/config/JacksonConfig.java @@ -0,0 +1,47 @@ +package com.youlai.boot.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import tools.jackson.databind.cfg.DateTimeFeature; +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.module.SimpleModule; +import tools.jackson.databind.ser.std.ToStringSerializer; + +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.TimeZone; + +/** + * Jackson 全局序列化配置 + * + *

本项目的统一序列化策略: + *
- 统一时区 GMT+8 统一日期格式 yyyy-MM-dd HH:mm:ss + *
- Long/BigInteger 序列化为字符串,避免前端精度丢失 + *
- 禁用 WRITE_DATES_AS_TIMESTAMPS,避免日期输出为时间戳

+ * + * @author Ray.Hao + * @since 2026/1/12 + */ +@Configuration +public class JacksonConfig { + + /** + * 全局 JsonMapper + * + *

由 Spring Boot 自动装配到 Jackson 相关的 HttpMessageConverter 中,作为全局 JSON 序列化/反序列化 + * 行为的唯一入口。

+ */ + @Bean + public JsonMapper objectMapper() { + return JsonMapper.builder() + .disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS) + .defaultDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")) + .defaultTimeZone(TimeZone.getTimeZone("GMT+8")) + .addModule(new SimpleModule() + .addSerializer(Long.class, ToStringSerializer.instance) + .addSerializer(BigInteger.class, ToStringSerializer.instance) + ) + .build(); + } + +} diff --git a/src/main/java/com/youlai/boot/config/WebMvcConfig.java b/src/main/java/com/youlai/boot/config/WebMvcConfig.java deleted file mode 100644 index a2b6f572..00000000 --- a/src/main/java/com/youlai/boot/config/WebMvcConfig.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.youlai.boot.config; - -import jakarta.validation.Validation; -import jakarta.validation.Validator; -import jakarta.validation.ValidatorFactory; -import lombok.extern.slf4j.Slf4j; -import org.hibernate.validator.HibernateValidator; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.converter.HttpMessageConverters; -import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter; -import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import tools.jackson.databind.cfg.DateTimeFeature; -import tools.jackson.databind.json.JsonMapper; -import tools.jackson.databind.module.SimpleModule; -import tools.jackson.databind.ser.std.ToStringSerializer; - -import java.math.BigInteger; -import java.text.SimpleDateFormat; -import java.time.format.DateTimeFormatter; -import java.util.TimeZone; - -/** - * Web 配置 - * - * @author Ray.Hao - * @since 2020/10/16 - */ -@Configuration -@Slf4j -public class WebMvcConfig implements WebMvcConfigurer { - - private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - - /** - * Spring Boot 4.x 已经使用Jackson 3.x - * Jackson 3.x已经自带JavaTimeModule,不再需要手工注册 - * - * @param converterBuilder the builder to configure - */ - @Override - public void configureMessageConverters(HttpMessageConverters.ServerBuilder converterBuilder) { - JsonMapper.Builder builder = JsonMapper.builder(); - - // 配置全局日期格式和时区 - builder.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS); - builder.defaultDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); - builder.defaultTimeZone(TimeZone.getTimeZone("GMT+8")); - - // 处理 Long/BigInteger 的精度问题 - SimpleModule simpleModule = new SimpleModule(); - simpleModule.addSerializer(Long.class, ToStringSerializer.instance); - simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance); - builder.addModule(simpleModule); - - converterBuilder.addCustomConverter(new JacksonJsonHttpMessageConverter(builder)); - } - - /** - * 配置校验器 - * - * @param autowireCapableBeanFactory 用于注入 SpringConstraintValidatorFactory - * @return Validator 实例 - */ - @Bean - public Validator validator(final AutowireCapableBeanFactory autowireCapableBeanFactory) { - try (ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class) - .configure() - .failFast(true) // failFast=true 时,遇到第一个校验失败则立即返回,false 表示校验所有参数 - .constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapableBeanFactory)) - .buildValidatorFactory()) { - - // 使用 try-with-resources 确保 ValidatorFactory 被正确关闭 - return validatorFactory.getValidator(); - } - } -}