zoukankan      html  css  js  c++  java
  • 真没想到,Springboot能这样做全局日期格式化,有点香!

    最近面了一些公司,有一些 Java方面的架构、面试资料,有需要的小伙伴可以在公众号【程序员内点事】里,无套路自行领取


    说在前边

    最近部门几位同事受了一些委屈相继离职,共事三年临别之际颇有不舍,待一切手续办妥帖,寒暄过后送他们出公司,几个老哥临别时冲我鬼魅一笑,我顿时心里一紧有种不好的预感,这事绝对没有这么简单。等我接手这几个大佬的项目后,应验了我的预感,此刻我居然有点后悔,为啥送别之时没揍他们一顿!哈哈哈~ 而这种打人的冲动,在我开始优化几位老哥的项目时候,变得越来越强烈。

    在这里插入图片描述

    有个坑

    技术部每个月都会组织一下代码走查及优化,以前是各自审查优化自己的项目,如今几位老哥的离职他们的项目就落到了我的头上。对于程序员来说最痛苦的事情就是接手别人的项目,还要做优化改造,因为这一点也不比重构一遍项目简单。不过,军令在前,没办法硬着头皮上吧!

    第一个优化的点就让我有点崩溃,这几个大佬的技能能力很强,一直都是我学习的榜样,但在项目里几乎所有的日期格式化都这样用 SimpleDateFormat ,像如下代码这样实现,emm~ ,受过伤的男人怎么啥事都做的出来,哈哈哈~

    SvcOrderDailyStatisticsPo orderDailyStatisticsPo = new SvcOrderDailyStatisticsPo();
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    Date stationTime = dateFormat.parse(dateFormat.format(svcWorkOrderPo.getPayEndTime()));
    orderDailyStatisticsPo.setStatisticalDate(stationTime);
    

    而且项目中的时间和日期API用的也比较混乱,考虑到 java.util.Datejava.util.Calendar 不支持时区,且非线程安全,对于日期的计算相对繁琐,技术部一致要求用JDK1.8以后的 java.time LocalDateTime。但不少人还是在用 java.util.Datejava.util.Calendar 处理日期。

    优化方案

    时间格式化是使用频率非常高的,如何让时间格式化变得既简单又不用重复造轮子,那么就应将它抽象出来,作为全局的日期格式化处理,下面就结合实践简单介绍下几种优化方案。

    测试地址:http://127.0.0.1:8080/timeTest

    
    @GetMapping("/timeTest")
        public OrderInfo timeTest() {
            OrderInfo order = new OrderInfo();
            order.setCreateTime(LocalDateTime.now());
            order.setUpdateTime(new Date());
            return order;
        }
    
    1、@JsonFormat注解

    使用@JsonFormat注解格式化时间,应该算是一个基本操作了,大部分开发者都应用此种方式,简单方便。

    /**
     * @Author: xiaofu
     * @Description:
     */
    public class OrderInfo {
    
        @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime createTime;
    
        @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
        private Date updateTime;
    
        public LocalDateTime getCreateTime() {
            return createTime;
        }
    
        public void setCreateTime(LocalDateTime createTime) {
            this.createTime = createTime;
        }
    
        public Date getUpdateTime() {
            return updateTime;
        }
    
        public void setUpdateTime(Date updateTime) {
            this.updateTime = updateTime;
        }
    }
    

    测试一下结果,发现 Date 类型和 LocalDateTime 类型都格式化成功,但还是有个问题,这样做仍然比较繁琐,每个实体类的日期字段都要加@JsonFormat注解,重复的工作量也不小。接着往下看~
    在这里插入图片描述

    2、全局配置 (1)

    Springboot 已经为我们提供了日期格式化 ${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss},这里我们需要进行全局配置,配置比较简单,也无需在实体类属性上添加@JsonFormat注解。

    /**
     * @Author: xiaofu
     * @Description:
     */
    public class OrderInfo {
    
        //@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime createTime;
    
        //@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
        private Date updateTime;
    
        public LocalDateTime getCreateTime() {
            return createTime;
        }
    
        public void setCreateTime(LocalDateTime createTime) {
            this.createTime = createTime;
        }
    
        public Date getUpdateTime() {
            return updateTime;
        }
    
        public void setUpdateTime(Date updateTime) {
            this.updateTime = updateTime;
        }
    }
    
    

    只需要用@Configuration定义一个配置类,注入两个Bean即可完成全局日期格式化处理,这种方式也是当前我项目中正在用的方式。

    /**
     * @Author: xiaofu
     * @Description:
     */
    @Configuration
    public class LocalDateTimeSerializerConfig {
    
        @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
        private String pattern;
    
        @Bean
        public LocalDateTimeSerializer localDateTimeDeserializer() {
            return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
        }
    
        @Bean
        public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
            return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());
        }
    }
    

    这种方式可支持 Date 类型和 LocalDateTime 类型并存,那么有一个问题就是现在全局时间格式是yyyy-MM-dd HH:mm:ss,但有的字段却需要yyyy-MM-dd格式咋整?

    那就需要配合@JsonFormat注解使用,在特定的字段属性添加@JsonFormat注解即可,因为@JsonFormat注解优先级比较高,会以@JsonFormat注解标注的时间格式为主。

    3、全局配置 (2)

    这种全局配置的实现方式与上边的效果是一样的,不过,要注意的是使用这种配置后,字段手动配置@JsonFormat注解将不再生效。

    /**
     * @Author: xiaofu
     * @Description:
     */
    public class OrderInfo {
    
        //@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime createTime;
    
        //@JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
        private Date updateTime;
    
        public LocalDateTime getCreateTime() {
            return createTime;
        }
    
        public void setCreateTime(LocalDateTime createTime) {
            this.createTime = createTime;
        }
    
        public Date getUpdateTime() {
            return updateTime;
        }
    
        public void setUpdateTime(Date updateTime) {
            this.updateTime = updateTime;
        }
    }
    
    
    /**
     * @Author: xiaofu
     * @Description:
     */
    @Configuration
    public class LocalDateTimeSerializerConfig {
    
        @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
        private String pattern;
    
        @Bean
        @Primary
        public ObjectMapper serializingObjectMapper() {
            ObjectMapper objectMapper = new ObjectMapper();
            JavaTimeModule javaTimeModule = new JavaTimeModule();
            javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
            javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
            objectMapper.registerModule(javaTimeModule);
            return objectMapper;
        }
    
        public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
            @Override
            public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                gen.writeString(value.format(ofPattern(pattern)));
            }
        }
    
        public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
            @Override
            public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException {
                return LocalDateTime.parse(p.getValueAsString(), ofPattern(pattern));
            }
        }
    }
    

    总结

    分享了一个Springboot项目开发过程中的一个小技巧,也顺便吐槽一下项目优化中遇到的坑,优化别的人的代码虽然是一件比较痛苦的事情,但在这个过程中确实能学习到很多技巧,对个人的技能提升也是很有帮助,因为都是些能够实实在在提高开发效率的干货。


    小福利:

    几百本各类技术电子书相送 ,嘘~,免费 送给小伙伴们。关注公众号回复【666】自行领取

  • 相关阅读:
    人生
    问模板函数、函数模板,模板类、类模板的区别的问题?
    李清照
    重师者王,重友者霸,重己者亡
    C++ Primer(第4版)习题解答
    C#设计模式(1)转载
    C#设计模式(5)
    C#设计模式(2)
    C# 编码规范和编程好习惯
    C#设计模式(4)
  • 原文地址:https://www.cnblogs.com/chengxy-nds/p/12691541.html
Copyright © 2011-2022 走看看