Springで日付パラメータを扱う

Springでの日付パラメーターの使用

1. 前書き

この短いチュートリアルでは、リクエストレベルとアプリケーションレベルの両方で、Spring RESTリクエストでDateLocalDateLocalDateTimeパラメータを受け入れる方法を見ていきます。

2. 問題

DateLocalDate、およびLocalDateTimeパラメータを受け入れる3つのメソッドを持つコントローラについて考えてみましょう。

@RestController
public class DateTimeController {

    @PostMapping("/date")
    public void date(@RequestParam("date") Date date) {
        // ...
    }

    @PostMapping("/localdate")
    public void localDate(@RequestParam("localDate") LocalDate localDate) {
        // ...
    }

    @PostMapping("/localdatetime")
    public void dateTime(@RequestParam("localDateTime") LocalDateTime localDateTime) {
        // ...
    }
}

ISO 8601に従ってフォーマットされたパラメータを使用してこれらのメソッドのいずれかにPOSTリクエストを送信すると、例外が発生します。

たとえば、「2018-10-22」を/dateエンドポイントに送信すると、次のようなメッセージで不正なリクエストエラーが発生します。

Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDate';
  nested exception is org.springframework.core.convert.ConversionFailedException.

これは、Springが既定でStringパラメーターを日付または時刻オブジェクトに変換できないためです。

3. リクエストレベルでの日付パラメーターの変換

この問題を処理する方法の1つは、パラメータに@DateTimeFormat annotationで注釈を付け、フォーマットパターンパラメータを提供することです。

@RestController
public class DateTimeController {

    @PostMapping("/date")
    public void date(@RequestParam("date")
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date date) {
        // ...
    }

    @PostMapping("/local-date")
    public void localDate(@RequestParam("localDate")
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate localDate) {
        // ...
    }

    @PostMapping("/local-date-time")
    public void dateTime(@RequestParam("localDateTime")
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime localDateTime) {
        // ...
    }
}

このように、文字列がISO 8601形式を使用してフォーマットされている場合、文字列は日付オブジェクトに適切に変換されます。

独自の変換パターンを使用することもできます。 @DateTimeFormatアノテーションでパターンパラメータを指定するだけです。

@PostMapping("/date")
public void date(@RequestParam("date")
  @DateTimeFormat(pattern = "dd.MM.yyyy") Date date) {
    // ...
}

4. アプリケーションレベルでの日付パラメーターの変換

Springで日時オブジェクトの変換を処理する別の方法は、グローバル構成を提供することです。 the official documentationに従うことでそれを行うことができます:

@Configuration
class DateTimeConfig {

    @Bean
    public FormattingConversionService conversionService() {
        DefaultFormattingConversionService conversionService =
          new DefaultFormattingConversionService(false);

        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setDateFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy"));
        registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"));
        registrar.registerFormatters(conversionService);

        // other desired formatters

        return conversionService;
    }
}

まず、falseパラメータを使用してDefaultFormattingConversionServiceを作成します。これは、Springがデフォルトでフォーマッタを登録しないことを意味します。

そして、DateTimeFormatterRegistrarオブジェクトに日付と日時の形式の新しいパターンを手動で登録します。

5. 概要

この記事では、SpringMVCリクエストで日付パラメータを受け入れる方法を学びました。 リクエストごとに、そしてグローバルにそれを行う方法について説明しました。

また、独自の日付書式パターンを作成する方法も学びました。

いつものように、すべてのソースコードはover on GitHubで利用できます。