JAX-RSでパラメータの受け取り方をいろいろ試す
JAX-RSでは次に挙げるアノテーションをメソッドの引数などに付けることでクエリパラメータやパスの一部を受け取ることができます。
@MatrixParam
@QueryParam
@PathParam
@CookieParam
@HeaderParam
メソッドの引数はString
やプリミティブを使うことができますが、それ以外のクラスも使用できます。
String
の引数をひとつだけ受け取るpublic
なコンストラクタを持つクラス
次のようなクラスでもクエリパラメータなどを受け取ることが出来ます。
public class Hoge {
public final String value;
public Hoge(String value) {
this.value = value;
}
}
リソースメソッドでは次のように使います。
@GET
public String get(@QueryParam("abc") Hoge abc) {
...
この例でいうとabc
という名前のクエリパラメータがnull
の場合はHoge
はインスタンス化されず引数abc
はnull
となります。
クエリパラメータがnull
の場合というのはabc
という名前のクエリパラメータが無い場合です。
?abc=&def=xyz
というようなクエリパラメータの場合はabc
はnull
ではなく空文字列です。
String
の引数をひとつだけ受け取る"valueOf"
という名前のstatic
ファクトリメソッドを持つクラス
次のようなクラスを使用することも可能です。
public class Hoge {
public final String value;
private Hoge(String value) {
this.value = value;
}
public static Hoge valueOf(String value) {
return new Hoge(value);
}
}
static
ファクトリメソッドを書く分の手間が増えますが、例えば、
-
value
が空文字列の場合はnull
を返す -
Integer
のようにキャッシュすることができる - サブクラスを返すことができる
という風に柔軟に実装することが可能です。
また、クラス(この例でいうとHoge
)をabstract
にすることも可能です。
String
の引数をひとつだけ受け取る"fromString"
という名前のstatic
ファクトリメソッドを持つクラス
static
ファクトリメソッドはvalueOf
以外にfromString
という名前にすることも可能です。
ひとつのクラスにvalueOf
とfromString
の両方が定義されている場合はvalueOf
が呼ばれます。
ただし列挙型の場合はvalueOf
が暗黙的に実装されており挙動を上書きできないためか、fromString
が呼ばれます。
列挙型でなくともfromString
を優先にしておけば良かったのでは、と思わなくもないです。
ParamConverter
を使用する
JAX-RS 2から
というふたつのインターフェースが追加されました。
ParamConverter
の実装クラスではString
から任意のクラスに変換するロジックを書きます。
public class HogeParamConverter implements ParamConverter<Hoge> {
@Override
public Hoge fromString(String value) {
return new Hoge(value);
}
@Override
public String toString(Hoge hoge) {
return hoge.value;
}
}
ParamConverterProvider
の実装クラスではリソースメソッドの引数の型やアノテーションをもとにParamConverter
を選択して返します。
public class HogeParamConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (rawType == Hoge.class) {
return (ParamConverter<T>) new HogeParamConverter();
}
return null;
}
}
この方法は一番手間がかかりますがstatic
ファクトリメソッドを用いる方法と比べて
-
Hoge
をインターフェースにすることが可能 - 同じ型に対してもアノテーションによって異なる
ParamConverter
を使用できる -
java
から始まるパッケージのクラスなど既存のクラスも使用できる
といったことが利点だと思います。
まとめ
JAX-RS 2からParamConverter
が入った事でクリエパラメータやリクエストヘッダをどんな型でも受け取ることができるようになりました。
インターセプターやクライアントAPIに比べると地味に見えますが、なかなか素晴らしい進化だと個人的には思っています。
サンプル書きました。
Discussion