栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot中LocalDate请求参数处理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot中LocalDate请求参数处理

版本说明:

  • springboot:2.6.7
  • jdk8

在项目中,有几个地方使用到了LocalDate作为请求参数,有的是作为URL参数进行传递,也有的作为请求体中的一个属性进行传递,即下面两种情况

@GetMapping("/xxx")
public List listByBeginDate(@RequestParam("beginDate") LocalDate beginDate) {
    // ...
}
@PostMapping("/xxx")
public User save(@ResponseBody User user) {
    // ...
}

@Data
static class User {
    private String name;
    private LocalDate birthday;
    // ...
}

在后台接收参数的时候,需要分别对二者进行处理,否则无法正常接收到参数。

1、LocalDate作为URL参数

添加如下的配置类即可,一般情况下,都是通过实现WebMvcConfigurer接口来处理跨域、静态资源映射或者添加拦截器等。而要处理LocalDate请求参数,最简单的做法就是添加类型转换器。

import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(localDateConvert());
    }

    public Converter localDateConvert() {
        // 不能替换为lambda表达式
        return new Converter() {
            @Override
            public LocalDate convert(String source) {
                if (StringUtils.hasText(source)) {
                    return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                }
                return null;
            }
        };
    }

}
2、LocalDate作为请求体中的一个属性

一般情况下是不会有问题的,如果真的出现了如下的错误,那多半是手动修改了MappingJackson2HttpMessageConverter中的ObjectMapper

org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.time.LocalDate]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDate` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling

实际上,项目中是有jackson-datatype-jsr310的,因为项目中依赖了spring-boot-starter-web,而其中又依赖了spring-boot-starter-json,这里面是有jackson-datatype-jsr310的,所以不需要额外添加依赖。

MappingJackson2HttpMessageConverter是springboot中的一个消息转换器,其部分Bean定义代码如下

// JacksonHttpMessageConvertersConfiguration.java
// ...
@Bean
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {
    return new MappingJackson2HttpMessageConverter(objectMapper);
}

ObjectMapper的定义如下

// JacksonAutoConfiguration.java
// ...
@Bean
@Primary
@ConditionalOnMissingBean
ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
    return builder.createXmlMapper(false).build();
}

通过上面的简要分析,可以知道,ObjectMapper是通过Jackson2ObjectMapperBuilder的build方法来生成,部分代码如下,重点在于configure方法

public  T build() {
    // ...
    configure(mapper);
    return (T) mapper;
}

public void configure(ObjectMapper objectMapper) {
    Assert.notNull(objectMapper, "ObjectMapper must not be null");

    MultiValueMap modulesToRegister = new LinkedMultiValueMap<>();
    // 是否让 Jackson 通过 JDK ServiceLoader 查找可用模块,默认false
    if (this.findModulesViaServiceLoader) {
        ObjectMapper.findModules(this.moduleClassLoader).forEach(module -> registerModule(module, modulesToRegister));
    }
    // 注册知名模块,默认为true,其中包括 Jdk8Module、JavaTimeModule
    else if (this.findWellKnownModules) {
        registerWellKnownModulesIfAvailable(modulesToRegister);
    }

    if (this.modules != null) {
        this.modules.forEach(module -> registerModule(module, modulesToRegister));
    }
    if (this.moduleClasses != null) {
        for (Class moduleClass : this.moduleClasses) {
            registerModule(BeanUtils.instantiateClass(moduleClass), modulesToRegister);
        }
    }
    List modules = new ArrayList<>();
    for (List nestedModules : modulesToRegister.values()) {
        modules.addAll(nestedModules);
    }
    objectMapper.registerModules(modules);
    // ......
}

所以,一般出现了请求体中的LocalDate报错,那多半是手动覆盖了ObjectMapper的Bean定义。

但有些时候,我们会自定义Jaskson工具类,这个时候,加一行代码即可解决,这个与Jackson2ObjectMapperBuilder中的findModulesViaServiceLoader = true基本上是一致的

objectMapper.findAndRegisterModules();

参考:https://github.com/spring-projects/spring-boot/issues/26859

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/970432.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号