热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

接手离职老哥留下来的项目,有个大坑!用springboot处理全局日期格式化

最近部门几位同事受了一些委屈相继离职,共事三年临别之际颇有不舍,待一切手续办妥帖,寒暄过后送他们出公司,几个老哥临别时冲我鬼魅一笑,我顿时心里一紧有种不好的预感,这事绝对没有这么简

接手离职老哥留下来的项目,有个大坑!用springboot处理全局日期格式化

最近部门几位同事受了一些委屈相继离职,共事三年临别之际颇有不舍,待一切手续办妥帖,寒暄过后送他们出公司,几个老哥临别时冲我鬼魅一笑,我顿时心里一紧有种不好的预感,这事绝对没有这么简单。

等我接手这几个大佬的项目后,应验了我的预感,此刻我居然有点后悔,为啥送别之时没揍他们一顿!哈哈哈~

而这种打人的冲动,在我开始优化几位老哥的项目时候,变得越来越强烈。

技术部每个月都会组织一下代码走查及优化,以前是各自审查优化自己的项目,如今几位老哥的离职他们的项目就落到了我的头上。

对于程序员来说最痛苦的事情就是接手别人的项目,还要做优化改造,因为这一点也不比重构一遍项目简单。不过,军令在前,没办法硬着头皮上吧!

有个坑

第一个优化的点就让我有点崩溃,这几个大佬的技能能力很强,一直都是我学习的榜样,但在项目里几乎所有的日期格式化都这样用 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.Date 和 java.util.Calendar 不支持时区,且非线程安全,对于日期的计算相对繁琐,技术部一致要求用JDK1.8以后的 java.time LocalDateTime。但不少人还是在用 java.util.Date 和 java.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注解,重复的工作量也不小。接着往下看~

file

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 {
        @Override
        public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(value.format(ofPattern(pattern)));
        }
    }
​
    public class LocalDateTimeDeserializer extends JsonDeserializer {
        @Override
        public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException {
            return LocalDateTime.parse(p.getValueAsString(), ofPattern(pattern));
        }
    }
}

本文分享了一个Springboot项目开发过程中的一个小技巧,也顺便吐槽一下项目优化中遇到的坑。

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

文源网络,仅供学习之用,如有侵权,联系删除。

我将面试题和答案都整理成了PDF文档,还有一套学习资料,涵盖Java虚拟机、spring框架、Java线程、数据结构、设计模式等等,但不仅限于此。

关注公众号【java圈子】获取资料,还有优质文章每日送达。

file


推荐阅读
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因
    本文介绍了解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因。其中包括修改包名、解决service name重复、处理jar包冲突和添加maven依赖等解决方案。同时推荐了一个人工智能学习网站,该网站内容通俗易懂,风趣幽默,值得一看。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
author-avatar
手机用户2502937447
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有