Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the functions of @ DateTimeFormat

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "what are the functions of @ DateTimeFormat". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what are the functions of @ DateTimeFormat"?

The outline of this article

Version convention

Spring Framework:5.3.x

Spring Boot:2.4.x

Text

The converter and formatter in Spring is a very important part of the whole Spring technology stack system, and is the basic support of many advanced features.

As a user of Spring, you may have worked for several years to realize that Spring has formatting ability only when you are exposed to the annotation @ DateTimeFormat; maybe you do not know the process of automatic encapsulation when using xml configuration and Spring MVC, so you may not be aware of the existence of Converter converter module; maybe you are not sure which types @ DateTimeFormat can be marked on, and you have to use Google Baidu every time you use it.

As a developer of Spring, the above should no longer be a problem. Instead, he is eloquent and familiar with it. Next, I will pass on the supplementary content of this article to you, sit tight and start.

What exactly does the @ DateTimeFormat annotation do?

Needless to guess, many programmers know / use @ DateTimeFormat annotations in the Spring MVC scenario, or even in this scenario: the front end passes a date-time format value, and the back end uses Date/LocalDateTime to receive this value.

The request entity for Request looks like this:

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

In this way, strings in the format "2021-03-07 21:00:00" passed to the front end can be automatically encapsulated in arriveTime.

Note: String-> LocalDateTime arriveTime belongs to the Parser function (also known as input), this note will also take effect when xxx-> String output (Printer function)?

After using @ DateTimeFormat for so long, do you know that it does not belong to the class of the spring-web/spring-webmvc module, but belongs to spring-context:org.springframework.format.annotation.DateTimeFormat? In other words: @ DateTimeForma, which belongs to the infrastructure class, is not limited to the web layer, but can be used in all places where transformation is needed.

As we learned from the previous article, the underlying functionality of @ DateTimeFormat and @ NumberFormat annotations depends on AnnotationFormatterFactory and the formatter registry FormatterRegistry core API. So what is the process?

Maybe this is still a bit abstract, so I tried to draw a flow chart to help you grasp the core working principle of this part (execution process):

The process can be interpreted as registering the annotation factory AnnotationFormatterFactory with the formatter registry FormatterRegistry's API to support formatting annotations. However, the underlying layer is actually adapted (for each FieldType type) to register with FormatterRegistry for Converter. In other words: the bottom layer of FormatterRegistry (actually ConverterRegistry) always manages some simple Converter converters, which is in line with the design principle that the lower layer is more abstract, the higher layer is more concrete, and it is a good design scheme.

It is worth noting that the underlying Converter of ConverterRegistry management is divided into three categories. 1:1 、 1:N 、 N:N?

After registering with the registry, the conversion service has the ability to convert to and from FieldType String of the types supported by AnnotationFormatterFactory. Of course, a prerequisite for it to perform the conversion action is that the FieldType must be marked with the annotation type specified by AnnotationFormatterFactory, and @ DateTimeFormat works.

From this point of view, the @ DateTimeFormat annotation does not actually do anything on its own, but is used purely as a metadata on Field to specify the parameters needed to participate in judgment and formatting. What really does "a lot of things" is the underlying core API, such as AnnotationFormatterFactory and FormatterRegistry, which is quietly done in the initialization phase, and the logic of all this (more complex) is completely transparent to developers.

JSR 310 date and time registrar

The last article introduced the idea of inversion of Spring formatter, which is embodied in the design of FormatterRegistrar interface. The above example is made with the "older" DateFormatterRegistrar that supports java.util.Date type, and the benefits of inverted design are experienced.

We know that the date-time type in the Java domain can be divided into three fields: the old date system, the JSR 310 system and the Joda-time system. This is not the inheritance system of the FormatterRegistrar interface. The three implementation classes correspond to it:

Brother A does not recommend using the Date type again for any reason in development, but instead uses JSR 310 instead. So next, let's take a look at what the DateTimeFormatterRegistrar registrar has done for us.

DateTimeFormatterRegistrar:JSR 310 registrant

Since 4.0 . Used under Spring to support JSR 310 date-time formatting / conversion.

We know that the date and time formatting of JSR 310 is actually very perfect, which is embodied in java.time.format.DateTimeFormatter, the native API of Java. Spring only encapsulates and adapts the date and time type format of JSR 310 on the basis of DateTimeFormatter, so that its posture is consistent with that of Date/JodaTime as far as possible, so that it is more developer-friendly and the code structure design can be more unified.

The DateTimeFormatterFactory introduced in the previous articles in this series is a simple wrapper for DateTimeFormatter and is used in the factory that produces formatter instances. DateTimeFormatterRegistrar here uses both of them for a series of registration actions, so it can be understood as a higher-level form of encapsulation.

Source code analysis

Let's start with the source code to find out.

The screenshot shows the types supported by the implementation class. Here, the custom enumerated classes are more abstractly defined into three categories, namely, date, time and date-time. These three categories actually contain the main API of JSR 310 type, including: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, OffsetDateTime, OffsetTime, a total of 6 API. Compare with the six types supported by Jsr310DateTimeFormatAnnotationFormatterFactory, as shown in the following screenshot:

Note: this screenshot shows that @ DateTimeFormat can only be marked on these six types of JSR 310 date and time.

In fact, Spring does not recommend that you directly use the native DateTimeFormatter API at any time, but use its encapsulated org.springframework.format.datetime.standard.DateTimeFormatterFactory to get a DateTimeFormatter instance, so that it can be more uniform and flexible to use.

This is not DateTimeFormatterRegistrar. This is how it works:

This is the only constructor: the DateTimeFormatter for all three types is generated "dynamically" by the DateTimeFormatterFactory factory encapsulated by Spring, rather than binding directly. Because DateTimeFormatter is designed to be immutable, if you bind it at initialization, you will not be able to make customized settings later. This is also another function of introducing DateTimeFormatterFactory to do customized parameter "cache" ~

By using DateTimeFormatterFactory instead of using DateTimeFormatter directly, you can easily customize parameters for different types. The following methods work on DateTimeFormatterFactory to ensure the coexistence of multiple conditions:

Of course, the most important thing is the implementation logic of the FormatterRegistrar interface method:

①: this step is similar to calling its public static method addDateConverters (registry) when DateFormatterRegistrar is described above, and acts as a registered base converter (such as the Converter converter for Date-> Calendar,Date-> Long), thus providing basic conversion capabilities. It is worth noting that DateFormatterRegistrar.addDateConverters (registry) is called internally in DateTimeConverters.registerConverters (registry), and additional Converter converters (such as ZonedDateTimeToLocalDateConverter, LongToInstantConverter, etc.) are added to LocalDate, Calendar, Long, Instant, and so on, which is a superset of the former.

Coincidentally: DateFormatterRegistrar.addDateConverters (registry) must also be called inside jodaTime's JodaTimeConverters.registerConverters (registry). If you are interested, can you check it out for yourself?

②: generates a formatter for each type. To put it simply, the corresponding formatter DateTimeFormatter ③ is created through DateTimeFormatterFactory: the role of this step is clearly explained in the comments in the source code. The role of this large piece of code is to use a variant formatter like ISO_LOCAL_* instead of execution, resulting in a two-fold improvement in performance.

? Explanation: this practice is also used to multiply the conversion performance when getPrinter () generates the formatter in the Jsr310DateTimeFormatAnnotationFormatterFactory mentioned earlier.

④: for types that do not require special acceleration, register the dedicated formatter org.springframework.format.Formatter on the binding. Such as PeriodFormatter, DurationFormatter, etc.

⑤: let the @ DateTimeFormat annotation support JSR 310 date and time. For the knowledge of formatting notes, please climb 2 floors or and click on the recommended link at the beginning / end of the article to get a detailed understanding of the article and deepen your memory.

Code example

The following is an example of the use of a DateTimeFormatterRegistrar registrar, including how API is used and how annotations are used.

How API is used

Generally speaking, the threshold for this kind of use is high, and you need to have a good understanding of the underlying API in order to use it freely. Generally, only partners who need to do secondary development on the basis of Spring will use it. Use a simple example to learn how to use it:

@ Test public void test1 () {FormattingConversionService conversionService = new FormattingConversionService (); / / the registrar is responsible for adding formatters to support Date series transformations new DateTimeFormatterRegistrar (). RegisterFormatters ((FormatterRegistry) conversionService); / / 1, general use (API mode) LocalDateTime now = LocalDateTime.now (); System.out.println ("current time:" + now) System.out.println ("LocalDateTime to LocalDate:" + conversionService.convert (now, LocalDate.class)); System.out.println ("LocalDateTime to LocalTime:" + conversionService.convert (now, LocalTime.class)); / / timestamp to Instant long currMills = System.currentTimeMillis (); System.out.println ("current timestamp:" + currMills); System.out.println ("timestamp to Instant:" + conversionService.convert (currMills, Instant.class));}

Run the program, output:

Current time: 2021-03-07T21:19:39.752 LocalDateTime to LocalDate:2021-03-07 LocalDateTime to LocalTime:21:19:39.752 current timestamp: 1615123179763 timestamp to Instant:2021-03-07T13:19:39.763Z

Perfect.

Through this example, we now know why the front end sends a timestamp and the back end can "catch" by using Instant instead of Long.

How annotations are used

See the section on how to integrate with Spring MVC for detailed explanation.

JodaTimeFormatterRegistrar:joda-time registrant

@ deprecated as of 5.3Please use Java standard JSR 310 date time instead

Tips:JodaDateTimeFormatAnnotationFormatterFactoryy is also marked as expired in version 5.3?

JodaTime was once the absolute king, saving the date and time of Java from fire and water until the emergence of the JSR 310 system. The same sentence is for you: it is recommended not to use jodaTime in (new) projects for any reason, but to give up completely like Date, using JSR 310 is enough.

Explanation: it is no longer recommended to use JodaTime instead of killing donkeys, but JSR 310 is donated to Java by the author / organization of jodaTime (look at the grammar, how similar!), so it's more appropriate to call it quitting now?

Because jodaTime does not have as much historical baggage as Date (the key Date is still the built-in core class of JDK), and it is in the same line as JSR 310, it will completely leave the Java stage and die out in the foreseeable future. Therefore, I personally think that it is no longer necessary to study jodaTime (including the surrounding area), so so this part will be skipped for the time being.

At this point, I believe you have a deeper understanding of "what is the role of @ DateTimeFormat". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report