fix: OpenAPI 接口文档元数据前端输出 base64 字符串导致文档无法显示的问题修复
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 是最稳妥的修复方式。
This commit is contained in:
47
src/main/java/com/youlai/boot/config/JacksonConfig.java
Normal file
47
src/main/java/com/youlai/boot/config/JacksonConfig.java
Normal file
@@ -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 全局序列化配置
|
||||||
|
*
|
||||||
|
* <p>本项目的统一序列化策略:
|
||||||
|
* <br>- 统一时区 GMT+8 统一日期格式 yyyy-MM-dd HH:mm:ss
|
||||||
|
* <br>- Long/BigInteger 序列化为字符串,避免前端精度丢失
|
||||||
|
* <br>- 禁用 WRITE_DATES_AS_TIMESTAMPS,避免日期输出为时间戳</p>
|
||||||
|
*
|
||||||
|
* @author Ray.Hao
|
||||||
|
* @since 2026/1/12
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class JacksonConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局 JsonMapper
|
||||||
|
*
|
||||||
|
* <p>由 Spring Boot 自动装配到 Jackson 相关的 HttpMessageConverter 中,作为全局 JSON 序列化/反序列化
|
||||||
|
* 行为的唯一入口。</p>
|
||||||
|
*/
|
||||||
|
@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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user