SpringBoot日期格式化处理(单独与全局)

SpringBoot日期格式化处理(单独与全局)

包括单独,与全局

1. 单独配置

1.1 使用Springboot提供注解方式

springboot默认提供,在需要的字段上使用@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")

这个方式每个字段都需要加有点过于麻烦。

1.2. 使用Spring自带注解

@DateTimeFormat(pattern = "yyyy-MM-dd")

这个方式每个字段都需要加有点过于麻烦。

2. 全局配置

2.1 在配置文件上配置

spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
  • 支持(content-type=application/json)请求中格式为yyyy-MM-dd HH:mm:ss的字符串,后台用@RequestBody接收,及返回值date转为yyyy-MM-dd HH:mm:ss格式string;

  • 不支持(content-type=application/json)请求中yyyy-MM-dd等类型的字符串转为date;

  • 不支持java8日期api

2.2 使用配置类方式

适合前后端都是json格式交互。

只需要用@Configuration定义一个配置类,注入两个Bean即可完成全局日期响应格式化处理。

@Configuration
public class LocalDateTimeSerializerConfig {

    /** 注入配置文件格式化的格式 
    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;*/
    private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    /**
     *  注册响应json格式的LocalDateTime日期格式序列化器,指定格式
     *
     * @return LocalDateTimeSerializer
     * @author: zhihao
     * @date: 2020/4/14
     */
    @Bean
    public LocalDateTimeSerializer localDateTimeSerializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
    }

    /** 
     *  注册json请求方式的LocalDateTime反序列化器,指定格式
     *
     * @return LocalDateTimeDeserializer 
     * @author: zhihao
     * @date: 2020/4/14 
     */
    @Bean
    public LocalDateTimeDeserializer localDateTimeDeserializer() {
        return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
    }

    /**
     *  格式化日期类型,响应对应格式化日期字符串
     *
     * @return Jackson2ObjectMapperBuilderCustomizer
     * @author: zhihao
     * @date: 2020/4/14
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> {
            //返回json格式,前端序列化为字符串
            builder.serializerByType(LocalDateTime.class, localDateTimeSerializer());
            //从json对象日期字符串反序列化为日期对象
            builder.deserializerByType(LocalDateTime.class, localDateTimeDeserializer());
        };
    }
}

上面方式如果需要其他格式,那就需要配合@JsonFormat注解使用,在特定的字段属性添加@JsonFormat注解即可,因为@JsonFormat注解优先级比较高,会以@JsonFormat注解标注的时间格式为主。

2.3.使用Jackson解决

JSON请求的序列化和响应Json的反序列化, 适合前后端都是json格式交互。

根据官方文档 Custom JSON Serializers and Deserializers ,想要接管Jackson的JSON的序列化和反序列化,只需通过注解@JsonComponent来声明其静态内部类即可。

首先根据项目要求提供自定义的日期序列化器和反序列化器,其中包括:

  • DateJsonSerializer extends JsonSerializer 表示将LocalDateTime格式化为日期字符串。

  • DateJsonDeserializer extends JsonDeserializer 表示将日期字符串解析为LocalDateTime日期。

    使用注解@JsonComponent是直接处理String和LocalDateTime的相互转换的,所以要注意空串问题。

@JsonComponent
public class DateFormatConfig {

    /**
     * 响应json日期格式化
     */
    public static class DateJsonSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            jsonGenerator.writeString(localDateTime.format(formatter));
        }
    }

    /**
     * 解析json请求日期字符串
     */
    public static class DateJsonDeserializer extends JsonDeserializer<LocalDateTime> {

        @Override
        public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            return LocalDateTime.parse(jsonParser.getText());
        }
    }
}

2.4 GET请求及POST表单日期时间字符串格式转换

这种情况要和时间作为Json字符串时区别对待,因为前端json转后端entity底层使用的是Json序列化Jackson工具(HttpMessageConverter);而时间字符串作为普通请求参数传入时,转换用的是Converter,两者在处理方式上是有区别。

非json请求的转换

使用自定义参数转换器(Converter)

实现 org.springframework.core.convert.converter.Converter,自定义参数转换器,如下:

@Configuration
public class DateConverterConfig {
    
    private static final String YYYY_MM_DD = "yyyy-MM-dd";
    private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    
   /** 
     * 自定义类型转换,HTTP请求日期字符串转换日期类型,
     * 相当于以前设置进 ConversionServiceFactoryBean
     *
     * @return Converter
     * @author: zhihao
     * @date: 2020/4/14 
     */
    @Bean
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return new Converter<String, LocalDateTime>() {
            @Override
            public LocalDateTime convert(String source) {
                try {
                    return parse(source);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                throw new RuntimeException("日期解析错误");
            }
        };
    }

    /**
     * 根据字符串进行解析,将Date转LocalDateTime
     *
     * @param source 日期字符串
     * @return java.time.LocalDateTime
     * @author: zhihao
     * @date: 2020/4/14
     */
    public LocalDateTime parse(String source) throws ParseException {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        DateFormat format;
        source = source.trim();
        //判断是否yyyy-MM-dd格式
        if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
            format = new SimpleDateFormat(YYYY_MM_DD);
            Date date = format.parse(source);
            return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
            //判断是否yyyy-MM-dd HH:mm:ss格式
        }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){
            format = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
            Date date = format.parse(source);
            return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        }else {
            throw new IllegalArgumentException("Invalid false value " + source);
        }
    }
}

点评:以上两个bean会注入到spring mvc的参数解析器(好像叫做ParameterConversionService),当传入的字符串要转为LocalDateTime类时,spring会调用该Converter对这个入参进行转换。

参考了:

https://www.jianshu.com/p/f4654d251104

https://segmentfault.com/a/1190000022355979

你可能感兴趣的:(Java,SpringBoot,java)