使用 java.time.LocalDateTime(续):全局返回时间戳给前端

Java 8

PostgreSQL 14

spring-boot-starter-parent 2.7.3

mybatis-plus-boot-starter 3.4.3.4

--

ben发布于博客园

前文:使用 java.time.LocalDateTime

https://www.cnblogs.com/luo630/p/17077756.html

 

在 参考文档#1 中,提供了 返回时间类型给前端时 统一使用时间戳 的方案:修改 ObjectMapper。

本文在示例项目 bootweb 中实现了此方案。

ben发布于博客园

在 bootweb 中,自动生成了 名为 jacksonObjectMapper 的 bean,类型为:class com.fasterxml.jackson.databind.ObjectMapper,

位于 jackson-databind-2.13.3.jar 中(Spring Boot 自带)。

修改该 bean 的 serializerFactory 即可——单独处理 LocalDate、LocalDateTime 类型。

 

示例代码:DateBeanSerializerModifier.java

继承了 com.fasterxml.jackson.databind.ser.BeanSerializerModifier 类,其中包含 两个静态类 LocalDateConverter、LocalDateTimeConverter,分别用于转换 LocalDate、LocalDateTime。

照抄 参考资料#1

DateBeanSerializerModifier.java
 package com.lib.bootweb.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;

public class DateBeanSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
                                                     BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        for (BeanPropertyWriter bpw : beanProperties) {
            if (isLocalDateType(bpw)) {
                bpw.assignSerializer(new LocalDateConverter());
            } else if (isLocalDateTimeType(bpw)) {
                bpw.assignSerializer(new LocalDateTimeConverter());
            }
        }
        return beanProperties;
    }

    private boolean isLocalDateType(BeanPropertyWriter bpw) {
        Class<?> clazz = bpw.getType().getRawClass();
        return LocalDate.class.isAssignableFrom(clazz);
    }

    private boolean isLocalDateTimeType(BeanPropertyWriter bpw) {
        Class<?> clazz = bpw.getType().getRawClass();
        return LocalDateTime.class.isAssignableFrom(clazz);
    }

    public static class LocalDateConverter extends JsonSerializer<Object> {

        @Override
        public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            // +8 可以修改为本地的 TODO
            gen.writeNumber(((LocalDate)value).atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        }
    }

    public static class LocalDateTimeConverter extends JsonSerializer<Object> {

        @Override
        public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            // +8 可以修改为本地的 TODO
            gen.writeNumber(((LocalDateTime) value).toInstant(ZoneOffset.of("+8")).toEpochMilli());
        }
    }

}

 

修改 ObjectMapper:ben发布于博客园

本文采用在一个 ApplicationRunner 对象中实现。

package com.lib.bootweb.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * 修改默认的 ObjectMapper Bean
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class ModifyObjectMapperRunner implements ApplicationRunner {

    private final ObjectMapper objectMapper;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        objectMapper.setSerializerFactory(
                objectMapper.getSerializerFactory()
                        .withSerializerModifier(new DateBeanSerializerModifier()) // 上文的新类
        );
        log.info("ModifyObjectMapperRunner END");
    }
}

ben发布于博客园

测试的VO:SomeInfo20VO、SomeInfo21VO、SomeInfo22VO,后面两个有使用 @JsonFormat 注解。

ben发布于博客园

新增测试接口:/api/someInfo/getWithTyped

    @GetMapping(value = "getWithType")
    public Object getByIdWithType(@RequestParam String id, @RequestParam Integer type) {
        SomeInfoPO ent = someInfoService.getById(id);
        if (ent == null) {
            return null;
        }
        switch (type) {
            case 20:
                SomeInfo20VO ret4 = new SomeInfo20VO();
                BeanUtils.copyProperties(ent, ret4);
                return ret4;
            case 21:
                SomeInfo21VO ret5 = new SomeInfo21VO();
                BeanUtils.copyProperties(ent, ret5);
                return ret5;
            case 22:
                SomeInfo22VO ret6 = new SomeInfo22VO();
                BeanUtils.copyProperties(ent, ret6);
                return ret6;
            default:
                return null;
        }
    }

 

调用接口 /api/someInfo/getWithType,测试结果:ben发布于博客园

无论入参的 type 是 20、21、22,返回的 createTime 都是时间戳。

 

注意,

本文中修改 ObjectMapper bean 的方式还需优化 TODO

 

关于 java.util.Date 类型也返回时间戳给前端,仅需修改 Spring Boot 项目的配置即可:

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=true

即可。

 

---END---ben发布于博客园

 

本文链接:

https://www.cnblogs.com/luo630/p/17080130.html

ben发布于博客园

参考资料

1、SpringBoot中对于LocalDate和LocalDateTime如何返回时间戳

https://www.jianshu.com/p/21309e1a08be

2020.11.03 15:18:18

原文:http://tech.cnhnb.com/post/9

2、

 

ben发布于博客园

 

posted @ 2023-01-31 19:37  快乐的欧阳天美1114  阅读(982)  评论(0编辑  收藏  举报