1. 概要

このチュートリアルでは、Springでパス変数をオプションにする方法を学習します。 最初に、がハンドラーメソッドで@PathVariableパラメーターをバインドする方法について説明します。 次に、さまざまなSpringバージョンでパス変数をオプションにするさまざまな方法を示します。

パス変数の概要については、SpringMVCの記事をお読みください。

2. Springが@PathVariableパラメーターをバインドする方法

デフォルトでは、Springはハンドラーメソッドの @PathVariable で注釈が付けられたすべてのパラメーターを、URIテンプレートの対応する変数にバインドしようとします。 Springが失敗した場合、そのハンドラーメソッドにリクエストを配信しません。

たとえば、 id パス変数をオプションにしようとする(失敗した)次のgetArticleメソッドについて考えてみます。

@RequestMapping(value = {"/article", "/article/{id}"})
public Article getArticle(@PathVariable(name = "id") Integer articleId) {
    if (articleId != null) {
        //...
    } else {
        //...
    }
}

ここで、 getArticle メソッドは、 /article/article /{id}の両方への要求を処理することになっています。 Springは、 articleIdパラメーターをidパス変数にバインドしようとします(存在する場合)。

たとえば、 / article / 123 にリクエストを送信すると、articleIdの値が123に設定されます。

一方、 / article にリクエストを送信すると、次の例外により、Springはステータスコード500を返します。

org.springframework.web.bind.MissingPathVariableException:
  Missing URI template variable 'id' for method parameter of type Integer

これは、 id が欠落しているため、SpringがarticleIdパラメーターの値を設定できなかったためです。

したがって、次のセクションで説明するように、対応するパス変数がない場合は、特定の@PathVariableパラメーターのバインドを無視するようにSpringに指示する方法が必要です。

3. パス変数をオプションにする

3.1. @PathVariablerequired属性を使用する

Spring 4.3.3以降、 @PathVariable アノテーションは、パス変数がハンドラーメソッドに必須かどうかを示すブール属性requiredを定義します。

たとえば、次のバージョンの getArticle は、required属性を使用します。

@RequestMapping(value = {"/article", "/article/{id}"})
public Article getArticle(@PathVariable(required = false) Integer articleId) {
   if (articleId != null) {
       //...
   } else {
       //...
   }
}

required属性はfalseであるため、 id パス変数がリクエストで送信されなくても、Springは文句を言いません。 つまり、Springは、送信された場合はarticleIdidに設定し、それ以外の場合はnullに設定します。

一方、requiredtrueの場合、 id が欠落していると、Springは例外をスローします。

3.2. オプションのパラメータタイプの使用

次の実装は、Spring 4.1が、 JDK 8のオプションクラスとともに、articleIdをオプションにする別の方法を提供する方法を示しています。

@RequestMapping(value = {"/article", "/article/{id}"}")
public Article getArticle(@PathVariable Optional<Integer> optionalArticleId) {
    if (optionalArticleId.isPresent()) {
        Integer articleId = optionalArticleId.get();
        //...
    } else {
        //...
    }
}

ここで、Springはオプション実例、 オプションのArticleId 、の値を保持する id id が存在する場合、 optionalArticleId はその値をラップします。それ以外の場合、optionalArticleIdnull値をラップします。 次に、オプション isPresent()、 get()、または orElse()メソッドを使用して値を操作できます。

3.3. Mapパラメータタイプの使用

Spring 3.2以降で使用可能なオプションのパス変数を定義する別の方法は、@ PathVariableパラメーターにM apを使用することです。

@RequestMapping(value = {"/article", "/article/{id}"})
public Article getArticle(@PathVariable Map<String, String> pathVarsMap) {
    String articleId = pathVarsMap.get("id");
    if (articleId != null) {
        Integer articleIdAsInt = Integer.valueOf(articleId);
        //...
    } else {
        //...
    }
}

この例では、 地図 pathVarsMap パラメータは、URIにあるすべてのパス変数をキー/値のペアとして収集します。 次に、 get()メソッドを使用して特定のパス変数を取得できます。

Springはパス変数の値をStringとして抽出するため、 Integer.valueOf()メソッドを使用してIntegerに変換したことに注意してください。

3.4. 2つのハンドラーメソッドの使用

従来のSpringバージョンを使用していた場合は、getArticleハンドラーメソッドを2つのメソッドに分割できます。

最初のメソッドは、 / article /{id}へのリクエストを処理します。

@RequestMapping(value = "/article/{id}")
public Article getArticle(@PathVariable(name = "id") Integer articleId) {
    //...        
}

2番目のメソッドは/article へのリクエストを処理しますが:

@RequestMapping(value = "/article")
public Article getDefaultArticle() {
    //...
}

4. 結論

要約すると、さまざまなSpringバージョンでパス変数をオプションにする方法について説明しました。

いつものように、この記事の完全なコードは、GitHubから入手できます。