2

@GETRESTEasy サービスに/の両方として使用したいメソッドが@POSTあり、そのデータはクエリ文字列とリクエスト本文の両方から取得される場合があります。

@GET
@POST
public String myMethod(@QueryParam("param1") @FormParam("param1") String param1,
                       @QueryParam("param2") @FormParam("param1") String param2) {
    // ...do things
}

ただし、次のことを行わずにこれを行う方法をまだ見つけていません。

@GET
public String myMethod(@QueryParam("param1") String param1, @QueryParam("param2") String param2) {
    // ...do things
}

@POST
public String myMethod2(@FormParam("param1") String param1, @FormParam("param2") String param2) {
    return this.myMethod(param1, param2);
}

最初の例を機能させる方法、またはコードを最小限に抑えた別のアプローチを知っている人はいますか?

4

3 に答える 3

6

本RESTful Java with JAX-RS を引用します。

JAX-RS は、特定の HTTP 操作にマップする 5 つのアノテーションを定義します。

  • @javax.ws.rs.GET
  • @javax.ws.rs.PUT
  • @javax.ws.rs.POST
  • @javax.ws.rs.DELETE
  • @javax.ws.rs.HEAD

(...)アノテーションは、
この@GETJava メソッドが URI への HTTP GET 要求を処理することを JAX-RS ランタイムに指示します。前述の他の 5 つのアノテーションのいずれかを使用して、さまざまな HTTP 操作にバインドします。ただし、Java メソッドごとに 1 つの HTTP メソッド アノテーションしか適用できないことに注意してください。複数適用すると展開エラーが発生します。

(上記のテキストは、RESTEasy の作成者によって書かれました。)

つまり、RESTEasy は JAX-RS に準拠しているため、複数の HTTP 動詞でメソッドに注釈を付けることはできません。

確信が持てない場合は、@GETアノテーションを見ると、それが へのメタアノテーションにすぎないことがわかります@HttpMethod

/**
 * Indicates that the annotated method responds to HTTP GET requests
 * @see HttpMethod
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod(HttpMethod.GET)
public @interface GET { 
}

また、 を開いた場合@HttpMethodは、javadoc を確認してください (メソッドに . で注釈が付けられた複数の注釈を付けることはエラーHttpMethodです)。

/**
 * Associates the name of a HTTP method with an annotation. A Java method annotated
 * with a runtime annotation that is itself annotated with this annotation will
 * be used to handle HTTP requests of the indicated HTTP method. It is an error
 * for a method to be annotated with more than one annotation that is annotated
 * with {@code HttpMethod}.
 *
 * @see GET
 * @see POST
 * @see PUT
 * @see DELETE
 * @see HEAD
 */
@Target({ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HttpMethod
{

つまり、両方を同じ方法で使用することはできません。


そうは言っても、本当に必要な場合はPreProcessInterceptor、JAX-RS メソッドの前に呼び出される を介してそれを達成できます。

それでも、この方法ははるかに複雑で (パラメーターを自分で解析する必要があるため)、保守性がはるかに低くなります (サービスがインターセプターで配信される!?)。

要するに、私の知る限り、あなたのソリューションは最適です。

以下のテストで私が言っていることを確認してください。

public class QueryAndFormParamTest  {

    @Path("/")
    public static class InterceptedResource {
        @GET
        //@Path("/stuff") // uncomment this and it will not work
        public String otherService(@QueryParam("yadda") String name){
            return "Im never called in this example" + name;
        }
    }

    public static class MyInterceptor implements PreProcessInterceptor, AcceptedByMethod {
        @Override
        public boolean accept(Class declaring, Method method) {
            System.out.println("Accepted by method "+method.getName());
            // you can check if this interceptor should act on this method here
            return true; // it'll act everytime
        }

        @Override
        public ServerResponse preProcess(HttpRequest request, ResourceMethod method)
                throws Failure, WebApplicationException {

            // parsing form parameters
            if (request.getHttpHeaders().getMediaType() != null && request.getHttpHeaders().getMediaType().isCompatible(MediaType.valueOf("application/x-www-form-urlencoded"))) {
                MultivaluedMap<String, String> formParameters = request.getFormParameters();
                if (formParameters != null) {
                    for (String key : formParameters.keySet()) {
                        System.out.println("[FORM] "+key + ": "+formParameters.get(key));
                    }
                }
            }

            // parsing query parameters
            MultivaluedMap<String, String> queryParameters = request.getUri().getQueryParameters();
            if (queryParameters != null)
            for (String key : queryParameters.keySet()) {
                System.out.println("[QUERY] "+key + ": "+queryParameters.get(key));
            }

            String responseText = "do something: " + request.getUri().getQueryParameters().getFirst("test");
            return new ServerResponse(responseText, 200, new Headers<Object>());
        }
    }

    @Test
    public void test() throws Exception {
        Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
        dispatcher.getProviderFactory().getServerPreProcessInterceptorRegistry().register(new MyInterceptor());
        dispatcher.getRegistry().addSingletonResource(new InterceptedResource());

        MockHttpRequest request = MockHttpRequest.get("/?test=someStuff");
        MockHttpResponse response = new MockHttpResponse();

        dispatcher.invoke(request, response);

        System.out.println(response.getContentAsString());
        Assert.assertEquals("do something: someStuff", response.getContentAsString());
    }
}
于 2013-05-10T15:42:33.953 に答える
5

HTTP 仕様と競合するため、複数の@GET@POST@PUT、アノテーションが付けられた REST メソッドを使用することはできません。@DELETE

また、myMethod2の結果を返すだけの場合myMethodは、アプリケーションでそれらのうちの 1 つだけを使用できます (たとえば、myMethod)。これは、基本的にサーバーからデータを読み取っ取得myMethod2するだけで、何も更新しないためです。これは、サーバー上で何も更新しないため、 で注釈を付けるのは適切ではないことを意味します。で注釈が付けられていても機能しますが、HTTP 仕様には適合しません。@POST@POST

CRUD 操作と HTTP 動詞の間にはマッピングがあります。サーバー上にリソースを作成する場合はPUTorを使用する必要があり、サーバーからリソースを読み取りPOSTたい場合は を使用する必要があります。すべてのケースは次のとおりです。GET

Create = PUT with a new URI
         POST to a base URI returning a newly created URI
Read   = GET
Update = PUT with an existing URI
Delete = DELETE
于 2013-05-10T14:30:20.977 に答える
1

複数の queryParam を単一のオブジェクトにバインドするには、応答メソッドに @Form を引数として追加する必要があります。それは私たちにとってうまくいきます。

@GET    
@Path("/")  
@Produces("application/json")
@Consumes("application/json")

public Response search(@Form CatalogSearchRequest reqObject)      
{

System.out.println("Entered into service"+reqObject.getAttribute());


}

POJO CLASS には、すべての属性に対して @QueryParam("") を含める必要があります
。たとえば、次のようになります。

@QueryParam("pageSize")
public Integer pageSize;

@QueryParam("page")
public Integer page;

public Integer getPageSize() {
    return pageSize;
}

public void setPageSize(Integer pageSize) {
    this.pageSize = pageSize;
}

public Integer getPage() 
{
 return page;
}

public void setPage(Integer page)
{
    this.page = page;
}

よろしく、
プラサナ。

于 2013-09-26T12:08:01.327 に答える