Menu Close

46.6. リソースの選択方法

概要

指定の URI を 1 つ以上のリソースメソッドにマップできます。たとえば、URI customerservice/12/ma@Path("customerservice/{id}") または @Path("customerservice/{id}/{state}") テンプレートと一致する可能性があります。JAX-RS は、リソースメソッドをリクエストに一致させるための詳細なアルゴリズムを指定します。このアルゴリズムは、正規化された URI、HTTP 動詞、およびリクエストエンティティーとレスポンスエンティティーのメディアタイプを、リソースクラスのアノテーションと比較します。

基本選択アルゴリズム

JAX-RS 選択アルゴリズムは、3 つのステージに分類されます。

  1. ルートリソースクラスを判断します。

    リクエスト URI は @Path アノテーションが付けられたすべてのクラスに対して照合されます。@Path アノテーションがリクエスト URI と一致するクラスが判断されます。

    リソースクラスの @Path アノテーションの値が要求 URI 全体と一致する場合、クラスのメソッドは 3 番目のステージへの入力として使用されます。

  2. オブジェクトがリクエストを処理することを決定します。

    リクエスト URI が選択したクラスの @Path アノテーションの値より長い場合、リソースメソッドの @Path アノテーションの値は、要求を処理できるサブリソースの検索に使用されます。

    1 つ以上のサブリソースメソッドがリクエスト URI と一致する場合、これらのメソッドは 3 番目のステージの入力として使用されます。

    リクエスト URI に一致するのが、サブリソースロケーターのみである場合、サブリソースロケーターによって作成されたオブジェクトのリソースメソッドがリクエスト URI と一致します。このステージは、サブリソースメソッドがリクエスト URI と一致するまで繰り返されます。

  3. リクエストを処理するリソースメソッドを選択します。

    HTTP 動詞アノテーションがリクエストの HTTP 動詞と一致するリソースメソッド。さらに、選択したリソースメソッドは、リクエストエンティティーボディーのメディア型を受け入れ、リクエストに指定されたメディア型に準拠する応答を生成できる必要があります。

複数のリソースクラスからの選択

選択アルゴリズムの最初の 2 つの段階で、リクエストを処理するリソースが決まります。場合によっては、リソースがリソースクラスによって実装されます。それ以外の場合は、同じ URI テンプレートを使用する 1 つ以上のサブリソースによって実装されます。リクエスト URI に一致する複数のリソースがある場合、リソースクラスはサブリソースよりも優先されます。

リソースクラスとサブリソース間のソート後に複数のリソースがリクエスト URI と一致する場合、以下の基準を使用して単一のリソースを選択します。

  1. URI テンプレートでリテラル文字が最も多いリソースを優先します。

    リテラル文字は、テンプレート変数の一部ではない文字です。たとえば、/widgets/{id}/{color} には 10 文字のリテラル文字があり、/widgets/1/{color} には 11 文字のリテラル文字があります。そのため、リクエスト URI /widgets/1/red は URI テンプレートとして /widgets/1/{color} のリソースと一致します。

    注記

    末尾のスラッシュ (/) はリテラル文字としてカウントされます。したがって、/joefred//joefred よりも優先されます。

  2. URI テンプレートで最も多くの変数を持つリソースを優先します。

    要求 URI /widgets/30/green は、/widgets/{id}/{color}/widgets/{amount}/ の両方と一致する可能性があります。ただし、2 つの変数があるため、URI テンプレート /widgets/ {id}/{color} のリソースが選択されます。

  3. 正規表現を含む変数が最も多いリソースを優先します。

    要求 URI /widgets/30/green は、/widgets/{number}/{color}/widgets/{id:.}/{color}* の両方と一致する可能性があります。しかし、URI テンプレート */widgets/{id:.}/{color} のあるリソースは、正規表現を含む変数があるため、選択されます。

複数のリソースメソッドからの選択

多くの場合、要求 URI に一致するリソースを選択すると、リクエストを処理できる単一のリソースメソッドになります。このメソッドは、リクエストで指定された HTTP 動詞とリソースメソッドの HTTP 動詞アノテーションを照合することによって決定されます。適切なHTTP動詞アノテーションを持つことに加えて、選択されたメソッドは、リクエストに含まれるリクエストエンティティーを処理し、リクエストのメタデータで指定された適切なタイプのレスポンスを生成できる必要があります。

注記

リソースメソッドが処理できるリクエストエンティティーの型は @Consumes アノテーションによって指定されます。リソースメソッドが生成できる応答の型は @Produces アノテーションを使用して指定されます。

リソースを選択すると、リクエストを処理できる複数のメソッドが生成される場合は、次の基準を使用して、リクエストを処理するリソースメソッドを選択します。

  1. サブリソースよりもリソースメソッドを優先します。
  2. サブリソースロケータよりもサブリソースメソッドを優先します。
  3. @Consumes アノテーションと @Produces アノテーションで最も具体的な値を使用するメソッドを優先します。

    たとえば、アノテーション @Consumes("text/xml") を持つメソッドは、アノテーション @Consumes("text/*") を持つメソッドよりも優先されます。どちらのメソッドも、@Consumes アノテーションのないメソッドやアノテーション @Consumes("\*/*") よりも優先されます。

  4. リクエストボディーエンティティーのコンテンツ型に最も一致するメソッドが推奨されます。

    注記

    リクエストボディーエンティティーのコンテンツ型は HTTP Content-Type プロパティーで指定されます。

  5. レスポンスとして受け入れられるコンテンツタイプに最も近いメソッドを優先します。

    注記

    レスポンスとして受け入れられるコンテンツタイプは、HTTP Accept プロパティーで指定されます。

選択プロセスのカスタマイズ

場合によっては、開発者は、複数のリソースクラスの選択方法においてアルゴリズムが多少制限されていると報告しています。たとえば、指定のリソースクラスが一致していて、このクラスに一致するリソースメソッドがない場合は、アルゴリズムの実行を停止します。残りの一致するリソースクラスをチェックすることはありません。

Apache CXF は、org.apache.cxf.jaxrs.ext.ResourceComparator インターフェースを提供します。このインターフェースを使用して、ランタイムが一致する複数のリソースクラスを処理する方法をカスタマイズできます。例46.9「リソース選択をカスタマイズするためのインターフェース」 に示されている ResourceComparator インターフェースには、実装する必要のあるメソッドが 2 つあります。一方は 2 つのリソースクラスを比較し、もう 1 つは 2 つのリソースメソッドを比較します。

例46.9 リソース選択をカスタマイズするためのインターフェース

package org.apache.cxf.jaxrs.ext;

import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.message.Message;

public interface ResourceComparator
{
  int compare(ClassResourceInfo cri1,
              ClassResourceInfo cri2,
              Message message);

  int compare(OperationResourceInfo oper1,
              OperationResourceInfo oper2,
              Message message);
}

カスタム実装は、以下のように 2 つのリソース間で選択します。

  • 最初のパラメーターが 2 番目のパラメーターよりも一致している場合は、1 を返します。
  • 2 番目のパラメーターが最初のパラメーターよりも一致している場合は、-1 を返します。

0 が返されると、ランタイムはデフォルトの選択アルゴリズムで続行されます。

カスタム ResourceComparator 実装を登録するには、子の resourceComparator をサービスのjaxrs:server に追加します。