问题描述
SpringBoot 项目,当返回前端的数据类型为 Map
的时候,在 Map
中 put() 时间对象会出现以下问题:
- 传递的
Date
对象会变成时间戳 - 传递的
LocalDateTime
对象会变成数组
问题复现
编写一个 Controller 方法,返回值为 Map
,分别 put() Date
对象和 LocalDateTime
对象。
@RestController
@RequestMapping("test")
public class TestController {
@ApiOperation("t1")
@GetMapping("t1")
public Map<String, Object> t1() {
return new HashMap<String , Object>(){{
put("java.util.Date", new Date());
put("java.time.LocalDate", LocalDate.now());
put("java.time.LocalTime", LocalTime.now());
put("java.time.LocalDateTime", LocalDateTime.now());
}};
}
}
访问接口,获得的数据如下,可以看到 Date
对象被转换成时间戳,而 LocalDateTime
对象被转换成数组。
解决问题
在上面复现问题时,我们发现 Date
、LocalDate
、LocalTime
、LocalDateTime
对象数据在返回给前端的时候,并不是我们预期想要的值,在 SpringBoot 中,支持我们自定义对象类型的消息转换器,可以分别为各种对象的数据进行格式化,下面案例对 Date
、LocalDate
、LocalTime
、LocalDateTime
四个对象进行消息转换。
创建自定义消息处理器可以通过重写 WebMvcConfigurer.extendMessageConverters()
方法来实现,代码如下:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
/**
* @author jiale
*/
@Configuration // 配置注解记得加上
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 扩展的消息转换器
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
/*
* 解决 LocalDateTime 返回给前端会变成数组的问题
*/
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = converter.getObjectMapper();
// 不显示为 null 的字段
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
SimpleModule module = new SimpleModule();
// Date 消息转换器
module.addSerializer(Date.class, new JsonSerializer<Date>() {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
// 对时间进行格式化,返回数据为字符串类型
jsonGenerator.writeString(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
}
});
// LocalDate 消息转换器
module.addSerializer(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(DateTimeFormatter.ofPattern("yyyy-MM-dd").format(localDate));
}
});
// LocalTime 消息转换器
module.addSerializer(LocalTime.class, new JsonSerializer<LocalTime>() {
@Override
public void serialize(LocalTime localTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(DateTimeFormatter.ofPattern("HH:mm:ss").format(localTime));
}
});
// LocalDateTime 消息转换器
module.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
@Override
public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(localDateTime));
}
});
// 如果还需要其它对象的消息转换器,就继续通过 module.addSerializer() 添加
mapper.registerModule(module);
converter.setObjectMapper(mapper);
// SpringBoot 默认提供了好多个消息转换器,这里把我们自定义的消息转换器放首个位置
converters.add(0, converter);
}
}
添加时间对象的消息处理器之后,返回前端的数据如下:
问题搞定!