springboot项目自定义序列化和反序列化器实现LocalDateTime转时间戳

文章目录

    • 自定义配置类
    • 接口代码
    • 接口测试
    • 举一反三:注解实现脱敏
    • 总结

在Spring Boot项目中,我们经常需要处理日期时间相关的数据。为了方便地进行日期时间的存储和传输,我们可以使用Java 8中的LocalDateTime类。本文将介绍如何在Spring Boot项目中自定义序列化和反序列化器,实现LocalDate,LocalDateTime与时间戳之间的转换。
objectMapper.registerModule 是 Jackson 库中的一个方法,用于注册自定义的模块。Jackson 是一个用于处理 JSON 数据的 Java 库,它提供了很多功能,如将 Java 对象转换为 JSON 字符串,或将 JSON 字符串转换为 Java 对象。通过注册自定义模块,可以扩展 Jackson 的功能。

自定义配置类

创建一个配置类JacksonLocalDateConfig,代码如下:

@Configuration
public class JacksonLocalDateConfig {

    @Bean
    public ObjectMapper objectMapper() {
        // 注册自定义序列化器
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new SimpleModule()
                .addDeserializer(LocalDateTime.class, new DateTimeDeserializerSerializer())
                .addDeserializer(LocalDate.class, new DateDeserializerSerializer())
                .addSerializer(LocalDateTime.class, new DateTimeSerializer())
                .addSerializer(LocalDate.class, new DateSerializer()));
        return objectMapper;
    }

    public static class DateTimeSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            long formattedDate = LocalDateTimeUtil.toEpochMilli(localDateTime);
            jsonGenerator.writeNumber(formattedDate);
        }
    }

    public static class DateSerializer extends JsonSerializer<LocalDate> {
        @Override
        public void serialize(LocalDate localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            long formattedDate = LocalDateTimeUtil.toEpochMilli(localDateTime);
            jsonGenerator.writeNumber(formattedDate);
        }
    }

    public static class DateTimeDeserializerSerializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext text) throws IOException, JacksonException {
            long timestamp = jsonParser.getValueAsLong();
            return LocalDateTimeUtil.of(timestamp);
        }
    }

    public static class DateDeserializerSerializer extends JsonDeserializer<LocalDate> {
        @Override
        public LocalDate deserialize(JsonParser jsonParser, DeserializationContext text) throws IOException, JacksonException {
            long timestamp = jsonParser.getValueAsLong();
            return Instant.ofEpochMilli(timestamp)
                    .atZone(ZoneId.systemDefault()).toLocalDate();
        }
    }
}

解析:SimpleModule 是 Jackson 库中的一个类,用于创建自定义的序列化和反序列化模块。通过使用 SimpleModule,你可以为特定的 Java 类型添加自定义的序列化和反序列化逻辑。这样,Jackson 在处理这些类型的对象时,会使用你定义的逻辑而不是默认的实现。
方法内部使用了registerModule方法注册了一个SimpleModule模块:

  1. 通过addDeserializer方法为LocalDateTime类添加了一个自定义的反序列化器DateTimeDeserializerSerializer。
  2. 通过addDeserializer方法为LocalDate类添加了一个自定义的反序列化器DateDeserializerSerializer。
  3. 通过addSerializer方法为LocalDateTime类添加了一个自定义的序列化器DateTimeSerializer。
  4. 通过addSerializer方法为LocalDate类添加了一个自定义的序列化器DateSerializer。
    其中,Instant.ofEpochMilli() 是 Java 8 中的一个静态方法,用于将自1970年1月1日(UTC)以来的毫秒数转换为 Instant 对象。
//测试方法;毫秒转localdate
public static void main(String[] args) {
        LocalDate localDate = Instant.ofEpochMilli(1700817717256l)
                .atZone(ZoneId.systemDefault()).toLocalDate();
        System.out.println(localDate);//2023-11-24
    }

LocalDateTimeUtil 是hutool 工具类的方法,LocalDateTimeUtil.toEpochMilli(localDateTime) 用于 localdate等类型转换为 时间戳。

接口代码

写一个controller:

@RequestMapping
@RestController
public class AppController {

    @GetMapping("/test")
    public Abount test() {
        Abount abount = new Abount();
        abount.setId(IdUtil.fastUUID());
        abount.setCreateDateTime(LocalDateTime.now());
        abount.setCreateDate(LocalDate.now());
        return abount;
    }

    @PostMapping("/postTest")
    public Abount test(@RequestBody Abount abount) {
        return abount;
    }
}

abount类为:

@Data
public class Abount {

    private String id;

    private LocalDateTime createDateTime;

    private LocalDate createDate;

}

接口测试

以get请求,路径:http://localhost:8080/test,接口返回:

{
    "id": "af6ca269-5807-4716-89f1-d8a425fb1245",
    "createDateTime": 1700874903392,
    "createDate": 1700841600000
}

以post请求,路径:http://localhost:8080/postTest,比如数据为:

{
    "id": "9bca316e-50c0-4552-9632-b6c59374bc0c",
    "createDateTime": 1700817717256,
    "createDate": 1700755200000
}

接口返回:

{
	"id": "9bca316e-50c0-4552-9632-b6c59374bc0c",
	"createDateTime": 1700817717256,
	"createDate": 1700755200000
}

举一反三:注解实现脱敏

可以依靠上述方式直接实现一个手机号,用户名的脱敏。需要用到hutool脱敏工具类方法:DesensitizedUtil.mobilePhone

  1. 创建一个自定义的序列化器类,实现JsonSerializer接口。
  2. 在自定义序列化器类中,重写serialize方法,将手机号对象转换为脱敏手机号码。
  3. 在需要使用自定义序列化器的类上,添加@JsonSerialize(using = PhoneDesensitizedSerializer.class)注解。

实现代码如下:

  1. 创建自定义序列化器类PhoneDesensitizedSerializer:
public class PhoneDesensitizedSerializer extends JsonSerializer<String> {
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        String encryptedPhoneNumber = DesensitizedUtil.mobilePhone(value);
        gen.writeString(encryptedPhoneNumber);
    }
}

  1. 在需要使用自定义序列化器的类上添加@JsonSerialize(using = PhoneDesensitizedSerializer.class)注解:
@Data
public class MyClass {

    @JsonSerialize(using = PhoneDesensitizedSerializer.class)
    private String mobile;
}

验证接口:

 @GetMapping("/test")
    public MyClass test() {
        MyClass abount = new MyClass();
        abount.setMobile("13512342210");
        return abount;
  }

返回:135****2210

总结

自定义序列化和反序列化器允许更精细的控制序列化过程。开发人员可以自定义序列化和反序列化的逻辑,根据具体需求进行配置,使得对象以最符合业务需求的方式被转换和恢复。

你可能感兴趣的:(java,spring,boot)