SpringBoot 全局时间格式处理

参考学习这几个

https://blog.csdn.net/weixin_44600430/article/details/105512891
https://www.jianshu.com/p/f4654d251104

使用配置类

因为目前前后端大多是通过json格式交互。
只需要用@Configuration定义一个配置类,注入两个Bean即可完成全局日期响应格式化处理。

import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@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 成大事
     * @since 2022/7/23 14:16
     */
    @Bean
    public LocalDateTimeSerializer localDateTimeSerializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
    }

    /**
     *  注册json请求方式的LocalDateTime反序列化器,指定格式
     *
     * @return LocalDateTimeDeserializer
     * @author 成大事
     * @since 2022/7/23 14:16
     */
    @Bean
    public LocalDateTimeDeserializer localDateTimeDeserializer() {
        return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
    }

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

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

使用jackson解决

JSON请求的序列化和响应Json的反序列化, 适合前后端都是json格式交互。
根据官方文档Custom JSON Serializers and Deserializers ,想要接管JacksonJSON的序列化和反序列化,只需通过注解@JsonComponent来声明其静态内部类即可。

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.jackson.JsonComponent;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@JsonComponent
public class DateFormatConfig {
    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 日期格式化
     */
    public static class DateJsonSerializer extends JsonSerializer<Date> {
        @Override
        public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(dateFormat.format(date));
        }
    }

    /**
     * 解析日期字符串
     */
    public static class DateJsonDeserializer extends JsonDeserializer<Date> {
        @Override
        public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            try {
                return dateFormat.parse(jsonParser.getText());
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }

        }
    }
    
}

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

这种情况要和时间作为Json字符串时区别对待,因为前端json转后端entity底层使用的是Json序列化Jackson工具(HttpMessageConverter<T>);而时间字符串作为普通请求参数传入时,转换用的是Converter<S, T>,两者在处理方式上是有区别。
使用自定义参数转换器(Converter)
实现 org.springframework.core.convert.converter.Converter,自定义参数转换器,如下:

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

@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<java.lang.String,java.util.Date>
     * @author 成大事
     * @since 2022/7/23 14:16
     */
    @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 成大事
     * @since 2022/7/23 14:16
     */
    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对这个入参进行转换。
总结一下:
我建议直接三个配置都添加。如果只是用第一个的话会发现没有转换。我的实体类的时间的Date
在这里插入图片描述
所以建议大家都写上

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值