Spring Boot GET请求数据类型转换失效及自定义转换器实现
嗨,我来帮你搞定Spring Boot里请求参数转换失败的问题!
解决Spring Boot请求参数转换异常&自定义转换器指南
一、先排查你可能漏掉的配置点
虽然你已经加了Swagger生成的OffsetDateTime转换器,但大概率是没把它纳入Spring的转换体系,或者细节没处理对:
- 你的转换器类有没有加
@Component注解?Spring不会自动扫描没标记的类哦 - 如果是手动配置的转换器,有没有在
WebMvcConfigurer的配置类里注册? - 前端传的参数格式和转换器期望的是否匹配?比如OffsetDateTime通常需要
2024-05-20T12:34:56+08:00这种ISO格式,要是前端传的是2024-05-20 12:34:56肯定会报错
二、自定义请求数据类型转换器的正确姿势
方法1:实现Converter接口并让Spring自动注册
写一个转换器类,实现Spring的Converter<String, OffsetDateTime>接口,然后加@Component让Spring扫描到:
import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; @Component public class StringToOffsetDateTimeConverter implements Converter<String, OffsetDateTime> { // 用ISO标准格式,和Swagger的默认格式对齐 private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_OFFSET_DATE_TIME; @Override public OffsetDateTime convert(String source) { if (source == null || source.trim().isEmpty()) { return null; } return OffsetDateTime.parse(source, FORMATTER); } }
这样启动项目后,Spring会自动把这个转换器加入到全局转换服务里,处理@RequestParam或者路径变量的转换。
方法2:通过WebMvcConfigurer手动注册(适合批量配置)
如果你的转换器不想加@Component,或者需要一次性注册多个转换器,可以写个配置类:
import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { // 注册自定义的OffsetDateTime转换器 registry.addConverter(new StringToOffsetDateTimeConverter()); // 这里还可以加其他类型的转换器,比如LocalDate、LocalTime之类的 } }
方法3:处理JSON请求体的情况(@RequestBody)
如果你的参数是通过@RequestBody接收的JSON格式,上面的Converter就不管用了——因为JSON解析是Jackson负责的。这时候要配置Jackson的JavaTime模块:
方式一:通过application.properties配置
# 指定日期时间格式,和ISO偏移格式对齐 spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ssXXX # 设置时区,根据你的业务调整 spring.jackson.time-zone=GMT+8 # 启用Java 8时间模块支持 spring.jackson.serialization.write-dates-as-timestamps=false
方式二:自定义ObjectMapper(更灵活)
如果需要更定制化的格式,可以手动配置Jackson的ObjectMapper:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.OffsetDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.time.format.DateTimeFormatter; @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); JavaTimeModule timeModule = new JavaTimeModule(); // 配置OffsetDateTime的反序列化规则 timeModule.addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); // 配置OffsetDateTime的序列化规则 timeModule.addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); objectMapper.registerModule(timeModule); return objectMapper; } }
三、针对你的场景的额外排查建议
- 先验证Swagger生成的转换器是否真的被Spring加载了:可以在转换器的
convert方法里加个日志打印,启动项目后看控制台有没有输出 - 区分参数类型:GET请求的
@RequestParam用Converter,POST的@RequestBody用Jackson配置,别搞混了 - 测试参数格式:用Postman或者Swagger直接传符合格式的参数,比如
2024-05-20T15:30:00+08:00,看是否能正常转换
要是按照上面的步骤还是有问题,可以把你的控制器代码贴出来,我再帮你细化排查!
内容的提问来源于stack exchange,提问作者Jigar Shah
相关产品推荐
相关产品推荐

