目录
1 时间格式化
1.1 出参格式化(Json)
创建一个测试类:
@Data
public class TestResponse {
@ApiModelProperty("未格式化时间")
private LocalDateTime localDateTime;
@ApiModelProperty("未格式化时间")
private LocalDate localDate;
@ApiModelProperty("未格式化时间")
private Date date;
}
restApi:
@GetMapping("test")
@ApiOperation("响应测试")
public TestResponse test(){
TestResponse response = new TestResponse();
response.setDate(new Date());
response.setLocalDateTime(LocalDateTime.now());
response.setLocalDate(LocalDate.now());
return response;
}
响应参数带Time的采用的是“ yyyy-MM-dd’T’HH:mm:ss.SSS ”格式,并且DATE默认使用的是UTC时间,比北京时间慢。
1.1.1 局部配置
在字段上加上注解@JsonFormat
@ApiModelProperty("已格式化时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime localDateTime;
@ApiModelProperty("已格式化时间")
@JsonFormat(pattern = "yyyy年MM月dd日")
private LocalDate localDate;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") //date默认使用UTC时间,北京时间得+8
@ApiModelProperty("已格式化时间")
private Date date;
@JsonFormat是jakson自带注解(spring家族默认使用jakson进行序列化与反序列化),常用属性如下:
属性 | 作用 |
---|---|
pattern | 格式化模板,如时间的’yyyy-MM-dd HH:mm:ss |
shape | 决定数据类型,如NUMBER、ARRAY,默认为ANY,任何类型 |
locale | 语言环境 |
timezone | 时区,默认为UTC |
在JSR310FormattedSerializerBase类createContextual方法中会检查序列化器,首先会获取目标对象字段上的JsonFormat,如果JsonFormat 不为空,会读取其属性值。根据属性值创建DateTimeFormatter对象,并将其设置为序列化器模板。
最终通过HttpMessageConverter接口实现类的子类MappingJackson2HttpMessageConverter输出响应。MappingJackson2HttpMessageConverter为默认的Json转换类。
也就是更改了LocalDateSerializer、LocalDateTimeSerializer:
1.1.2 全局配置
注释掉@JsomFormat:
1.1.2.1 yml配置文件中进行全局配置
spring:
jackson:
# 全局配置,但是对LocalDateTime和LocalDate无效
date-format: yyyy-MM-dd HH:mm:ss
# 时区
time-zone: GMT+8
重启,可以看到我们在配置文件中设置的格式与时区注入进了ObjectMapper.
因为未对LocalDateSerializer和LocalDateTimeSerializer进行改动,结果只对date生效。
1.1.2.2 编写配置类进行全局配置(推荐)
先取消上一步的配置
手写ObjectMapper配置类:
@Configuration
public class DateTimeConfiguration {
@Bean
public ObjectMapper initObjectMapper(){
ObjectMapper objectMapper=new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//JavaTimeModule 是jackson通过jsr310引入的JAVA8格式化类,没有此Module,序列化后的值会比较乱
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
}
运行结果同之前YML中配置一样:
所以LocalDateSerializer和LocalDateTimeSerializer中也得按我们需要的格式进行序列化:
@Bean
public ObjectMapper initObjectMapper(){
//自定义ObjectMapper配置并注册BEAN
ObjectMapper objectMapper=new ObjectMapper();
JavaTimeModule javaTimeModule=new JavaTimeModule();
//针对LocalDateTime和LocalDate
javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
//针对Date类
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//JavaTimeModule 是jackson通过jsr310引入的JAVA8格式化类,没有此Module,序列化后的值会比较乱
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
上面localdate字段未被全局序列化覆盖,因为字段上加了注解,说明局部优先于全局:
去掉注解:
也可以通过Jackson2ObjectMapperBuilder来构建新的ObjectMapper实例设置序列化与反序列化方式:
@Configuration
public class DateTimeConfiguration {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
//通过ObjectMapper构造器构建实例
return builder -> {
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //date格式,序列化和反序列化都是它
//序列化
builder.serializerByType(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
builder.serializerByType(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
//反序列化
builder.deserializerByType(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
builder.deserializerByType(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
};
}
// @Bean
// public ObjectMapper initObjectMapper(){ //自定义ObjectMapper配置并注册BEAN
// ObjectMapper objectMapper=new ObjectMapper();
// JavaTimeModule javaTimeModule=new JavaTimeModule();
// //针对LocalDateTime和LocalDate
// javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
// javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
// //针对Date类
// objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// //JavaTimeModule 是jackson通过jsr310引入的JAVA8格式化类,没有此Module,序列化后的值会比较乱
// objectMapper.registerModule(javaTimeModule);
// return objectMapper;
// }
}
1.2 入参格式化
1.2.1 json参数
创建测试接口
@PostMapping("body")
@ApiOperation("json请求测试")
public TestResponse body(@RequestBody TestResponse testResponse){
log.info("打印的body:{}",testResponse);
return testResponse;
}
因为LocalDateTimeDeserializer与LocalDateDeserializer默认格式模板分别为’yyyy-MM-ddTHH:mm:ss 、'yyyy-MM-dd '.
我们按照默认格式传输自然没问题:
1.2.1.1 局部配置
同样,我们也可以像局部序列化一样局部反序列化时间。
还是使用@JsonFormat注解(序列化与反序列化一致),此时,标了注解字段全局序列化配置失效:
@ApiModelProperty("已格式化时间")
@JsonFormat(pattern = "yyyy年MM月dd日HH时mm分ss秒")
private LocalDateTime localDateTime;
@ApiModelProperty("已格式化时间")
@JsonFormat(pattern = "yyyy年MM月dd日")
private LocalDate localDate;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS") //date默认使用UTC时间,北京时间得+8
@ApiModelProperty("已格式化时间")
private Date date;
同序列化时相同,JSR310DateTimeDeserializerBase反序列化时也是读取注解中的属性值,创建新的JsonDeserializer(包括LocalDateTimeDeserializer、LocalDateDeserializer等)
1.2.1.2 全局配置
序列化我们用了全局配置,反序列化自然也应该使用全局配置
去掉注解:
再已有全局配置加上反序列化方式:
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //date格式,序列化和反序列化都是它
//序列化
builder.serializerByType(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
builder.serializerByType(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
//反序列化
builder.deserializerByType(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
builder.deserializerByType(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
};
}
自然也可以自定义并注册ObjectMapper到BEAN
@Bean
public ObjectMapper initObjectMapper(){
//自定义ObjectMapper配置并注册BEAN
ObjectMapper objectMapper=new ObjectMapper();
JavaTimeModule javaTimeModule=new JavaTimeModule();
//针对LocalDateTime和LocalDate
//序列化
javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
//反序列化
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//针对Date类 序列化和反序列化都是它
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//JavaTimeModule 是jackson通过jsr310引入的JAVA8格式化类,没有此Module,序列化后的值会比较乱
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
// @Bean
// public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
// return builder -> {
// builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //date格式,序列化和反序列化都是它
// //序列化
// builder.serializerByType(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
// builder.serializerByType(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
// //反序列化
// builder.deserializerByType(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
// builder.deserializerByType(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
// };
// }
1.2.2 非json参数
将接口改入参改成非JSON类型
@PostMapping("param")
@ApiOperation("普通参数请求测试")
public TestResponse body(TestResponse testResponse){
try {
log.info("打印的param:{}",testResponse);
} catch (Exception e) {
e.printStackTrace();
}
return testResponse;
}
此时我们配置的json反序列化方式是无效的
1.2.2.1 局部配置
我们再字段上加上注解@DateTimeFormat
@ApiModelProperty("已格式化时间")
@DateTimeFormat(pattern = "yyyy年MM月dd日HH时mm分ss秒")
private LocalDateTime localDateTime;
@ApiModelProperty("已格式化时间")
@DateTimeFormat(pattern = "yyyy年MM月dd日")