Closed bfchengnuo closed 5 years ago
补充,SpringBoot 中对 Jackson 的一些使用:
spring:
jackson:
# 全局格式化标准
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
# 忽略 null 值的输出
default-property-inclusion: non_null
# 返回时间戳
# serialization:
# write-dates-as-timestamps: true
使用 @JsonSerialize(using = Date2LongSerializer.class)
来指定转换规则,例如毫秒转换为秒:
public class Date2LongSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeNumber(date.getTime() / 1000);
}
}
如果使用的是 @RequestBody
的情况下时间戳是 yyyy-MM-dd 格式的日期,Jackson 会自动识别并且转换成功,若是 yyyy-MM-dd HH:mm:ss 这种格式的日期字符串的话,Jackson 无法自动转换成 Date 类型。
解决方案可以在字段上使用 @JsonFormat
,但如果要兼容多种格式,则需要使用 @JsonDeserialize
来自定义转换规则。
当然,最小耦合的方法是重写 Jackson 的日期转换器,适应各种格式。
现在,整理下最常用的几种方案:
@DateTimeFormat(pattern = “yyyy-MM-dd HH:mm:ss”)
注解在实体字段上附:
# 方案 3 配置示例:
spring.jackson.date-format = yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone = GMT+8
spring.mvc.date-format = yyyy-MM-dd HH:mm:ss
// 方案 4,写在 controller 中
@InitBinder
public void initBinder(ServletRequestDataBinder binder) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
}
// 方案 5
@Component
public class DateConverterConfig implements Converter<String, Date> {
private static final List<String> formarts = new ArrayList<>(4);
static{
formarts.add("yyyy-MM");
formarts.add("yyyy-MM-dd");
formarts.add("yyyy-MM-dd hh:mm");
formarts.add("yyyy-MM-dd hh:mm:ss");
}
@Override
public Date convert(String source) {
String value = source.trim();
if ("".equals(value)) {
return null;
}
if(source.matches("^\\d{4}-\\d{1,2}$")){
return parseDate(source, formarts.get(0));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
return parseDate(source, formarts.get(1));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")){
return parseDate(source, formarts.get(2));
}else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){
return parseDate(source, formarts.get(3));
}else {
throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
}
}
/**
* 格式化日期
* @param dateStr String 字符型日期
* @param format String 格式
* @return Date 日期
*/
public Date parseDate(String dateStr, String format) {
Date date=null;
try {
DateFormat dateFormat = new SimpleDateFormat(format);
date = dateFormat.parse(dateStr);
} catch (Exception e) {
}
return date;
}
}
需要注意的是,在某些情况下,例如使用 feign 调用、MQ 传输,某些方式的配置可能会失效,例如配置文件中配置的就可能会失效,这个需要自行确认。
https://www.jianshu.com/p/2a8c31480c5d https://blog.csdn.net/eumenides_/article/details/79033505
因为 SpringBoot 的黑箱问题,如果不熟悉 SB 的源码或者流程,会比较蛋疼,比如我。。。
因为用到了 Swagger,我通过继承 WebMvcConfigurationSupport 的 addResourceHandlers 方法进行了对静态资源文件的过滤,保证其可访问; 然而,这导致了配置文件中配置的日期转换失效。。。 修正方法:
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
super.addResourceHandlers(registry);
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
.indentOutput(true)
.dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
// JDK8 新特性,可选择多个模块
.modulesToInstall(new ParameterNamesModule());
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
/**
* 自动转换时间格式
*
* @param registry date
*/
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
}
}
参考:https://blog.csdn.net/qq_25610165/article/details/78696060
原文是使用 @EnableWebMvc 后、implements WebMvcConfigurer 后导致的失效。
Spring 提供的数据格式化有很多,例如数字相关的 @NumberFormat(pattern=“#.##”)
就是有两位小数的。
最常用的两个注解:
@DateTimeFormat
和@JsonFormat
@DateTimeFormat
转换前端 String 类型到后端 Date 类型。@JsonFormat
转换后端 Date 类型到前端 String 类型,如果只用到此注解,加到属性上或者方法上都可以; 如果跟@DateTimeFormat
配合使用,此注解添加到 getter 方法上面,注意加timezone="GMT+8"
示例: