1. 序章

この短いチュートリアルでは、SpringRESTリクエストでDate LocalDate、LocalDateTimeパラメーターをリクエストレベルとアプリケーションレベルの両方で受け入れる方法を学習します。

2. 問題

Date LocalDate 、および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が文字列パラメータを日付または時刻オブジェクトに変換できないためです。

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

この問題を処理する方法の1つは、パラメーターに @DateTimeFormat アノテーションを付け、フォーマットパターンパラメーターを指定することです。

@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で日付と時刻のオブジェクト変換を処理する別の方法は、グローバル構成を提供することです。 公式ドキュメントに従って、WebMvcConfigurationSupport構成とそのmvcConversionServiceメソッドを拡張する必要があります。

@Configuration
public class DateTimeConfig extends WebMvcConfigurationSupport {

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

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

        DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
        dateRegistrar.setFormatter(new DateFormatter("dd.MM.yyyy"));
        dateRegistrar.registerFormatters(conversionService);

        return conversionService;
    }
}

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

次に、日付と日時のパラメーターのカスタム形式を登録する必要があります。 これを行うには、2つのカスタムフォーマットレジストラを登録します。 最初のDateTimeFormatterRegistar、は、LocalDateおよびLocaDateTimeオブジェクトの解析を担当します。 2番目のDateFormattingRegistrar、は、Dateオブジェクトを処理します。

5. プロパティファイルで日時を設定する

Springには、アプリケーションのプロパティファイルを介してグローバルな日時形式を設定するオプションもあります。 日付、日時、および時刻の形式には、次の3つの個別のパラメーターがあります。

spring.mvc.format.date=yyyy-MM-dd
spring.mvc.format.date-time=yyyy-MM-dd HH:mm:ss
spring.mvc.format.time=HH:mm:ss

これらのパラメータはすべて、iso値に置き換えることができます。 たとえば、日時パラメータを次のように設定します。

spring.mvc.format.date-time=iso

ISO-8601フォーマットと同じになります:

spring.mvc.format.date-time=yyyy-MM-dd HH:mm:ss

6. 結論

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

また、独自の日付フォーマットパターンを作成する方法も学びました。

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