我的编程空间,编程开发者的网络收藏夹
学习永远不晚

@DateTimeFormat的作用有哪些

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

@DateTimeFormat的作用有哪些

本篇内容主要讲解“@DateTimeFormat的作用有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“@DateTimeFormat的作用有哪些”吧!

本文提纲

@DateTimeFormat的作用有哪些

版本约定

  • Spring Framework:5.3.x

  • Spring Boot:2.4.x

正文

Spring中的转换器、格式化器是整个Spring技术栈体系中非常重要的一份子,是众多高级特性的基础支撑。

作为一个Spring的使用者,也许你工作了好几年都只接触到@DateTimeFormat这个注解才感知到Spring是有格式化能力的;也许你在使用xml配置、Spring  MVC时全然不知自动化封装的流程,也就感知不到Converter转换器模块的存在;也许你还一直不确定@DateTimeFormat能标注在哪些类型上,每次使用时都得用谷歌百度一下......

作为一个Spring的开发者,以上不应该再成为问题。而是能说会道,滚瓜烂熟。下面将本文补充内容传递给你,坐稳发车喽。

@DateTimeFormat注解到底做了什么?

不用猜,很多程序员同学知道/使用@DateTimeFormat注解是在Spring  MVC场景,甚至只是在此场景:前端传一个日期时间格式的值,后端使用Date/LocalDateTime接收此值时使用。

Request的请求实体形如这样:

@Data public class Person{    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")  private LocalDateTime arriveTime; }

这么一来,前端传入"2021-03-07 21:00:00"这种格式的字符串就能被自动封装进arriveTime了。

说明:String -> LocalDateTime arriveTime属于Parser功能(也称作输入),此注解在xxx ->  String输出时(Printer功能)也会生效的?

使用了@DateTimeFormat这么久,你是否知道它并不属于spring-web/spring-webmvc模块的类,而是属于spring-context:org.springframework.format.annotation.DateTimeFormat。换句话讲:@DateTimeForma它属于基础设施类,并不是只能用于web层,而是可用于所有有需要转换的地方。

通过上篇文章  我们知道了,@DateTimeFormat和@NumberFormat注解的功能底层是依赖于AnnotationFormatterFactory以及格式化器注册中心FormatterRegistry核心API去完成的。那么这个流程是怎样的呢?

可能这么说还是觉得比较抽象,那么我尝试画了一幅流程图,可助你掌握这部分的核心工作原理(执行流程):

@DateTimeFormat的作用有哪些

该流程可释义为:通过格式化器注册中心FormatterRegistry的API向其注册注解工厂AnnotationFormatterFactory以支持格式化注解。但是,底层其实都(为每个FieldType类型)适配为了Converter才注册到FormatterRegistry进去的。换句话讲:FormatterRegistry(其实是ConverterRegistry)底层管理的永远是一些简单的Converter转换器们,这便也符合了越底层越抽象,越上层越具体的设计原则,是一种良好的设计方案。

值得注意:ConverterRegistry管理的底层这些Converter是分为三大类的哟。1:1、1:N、N:N?

向注册中心注册完成后,转换服务就具备了AnnotationFormatterFactory所支持的类型FieldType <->  String互相转换的能力了。当然喽,让其能执行转换动作还有个前提条件是FieldType上必须标注有AnnotationFormatterFactory指定的注解类型才行,这个时候@DateTimeFormat就发挥作用啦。

这么来看,@DateTimeFormat注解自己其实并未做什么,只是纯被当做Field上的一个元数据被用作参与判断、格式化时所需参数的指定,此注解它是面向开发者的。真正做了“很多事”的其实是AnnotationFormatterFactory和FormatterRegistry等底层核心API,它们在初始化阶段就默默全部完成,而这一切(较为复杂)的逻辑对开发者是完全透明的。

JSR 310日期时间注册员

上篇文章  介绍了Spring格式化器倒排思想,其具体体现在FormatterRegistrar接口的设计,上文用“比较古老”的支持java.util.Date类型的DateFormatterRegistrar打了个样,体验了一把倒排设计的好处。

我们知道在Java领域日期时间类型分为三大领域:老Date体系、JSR  310体系、Joda-time体系。这不FormatterRegistrar接口的继承体系三个实现类刚好与之对应:

@DateTimeFormat的作用有哪些

A哥不建议在开发中再以任何理由再使用Date类型,而是用JSR  310取以代之。因此接下来,就看看DateTimeFormatterRegistrar注册员为我们做了哪些事。

DateTimeFormatterRegistrar:JSR 310注册员

Since 4.0。在Spring下使用以支持JSR 310日期时间的格式化/转换。

我们知道,JSR  310对日期时间的格式化其实已经非常完善了,具体都体现在java.time.format.DateTimeFormatter这个Java原生API里。Spring针对于JSR  310日期时间类型格式化只是在DateTimeFormatter的基础上做了简单封装和适配,让它使用起来的姿势尽量和Date/JodaTime保持一致,以便对开发者更加友好,代码结构设计上也能够趋近于统一。

本系列前面文章介绍过的DateTimeFormatterFactory便是对DateTimeFormatter的简单包装,用于生产格式化器实例的工厂。此处的DateTimeFormatterRegistrar就使用它俩来进行一系列注册动作,因此可理解为他是更上层的封装形式。

源码分析

下面从源码下手一探究竟。

@DateTimeFormat的作用有哪些

截图里示例出该实现类支持的类型,这里用自定义的枚举类来更抽象的方式定义为三类了,即日期、时间、日期时间。这三大类其实包含了JSR  310类型的主要API,包括:LocalDate、LocalTime、LocalDateTime、ZonedDateTime、OffsetDateTime、OffsetTime共计6个API。对比一下这不正就是Jsr310DateTimeFormatAnnotationFormatterFactory所支持的六大类型么,如下截图所示:

@DateTimeFormat的作用有哪些

说明:该份截图是说明@DateTimeFormat只能标注在JSR  310日期时间的这6种类型上才有效哦。

其实,在任何时候Spring都不建议你直接使用原生的DateTimeFormatter这个API,而是用其封装过的org.springframework.format.datetime.standard.DateTimeFormatterFactory来获得一个DateTimeFormatter实例,以便使用起来更具统一性和灵活性。

这不DateTimeFormatterRegistrar它就是这么来干的:

@DateTimeFormat的作用有哪些

这是唯一构造器:3个类型对应的DateTimeFormatter均由Spring封装过的DateTimeFormatterFactory工厂来“动态”产生,而非直接绑定。由于DateTimeFormatter被设计为不可变,若初始化时就绑定上,后面将无法做定制化设置。这也是引入DateTimeFormatterFactory来做定制化参数“缓存”的又一作用~

由于使用DateTimeFormatterFactory而并非直接使用DateTimeFormatter,就可以很方便的对不同类型做参数定制化,如下方法们,它们是作用在DateTimeFormatterFactory上的,从而可以确保多个条件共存:

@DateTimeFormat的作用有哪些

当然,最重要的当属对FormatterRegistrar  接口方法 的实现逻辑:

@DateTimeFormat的作用有哪些

①:这个  步骤类似于上文讲述DateFormatterRegistrar时调用其public静态方法addDateConverters(registry),作用为注册基础转换器(如Date  -> Calendar,Date ->  Long的Converter转换器),从而提供基本的转换能力。值得注意的是:DateTimeConverters.registerConverters(registry)内部调用了DateFormatterRegistrar.addDateConverters(registry),并且额外增加了LocalDate、Calendar、Long、Instant等等的Converter转换器(如ZonedDateTimeToLocalDateConverter、LongToInstantConverter等等),后者是前者的超集。

无独有偶:jodaTime的JodaTimeConverters.registerConverters(registry)内部必然也调用了DateFormatterRegistrar.addDateConverters(registry)喽,感兴趣可自己去瞅瞅确认下?

②:生成每个类型对应的格式化器。简单的讲就是通过DateTimeFormatterFactory创建出对应的格式化器DateTimeFormatter③:这一步的作用在源码中的注释部分解释得很清楚了,这一大段代码的作用是使用ISO_LOCAL_*这种变种格式化器来代替执行,效果是性能提升2倍

?说明:这个做法在前文提到的Jsr310DateTimeFormatAnnotationFormatterFactory里getPrinter()生成格式化器时也被用到了用以成倍提升转换性能?

④:对于不需要特殊提速的类型,注册绑定上专用的格式化器org.springframework.format.Formatter即可。如PeriodFormatter、DurationFormatter等

@DateTimeFormat的作用有哪些

@DateTimeFormat的作用有哪些

⑤:让@DateTimeFormat注解对JSR 310日期时间提供支持。关于格式化注解方面的知识,请向上爬2层楼 or  点击文首/文末推荐链接均可进入文章进行详细了解,加深记忆。

代码示例

下面介绍DateTimeFormatterRegistrar注册员的使用示例,其中包括API使用方式,以及面向注解的使用方式。

API使用方式

此类使用方式一般门槛较高,需要对底层API有较熟了解才能运用自如,一般是需要在Spring基础上做二次开发的小伙伴才会用到,用个简单示例了解一下用法:

@Test public void test1() {     FormattingConversionService conversionService = new FormattingConversionService();     // 注册员负责添加格式化器以支持Date系列的转换     new DateTimeFormatterRegistrar().registerFormatters((FormatterRegistry) conversionService);      // 1、普通使用(API方式)     LocalDateTime now = LocalDateTime.now();     System.out.println("当前时间:" + now);     System.out.println("LocalDateTime转为LocalDate:" + conversionService.convert(now, LocalDate.class));     System.out.println("LocalDateTime转为LocalTime:" + conversionService.convert(now, LocalTime.class));      // 时间戳转Instant     long currMills = System.currentTimeMillis();     System.out.println("当前时间戳:" + currMills);     System.out.println("时间戳转Instant:" + conversionService.convert(currMills, Instant.class)); }

运行程序,输出:

当前时间:2021-03-07T21:19:39.752 LocalDateTime转为LocalDate:2021-03-07 LocalDateTime转为LocalTime:21:19:39.752 当前时间戳:1615123179763 时间戳转Instant:2021-03-07T13:19:39.763Z

完美。

通过这个示例,现在知道为啥前端传个时间戳,后端不用Long而使用Instant也能“接得住”不报错了吧~

注解使用方式

见与Spring MVC整合使用方式章节,详细解释。

JodaTimeFormatterRegistrar:joda-time注册员

@deprecated as of 5.3,请使用Java标准的JSR 310日期时间代替

Tips:JodaDateTimeFormatAnnotationFormatterFactoryy也一样在5.3版本被标记为过期了?

jodaTime曾经乃是绝对的王者,拯救Java日期时间于水火,直到JSR  310体系的出现。同样的那句话送给你:建议不要在(新)项目中以任何理由去使用jodaTime,而是和Date一样完全放弃,使用JSR 310足矣。

说明:现在不建议再使用JodaTime并非卸磨杀驴,而是JSR  310就是jodaTime的作者/组织捐赠给Java的(你看那语法,多像!),所以现在叫功成身退更为恰当?

由于jodaTime不像Date一样有那么重的历史包袱(关键Date还是JDK内置的核心类),并且它和JSR  310一脉相承,因此在可预见的将来它将彻底告别Java舞台,逐渐消亡。所以呢,我个人认为,再去学习jodaTime(包括周边)已再无必要,so此part就暂且略过喽。

到此,相信大家对“@DateTimeFormat的作用有哪些”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

@DateTimeFormat的作用有哪些

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

powershell的作用有哪些

今天小编给大家分享一下powershell的作用有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。powershell能干
2023-07-05

Jqgrid的作用有哪些

JqGrid是一个基于jQuery的表格插件,用于在网页上展示和操作数据。它具有以下作用:1. 数据展示:JqGrid可以将数据以表格的形式展示在网页上,提供分页、排序、过滤等功能,方便用户浏览和查找数据。2. 数据编辑:JqGrid支持对
2023-09-11

Vuex的作用有哪些

这篇文章给大家分享的是有关Vuex的作用有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。概述想必用过 vue.js 的童鞋,一定知道在 vue 各个组件之间传值的痛苦,基于父子、兄弟组件,我们传值可能会很方便
2023-06-15

Kotlin的作用有哪些

Kotlin的作用有以下几个:Android开发:Kotlin可以用于开发Android应用程序,它与Java语言兼容,可以与现有的Java代码无缝集成。服务器端开发:Kotlin可以用于开发服务器端应用程序,它提供了许多方便的特性,如函数
2023-10-25

php的作用有哪些

这篇文章主要讲解了“php的作用有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php的作用有哪些”吧!php即“超文本预处理器”,是在服务器端执行的脚本语言,用于web开发;php的作
2023-07-05

css的作用有哪些

这篇文章给大家分享的是有关css的作用有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。css的作用是:1、主要用来设计网页的样式,美化网页;2、能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体
2023-06-06

github的作用有哪些

本篇内容主要讲解“github的作用有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“github的作用有哪些”吧!github的作用:1、让开发变得更简单;github能够在服务器上存储代码
2023-07-05

phpinclude的作用有哪些

1. 代码重用:phpinclude可以将一个PHP文件中的代码引入到另一个PHP文件中,实现代码的重用。2. 维护性:将具有相同功能的代码放在一个文件中,方便维护和修改。3. 可读性:将不同的代码放在不同的文件中,可以提高代码的可读性和可
2023-06-13

css3的作用有哪些

本篇文章为大家展示了css3的作用有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。CSS3是CSS2的升级版本,3只是版本号,它在CSS2.1 的基础上增加了很多强大的新功能,目前主浏览器 Ch
2023-06-15

Python的作用有哪些

本篇内容主要讲解“Python的作用有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python的作用有哪些”吧!Python能干什么?1、web开发领域2、机器学习领域3、游戏开发领域4、
2023-06-15

jQuery的作用有哪些

今天小编给大家分享一下jQuery的作用有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。jQuery是什么?jQuery
2023-06-27

linux组的作用有哪些

今天小编给大家分享一下linux组的作用有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。l
2023-04-13

java final的作用有哪些

Java中的final关键字有以下几个作用:1. 声明一个常量:可以用final修饰一个变量,使其变成一个常量,一旦被赋值后就不能再修改。例如:final int MAX_VALUE = 10;2. 防止继承:可以用final修饰一个类,使
2023-09-05

java jre的作用有哪些

Java Runtime Environment (JRE) 是一个运行 Java 程序的环境,它包含了 Java 虚拟机(JVM)和 Java 核心类库。JRE 的作用包括:1. 执行 Java 程序:JRE 提供了 Java 虚拟机,它
2023-09-21

maven provided的作用有哪些

Maven提供了以下功能:项目管理:Maven提供了一种标准的项目结构,并可以管理项目的依赖关系、构建过程、测试、部署等。依赖管理:Maven可以管理项目的外部依赖库,并自动下载和管理这些依赖库的版本。构建工具:Maven可以自动执行各种构
2023-10-26

handlerexecutionchain类的作用有哪些

handlerexecutionchain类的作用有哪些?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。HandlerExecutionChain类/* * 处理
2023-05-31

编程热搜

目录