弃Date转LocalDateTime
以前用的是Date作为时间组件,Spring MVC会自动进行 Date<--->时间戳---> 的转换,然而新项目换成Jdk8新日期时间Api
,就不会自动转换成时间戳了,如果强行接收时间戳给新日期时间Api
则会直接报400。如果直接返回新日期时间Api
则会返回类似下图的结果,这可能不是我们想要的,前端处理起来也没有时间戳来得方便。
Java8全新日期时间API
Instant 它代表的是时间戳
LocalDate 不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。
LocalTime 它代表的是不含日期的时间
LocalDateTime 它包含了日期及时间,不过还是没有偏移信息或者说时区。
ZonedDateTime 这是一个包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。
如果我们要让框架支持新时间,我们可以自己写序列化与反序列化。
pom引入jar包。
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jdk8</artifactId> <version>2.9.9</version> </dependency>
|
定义LocalDateTime序列化组件。
package vc.thinker.userservice.common;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException; import java.time.*;
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
public static final LocalDateTimeSerializer INSTANCE;
static { INSTANCE = new LocalDateTimeSerializer(); }
private LocalDateTimeSerializer() { }
private static final ZoneOffset CURRENT_ZONE_OFFSET = ZoneOffset.ofHours(8);
@Override public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeNumber(localDateTime.toInstant(CURRENT_ZONE_OFFSET).toEpochMilli()); } }
|
package vc.thinker.userservice.config;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.google.common.collect.Lists; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import vc.thinker.userservice.common.LocalDateTimeDeserializer; import vc.thinker.userservice.common.LocalDateTimeSerializer;
import java.nio.charset.Charset; import java.time.LocalDateTime; import java.util.List;
@Configuration public class WebConfig implements WebMvcConfigurer {
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { List<HttpMessageConverter<?>> myConverters = Lists.newArrayList(); MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(); jacksonConverter.setPrettyPrint(true);
jacksonConverter.setObjectMapper(new ObjectMapper() .registerModules(new JavaTimeModule() .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE) .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE) ) .setSerializationInclusion(JsonInclude.Include.NON_NULL));
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("utf-8"));
myConverters.add(stringHttpMessageConverter); myConverters.add(jacksonConverter); myConverters.addAll(converters); converters.clear(); converters.addAll(myConverters); } }
|
配置之后效果
反序列化
以上示例只是说明了怎么去定义并且添加转换组件到spring中,以及怎么将返回数据类型为LocalDateTime的情况自动转换为时间戳。然而我们还需要让转换器支持从前端接收的时间戳。
虽然已经用new JavaTimeModule() 就可以自动识别接收的时间戳了,但是前端有可能是传一个字符串类型的时间戳,所以我们还要再定义一个反序列化组件来适配,最后记得像序列化组件一样注册即可。
下面贴上我的反序列化:
package vc.thinker.userservice.common;
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset;
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
public static final LocalDateTimeDeserializer INSTANCE;
static { INSTANCE = new LocalDateTimeDeserializer(); }
private LocalDateTimeDeserializer() { }
private static final ZoneOffset CURRENT_ZONE_OFFSET = ZoneOffset.ofHours(8);
@Override public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { return Instant.ofEpochMilli(Long.valueOf(jsonParser.getText())).atZone(CURRENT_ZONE_OFFSET).toLocalDateTime(); } }
|
- LocalDate、LocalTime、ZonedDateTime也是类似的适配方式,可以按需适配。