2013-05-10 120 views
2

我在我的RESTEasy服務中有一個方法,我想用它作爲@GET/@POST,它的數據可能來自查詢字符串和請求主體。RESTEasy - @ GET/@ 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); 
} 

有誰知道如何讓第一個例子中工作,或用最少的代碼的另一種方法可能?

+0

這種限制有什麼困擾你?是否需要複製註釋? – eiden 2013-05-10 21:10:20

回答

5

競標書REST風格的Java與JAX-RS

JAX-RS定義了五個註解映射到特定的HTTP操作:

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

(...)
@GET註釋指示JAX-RS運行時,這個Java方法 將處理HTTP GET請求的URI。您可以使用 之前描述的其他五個註釋之一綁定到 不同的HTTP操作。 但需要注意的一點是,您可能只能爲每個Java方法應用一個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()); 
    } 
} 
+0

這很奇怪,我沒有在'@ GET'和'@ POST'註解的方法中出現任何部署錯誤;另外,我可以使用它,但是如果定義了@ QueryParam,它總是用來代替'@ FormParam' .. – gustavohenke 2013-05-10 17:42:53

+0

我必須檢查,但是可能發生的是它正在失敗只有第一個註解(在方法和參數中)並忽略其餘部分。儘管如此,這是不可預知的行爲,因爲規範非常清楚不應該使用多於一個的規範。 – acdcjunior 2013-05-10 18:41:06

4

你不能有一個REST方法,這是註釋與@GET@POST@PUT@DELETE註解不止一個,因爲這是HTTP規範衝突。

而且,如果myMethod2剛剛返回的myMethod結果,你可以使用它們的唯一一個在你的應用程序(例如,myMethod),因爲基本上myMethod2只是讀取從服務器檢索數據,但不會更新任何內容。這意味着它是不恰當與@POST進行註釋,因爲它沒有在服務器上更新什麼。如果註釋爲@POST,它仍然可以工作,但不符合HTTP規範。

有CRUD操作和HTTP動詞之間的映射。在當你創建在服務器上的資源的情況下,你必須使用PUTPOST並在情況下,當你想要的從服務器某些資源,你應該使用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 
+0

雖然這篇文章的精神是好的..「你不能有一個REST方法,......用多個註釋......因爲這與HTTP規範衝突。」是不正確的。你不能,因爲RESTEasy不允許。我希望這樣做......因爲有時它會(或將會)方便地打破HTTP的精神來完成工作。 – 2013-11-05 19:18:11

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類應包含@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; 
} 

問候,
人員Prasanna。

+0

感謝您的回覆,但這並沒有回答這個問題;同樣,它已經被回答:) – gustavohenke 2013-09-26 21:48:00

+0

儘管這並不直接回答這個問題,但應該指出的是,它首先回答了引發問題的原因:一個人希望同時擁有「 @ get'和'@ post'方法主要用於重用查詢的條目參數。 – eddyce 2016-05-25 15:53:37