SpringBoot
日期格式化处理(单独与全局)包括单独,与全局
Springboot
提供注解方式springboot默认提供,在需要的字段上使用
@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
这个方式每个字段都需要加有点过于麻烦。
Spring
自带注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
这个方式每个字段都需要加有点过于麻烦。
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
。
适合前后端都是
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
注解标注的时间格式为主。
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());
}
}
}
这种情况要和时间作为Json字符串时区别对待,因为前端json转后端
entity
底层使用的是Json序列化Jackson工具(HttpMessageConverter
);而时间字符串作为普通请求参数传入时,转换用的是Converter
,两者在处理方式上是有区别。非json请求的转换
实现 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