1

私はJerseyをテストしてい405 Method Not AllowedますPUT.

@Singleton @Path("images")
public class ImageResource {
    private static final String IMAGE_ID_PATH_PARAM = "{imageId : [A-Za-z0-9_\\-]+}";
    private static final String EXTENSION_PATH_PARAM = "{extension : (\\.[A-Za-z]+)?}";

    @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@GETパスをに設定した場合にのみ機能し@Path(IMAGE_ID_PATH_PARAM)ます。拡張部分を追加すると、405ステータス コードが表示されます。GETどちらの場合でも機能するようです。失敗した からの出力は次のPUTとおりです。

$ curl -v --header "Content-Type: image/jpeg" --upload-file /Users/andy/Desktop/test.jpg http://localhost:9090/images/abcde
* About to connect() to localhost port 9090 (#0)
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 9090 (#0)
> PUT /images/abcde HTTP/1.1
> User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
> Host: localhost:9090
> Accept: */*
> Content-Type: image/jpeg
> Content-Length: 48198
> Expect: 100-continue
> 
< HTTP/1.1 100 Continue
< HTTP/1.1 405 Method Not Allowed
< Content-Type: text/html; charset=iso-8859-1
< Date: Mon, 20 Aug 2012 18:35:59 GMT
< Allow: GET,OPTIONS,HEAD
< Transfer-Encoding: chunked

@Producesおよび注釈なしでテストも試みましたが、@Consumesどちらも機能しませんでした。

4

1 に答える 1

3

リクエストを送信するとどうなるか見てみましょう。

状況 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_PARAMGETこのリソースには、または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 が返されます。

これが発生する理由は、メソッドgetImageputImageが異なるリソースを表すようになったためです。注意深く見ると、パスは次のように読み取ることができます (わかりやすくするために正規表現は省略します)。

@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>

images2 つの別個のサブリソースがあり、それぞれに 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 クライアントにあまり時間をかけずに、リソース メソッドで何が起こっているかを確認するための優れた方法です。

于 2012-08-20T19:48:05.687 に答える