JAX-RSでのURL構築のやり方をまとめてみた

【前提条件】

[環境]
[設定など]

コンテキストパスは「/」で動作させています。

【概要】

JAX-RSリソースのURIを取得する際に
UriBuilder#fromMethodを使うとパスを意識しすぎてなくて良いと
教えていただきました。

使っているうちにメソッドを組み合わせないと上手くいかないケースが出てきたので、
ちょっとまとめてみました。

便利メソッドが別にあって、そんなことしなくても・・・
と言うのはあるかもしれません。

【サンプルで使うリソースクラス】

サンプルで使用するリソースクラスは下記のようになります。

import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path("/root/sample-resource")
public class SampleResource {

    @Path("/sample-1")
    public Response sample1() {

        return null;
    }

    @Path("/pathParam/{id}/{mode}/hoge")
    public Response samplePathParam() {

        return null;
    }
}

今回は@Pathのところだけしか使わないので、中身は適当です。

【fromResource/fromMethod】

fromResourceメソッドはクラスから、fromMethodはメソッドからパスの情報を取得します。

[ソース]
    System.out.println(UriBuilder.fromResource(SampleResource.class).build());
    System.out.println(UriBuilder.fromMethod(SampleResource.class, "sample1").build());

UriBuilder#buildはUriBuilderからjava.net.URIクラスのオブジェクトを生成します。

[結果]
/root/sample-resource
/sample-1

それぞれクラス/メソッドで指定した@Pathの値が出力されます。

【メソッドのフルパスを取得】

SampleResource#samplePathParamのパスは「/root/sample-resource/sample-1」になるので、
メソッドを1回呼び出しただけでは取得できません。

一度パスを文字列にして、再度UriBuilderを構築します。

    String base = UriBuilder.fromResource(SampleResource.class).toTemplate();
    String append = UriBuilder.fromMethod(SampleResource.class, "sample1").toTemplate();

    UriBuilder builder = UriBuilder.fromUri(base + append);
    System.out.println(builder.build());

UriBuilder#toTemplateでそれぞれの文字列が帰ってきます。

UriBuilder#fromUriにつなげた文字列を渡すとUriBuilderのオブジェクトが作成されます。

[結果]

UriBuilder#toTemplate

【パスパラメータ】

@PathParamを使ってパスからパラメータを取得するような形式だった場合は
どうするかというのもメソッドとして提供されています。

[ソース]
    String base = UriBuilder.fromResource(SampleResource.class).toTemplate();
    String append = UriBuilder.fromMethod(SampleResource.class, "samplePathParam").toTemplate();
    UriBuilder builder = UriBuilder.fromUri(base + append);

先ほどと同じようにSampleResource#samplePathParamに対してUriBuilderを構築します。

    System.out.println(builder.build(8009, "ajp"));

    UriBuilder pathChanged = builder.resolveTemplate("mode", "ajp").resolveTemplate("id", 8009);
    System.out.println(pathChanged.build());

やり方は二通りあります。

まずはUriBuilder#buildにパラメータを渡すパターンです。
記述はシンプルですが、順番に依存するのがデメリットだと思います。

UriBuilder#resolveTemplateで値を設定するパターンです。
記述量は増えて面倒ですが、順番に対しては依存していません。
名前には依存してしまいますが。

[結果]
/root/sample-resource/pathParam/8009/ajp/hoge
/root/sample-resource/pathParam/8009/ajp/hoge

【まとめ】

UriBuilder、便利。