浙江做网站,大同市建设工程质量监督站网站,游戏开发物语攻略,谷歌网站优化工具在部分场景中#xff0c;后台的时间属性用的不是Date或Long#xff0c;而是Instant#xff0c;Java8引入的一个精度极高的时间类型#xff0c;可以精确到纳秒#xff0c;但实际使用的时候不需要这么高的精确度#xff0c;通常到毫秒就可以了。
而在前后端传参的时候需要…在部分场景中后台的时间属性用的不是Date或Long而是InstantJava8引入的一个精度极高的时间类型可以精确到纳秒但实际使用的时候不需要这么高的精确度通常到毫秒就可以了。
而在前后端传参的时候需要对Instant类型进行序列化及反序列化等处理默认情况下ObjectMapper是不支持序列化Instant类型的需要注册JavaTimeModule才行而且序列化的结果也不是时间戳测试如下
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;import java.time.Instant;/*** Instant Jackson测试** author yangguirong*/
Slf4j
public class InstantTest {ObjectMapper objectMapper new ObjectMapper();Testvoid serializeTest() throws JsonProcessingException {objectMapper.registerModule(new JavaTimeModule());String str objectMapper.writeValueAsString(Instant.now());log.info(serializeTest: {}, str);// serializeTest: 1691208180.052185000}Testvoid deserializeTest() throws JsonProcessingException {objectMapper.registerModule(new JavaTimeModule());Instant instant objectMapper.readValue(1691208180.052185000, Instant.class);log.info(deserializeTest: {}, instant);// deserializeTest: 2023-08-05T04:03:00.052185Z}
}想要将其序列化为毫秒时间戳需要对序列化及反序列化进行自定义
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.slf4j.Slf4j;import java.io.IOException;
import java.time.Instant;/*** 自定义Instant序列化及反序列** author yangguirong*/
public class InstantMillsTimeModule extends SimpleModule {public InstantMillsTimeModule() {this.addSerializer(Instant.class, new InstantMillisecondsSerializer());this.addDeserializer(Instant.class, new InstantMillisecondsDeserializer());}public static class InstantMillisecondsSerializer extends JsonSerializerInstant {Overridepublic void serialize(Instant instant, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {if (instant null) {jsonGenerator.writeNull();} else {jsonGenerator.writeNumber(instant.toEpochMilli());}}}Slf4jpublic static class InstantMillisecondsDeserializer extends JsonDeserializerInstant {Overridepublic Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {try {long mills p.getValueAsLong();return mills 0 ? Instant.ofEpochMilli(mills) : null;} catch (Exception e) {log.error(Instant类型反序列化失败val: {}, message: {}, p.getText(), e.getMessage());}return null;}}
}再来测试一下自定义的序列化及反序列化方式
import com.example.websocket.config.InstantMillsTimeModule;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;import java.time.Instant;/*** Instant Jackson测试** author yangguirong*/
Slf4j
public class InstantTest {ObjectMapper objectMapper new ObjectMapper();Testvoid serializeTest() throws JsonProcessingException {objectMapper.registerModule(new JavaTimeModule());String str objectMapper.writeValueAsString(Instant.now());log.info(serialize: {}, str);// serialize: 1691208180.052185000}Testvoid deserializeTest() throws JsonProcessingException {objectMapper.registerModule(new JavaTimeModule());Instant instant objectMapper.readValue(1691208180.052185000, Instant.class);log.info(deserialize: {}, instant);// deserialize: 2023-08-05T04:03:00.052185Z}Testvoid millsSerializeTest() throws JsonProcessingException {objectMapper.registerModule(new InstantMillsTimeModule());String str objectMapper.writeValueAsString(Instant.now());log.info(millsSerializeTest: {}, str);// millsSerializeTest: 1691208541018}Testvoid millsDeserializeTest() throws JsonProcessingException {objectMapper.registerModule(new InstantMillsTimeModule());Instant instant objectMapper.readValue(1691208541018, Instant.class);log.info(millsDeserializeTest: {}, instant);// deserialize: 2023-08-05T04:09:01.018Z}
}可以看到结果是符合预期的可以在毫秒时间戳和Instant之间相互转换。
在后台配置SpringBoot的时候需要考虑两种情况一种就是Instant作为RequestParam/PathVariable的情况另一种是RequestBody/ResponseBody的情况。前者借助转换器实现配置如下
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.time.Instant;/*** web mvc设置** author yangguirong*/
Configuration
public class WebMvcConfig implements WebMvcConfigurer {Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(instantConvert());}public ConverterString, Instant instantConvert() {// 不能替换为lambda表达式return new ConverterString, Instant() {Overridepublic Instant convert(String source) {if (StringUtils.hasText(source)) {return Instant.ofEpochMilli(Long.parseLong(source));}return null;}};}
}后者如果是局部配置则在具体的实体类属性上添加JsonSerialize和JsonDeserialize注解在注解中指定序列化器和反序列化器即可。如果是全局配置则可以按照如下方式进行配置将InstantMillsTimeModule注册为Bean这个Bean会在JacksonAutoConfiguration中的StandardJackson2ObjectMapperBuilderCustomizer被自动注入然后进行注册。
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Jackson配置** author yangguirong*/
Configuration
AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonCustomizerConfig {Beanpublic Jackson2ObjectMapperBuilderCustomizer jacksonModuleRegistryCustomizer() {return jacksonObjectMapperBuilder - jacksonObjectMapperBuilder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, SerializationFeature.FAIL_ON_EMPTY_BEANS);}Beanpublic InstantMillsTimeModule instantMillsTimeModule() {return new InstantMillsTimeModule();}
}简单的接口测试
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import java.time.Instant;/*** instant测试** author yangguirong*/
Slf4j
RequestMapping(instant)
RestController
public class InstantTestController {GetMapping(getInstant)public Instant getInstant() {return Instant.now();}PutMapping(setInstant)public void setInstant(RequestParam Instant instant) {log.info(setInstant: {}, instant);}GetMapping(getInstantDemoVO)public DemoVO getInstantDemoVO() {return new DemoVO(Instant.now());}PutMapping(setInstantDemoVO)public void setInstantDemoVO(RequestBody DemoVO vo) {log.info(setInstantDemoVO:{}, vo);}DataNoArgsConstructorAllArgsConstructorstatic class DemoVO {private Instant instant;}
}