问题描述
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 {/*** 扩展的消息转换器*/@Overridepublic 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>() {@Overridepublic 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>() {@Overridepublic 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>() {@Overridepublic 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>() {@Overridepublic 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);}
}
添加时间对象的消息处理器之后,返回前端的数据如下:
问题搞定!