リクエストを送信するとどうなるか見てみましょう。
状況 1: 延長なし
メソッドは次のようになります。
@GET @Path(IMAGE_ID_PATH_PARAM)
@Produces("image/*")
public Response getImage(@PathParam("imageId") String imageId,
@PathParam("extension") String extension, @QueryParam("mods") String mods) {
...
}
@PUT @Path(IMAGE_ID_PATH_PARAM)
@Consumes("image/*")
public Response putImage(@PathParam("imageId") String imageId, File image) {
...
}
次のリクエストを送信すると:
PUT http://localhost:9090/images/abcde
最初に、Jersey は問題の URI を持つリソースを探します。
http://localhost:9090/images/abcde
リソースが見つかったら、そのリソースにアクセスするために使用できるメソッドを確認します。この場合、 で定義されたパスを持つ単一のリソースがありますIMAGE_ID_PATH_PARAM
。GET
このリソースには、またはPUT
リクエストでアクセスできます。注釈で指定したとおりです。
状況 2: 拡張機能が追加されたgetImage
メソッドは次のようになります。
@GET @Path(IMAGE_ID_PATH_PARAM + EXTENSION_PATH_PARAM)
@Produces("image/*")
public Response getImage(@PathParam("imageId") String imageId,
@PathParam("extension") String extension, @QueryParam("mods") String mods) {
...
}
@PUT @Path(IMAGE_ID_PATH_PARAM)
@Consumes("image/*")
public Response putImage(@PathParam("imageId") String imageId, File image) {
...
}
再度、同じリクエストを送信します。
PUT http://localhost:9090/images/abcde
また、Jersey は URL に一致する最初のリソースを見つけます。getImage
最初と同じように、リソースはメソッドによって表されます。今回も、@GET
アノテーションがリクエストと一致しません。前と同じように、Jersey は、リクエストに一致するように、リソースに使用できる別のメソッドを見つけようとします。
ただし、今回はそのようなメソッドが見つからないため、405 が返されます。
これが発生する理由は、メソッドgetImage
とputImage
が異なるリソースを表すようになったためです。注意深く見ると、パスは次のように読み取ることができます (わかりやすくするために正規表現は省略します)。
@Path({imageId}{extension})
為にgetImage
と
@Path({imageId})
為にputImage
正規表現を考慮すると、これら 2 つのパスは同じものになる可能性がありますが、Jersey はそれらを別個のリソースの識別子と見なします。
Jersey によって生成された WADL (標準に慣れていない場合は、ここを参照してください) ファイル (で入手できるはずですhttp://localhost:9090/application.wadl
) を見ると、まさにこれが起こっていることに気付くでしょう。
<application xmlns="http://research.sun.com/wadl/2006/10">
<resources base="http://localhost:9090/">
<resource path="images">
<resource path="{imageId : [A-Za-z0-9_\-]+}">
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="imageId" style="template" type="xs:string"/>
<method id="putImage" name="PUT">
<request>
<representation mediaType="image/*"/>
</request>
<response>
<representation mediaType="*/*"/>
</response>
</method>
</resource>
<resource path="{imageId : [A-Za-z0-9_\-]+}{extension : (\.[A-Za-z]+)?}">
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="extension" style="template" type="xs:string"/>
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="imageId" style="template" type="xs:string"/>
<method id="getImage" name="GET">
<request>
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="mods" style="query" type="xs:string"/>
</request>
<response>
<representation mediaType="image/*"/>
</response>
</method>
</resource>
</resource>
</resources>
</application>
images
2 つの別個のサブリソースがあり、それぞれに 1 つのメソッドがあることに注目してください。
解決
のアノテーションにEXTENSION_PATH_PARAM
セグメントを追加すると、これら 2 つのメソッドが再び単一のリソースにマップされるため、問題は解消されます。正規表現はこの部分をオプションにするので、自由に省略して存在しないふりをすることができます。putImage
@Path
違いは、生成された WADL で明確に確認できます。
<application xmlns="http://research.sun.com/wadl/2006/10">
<resources base="http://localhost:9090/">
<resource path="images">
<resource path="{imageId : [A-Za-z0-9_\-]+}{extension : (\.[A-Za-z]+)?}">
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="extension" style="template" type="xs:string"/>
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="imageId" style="template" type="xs:string"/>
<method id="putImage" name="PUT">
<request>
<representation mediaType="image/*"/>
</request>
<response>
<representation mediaType="*/*"/>
</response>
</method>
<method id="getImage" name="GET">
<request>
<param xmlns:xs="http://www.w3.org/2001/XMLSchema" name="mods" style="query" type="xs:string"/>
</request>
<response>
<representation mediaType="image/*"/>
</response>
</method>
</resource>
</resource>
</resources>
</application>
この場合、images
には 1 つのサブリソースがあり、これには 2 つの使用可能なメソッドがあります。
個人的には、WADL の自動生成は Jersey の素晴らしい機能だと思います。これは、curl やその他の REST クライアントにあまり時間をかけずに、リソース メソッドで何が起こっているかを確認するための優れた方法です。