ホームページ >Java >&#&チュートリアル >Spring Boot の日付と時刻を処理する方法

Spring Boot の日付と時刻を処理する方法

PHPz
PHPz転載
2023-05-18 14:22:061011ブラウズ

GET リクエストと POST フォームの日付と時刻の文字列形式の変換

この状況は、時刻が Json 文字列として使用される場合とは異なる方法で処理する必要があります。これは、フロントエンドの JSON の最下層がバックエンドに変換されるためです。 pojoではJsonシリアル化Jacksonツール(HttpMessgeConverter)を使用しますが、通常のリクエストパラメータとして時刻文字列が渡される場合はConverterを使用して変換する処理方法の違いがあります。ふたつの間に。

カスタム パラメーター コンバーター (コンバーター)

実装org.springframework.core.convert.converter.Converter、カスタム パラメーター コンバーターを次のように使用します:

@Configuration
public class DateConverterConfig {
    @Bean
    public Converter<String, LocalDate> localDateConverter() {
       return new Converter<String, LocalDate>() {
            @Override
            public LocalDate convert(String source) {
                return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            }
        };
    }
    @Bean
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return new Converter<String, LocalDateTime>() {
            @Override
            public LocalDateTime convert(String source) {
                return LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
        };
    }
}

コメント: 上記の 2 つの Bean は、spring mvc のパラメーター パーサーに挿入されます (ParameterConversionService と呼ばれるようです)。受信文字列が LocalDateTime クラスに変換されるとき、spring はコンバータ この入力パラメータを変換します。

注: カスタムパラメータコンバータ Converter に関して、落とし穴があります。上記の匿名内部クラスをラムダ式に簡略化すると、

   @Bean
    @ConditionalOnBean(name = "requestMappingHandlerAdapter")
    public Converter<String, LocalDate> localDateConverter() {
        return source -> LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
    }

プロジェクトを再度開始すると例外が発生します。 :

原因: java.lang.IllegalArgumentException: コンバータのソース タイプ 1eefd63bbe027a2807ccada294a3372c とターゲット タイプ 8742468051c85b06f0a0af9e3e506b5c を決定できません [com.example.demo126.config.MappingConverterAdapter$$ Lambda$522/817994751]; クラスはこれらの型をパラメータ化しますか?

理由:

Web プロジェクトが登録を開始するときに初期化されますrequestMappingHandlerAdapter ## WebBindingInitializer

adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer());

そして

ConfigurableWebBindingInitializer には FormattingConversionService が必要です。FormattingConversionService によりすべての Converter が追加されます。追加時にジェネリック情報を取得する必要があります:

@Override
public void addFormatters(FormatterRegistry registry) {
    for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
       registry.addConverter(converter);
    }
    for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
       registry.addConverter(converter);
    }
    for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
       registry.addFormatter(formatter);
    }
}

Converter.class を追加すると、通常、インターフェースを通じて 2 つのジェネリックの特定の型を取得します。

public ResolvableType as(Class<?> type) {
    if (this == NONE) {
      return NONE;
    }
    Class<?> resolved = resolve();
    if (resolved == null || resolved == type) {
      return this;
    }
    for (ResolvableType interfaceType : getInterfaces()) {
      ResolvableType interfaceAsType = interfaceType.as(type);
      if (interfaceAsType != NONE) {
        return interfaceAsType;
      }
    }
    return getSuperType().as(type);
}

ラムダ式のインターフェースは Converter であり、特定の型は取得できません。この場合の解決策は次のとおりです:

  • 最も簡単な方法は、ラムダ式を使用せず、匿名の内部クラスを使用することで、上記の問題が発生しないようにすることです

  • requestMappingHandlerAdapterbean が登録されるまで待ってから独自のコンバータを追加すると、FormattingConversionService

  • には登録されません。
は、照合のために、フロントエンドによって渡された文字列 (yyyy-MM-dd HH:mm:ss、yyyy-MM-dd、HH:mm:ss など) に対して通常の照合を実行することもできます。さまざまなシナリオに適応します。

@Bean
@ConditionalOnBean(name = "requestMappingHandlerAdapter")
public Converter<String, LocalDateTime> localDateTimeConverter() {
  return source -> LocalDateTime.parse(source, DateTimeUtils.DEFAULT_FORMATTER);
}

注: ここでは、Date 日付形式を照合するときに hutool が直接使用されます。これは、すでに作成した解析ツール クラスです。ここでは車輪の再発明はしません。次のメソッドでもこのツール クラスを使用します。必要に応じて、独自のプロジェクトでこのツール クラスを使用することも非常に簡単です。次のように、プロジェクトの pom ファイルに hutool の依存関係を導入するだけです:

@Component
public class DateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String value) {
        /**
         * 可对value进行正则匹配,支持日期、时间等多种类型转换
         * 这里在匹配Date日期格式时直接使用了 hutool 为我们已经写好的解析工具类,这里就不重复造轮子了
         * cn.hutool.core.date.DateUtil
         * @param value
         * @return
         */
        return DateUtil.parse(value.trim());
    }
}

Use Spring annotations

Use spring's annotations独自のアノテーション

@DateTimeFormat(pattern = "yyyy-MM-dd")、次のように:

<!--hu tool 工具类-->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.1.3</version>
</dependency>

カスタムパラメータコンバータが使用されている場合、Spring はこのメソッドを優先的に使用して処理します。つまり、Spring アノテーションは有効になりません。

Use ControllerAdvice with initBinder

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date startDate;

名前からわかるように、これはコントローラー内のループカットであり (グローバル例外キャプチャもここで実行できます)、パラメーターは前に変換されます。ハンドラーの入力; 対応するオブジェクトの変換。

JSON 入力パラメータと戻り値のグローバル処理

リクエスト タイプは:

post,content-type=application/json、バックグラウンドでは @ が使用されます。 RequestBody 受信、デフォルトの受信および戻り値の形式は次のとおりです: yyyy-MM-dd HH:mm:ss

application.yml ファイルを変更します

追加application.propertities ファイル内 次の内容:

spring:

jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT 8

サポート

(content-type=application/json) リクエストの文字列形式は yyyy-MM-dd です HH:mm:ss 、バックグラウンドで @ を使用 RequestBody が受信され、戻り値の日付が yyyy-MM-dd HH:mm:ss 形式の文字列に変換されます;

はサポートされていません (

content-type=application/json ) リクエスト内の yyyy-MM-dd およびその他のタイプの文字列は、date; java8dateapi はサポートされていません;

Jackson の JSON シリアル化と逆シリアル化の使用

@ControllerAdvice
public class GlobalExceptionHandler {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
        });
        binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
        });
        binder.registerCustomEditor(LocalTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalTime.parse(text, DateTimeFormatter.ofPattern("HH:mm:ss")));
            }
        });
    }
}

以上がSpring Boot の日付と時刻を処理する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。