Java RESTEasy-在@GET/@POST时重用方法参数

Java RESTEasy-在@GET/@POST时重用方法参数,java,web-services,rest,jax-rs,resteasy,Java,Web Services,Rest,Jax Rs,Resteasy,我的RESTEasy服务中有一个方法,我想将其用作@GET/@POST,其数据可能来自查询字符串和请求正文 @GET @POST public String myMethod(@QueryParam("param1") @FormParam("param1") String param1, @QueryParam("param2") @FormParam("param1") String param2) { // ...do things }

我的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);
}

有人知道如何使第一个示例工作,或者使用尽可能少的代码实现另一种方法吗?

您不能使用REST方法,该方法使用多个
@GET
@POST
@PUT
@DELETE
注释进行注释,因为这与HTTP规范冲突

另外,如果
myMethod2
只返回
myMethod
的结果,那么您可以在应用程序中使用其中唯一的一个(例如,
myMethod
),因为基本上
myMethod2
从服务器读取数据,而检索数据,但不更新任何内容。这意味着用
@POST
注释是不合适的,因为它不会更新服务器上的任何内容。如果用
@POST
注释,它仍然可以工作,但不符合HTTP规范

CRUD操作和HTTP谓词之间存在映射。在服务器上创建资源时,必须使用
PUT
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
引用《使用JAX-RS实现RESTful Java》一书:

/**
 * 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
{
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方法 将处理对URI的HTTP GET请求。你会用 前面描述的要绑定到的其他五个注释之一 不同的HTTP操作不过,需要注意的一点是,您 每个Java方法只能应用一个HTTP方法注释。A. 如果应用多个,则会发生部署错误。

(上面的文字是由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
进行注释):

所以,就是这样,你不能用同一种方法同时拥有它们


也就是说,如果您真的必须这样做,您可以通过在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());
    }
}
公共类查询用于MParamTest{
@路径(“/”)
公共静态类InterceptedResource{
@得到
//@Path(“/stuff”)//取消对此的注释,它将不起作用
公共字符串otherService(@QueryParam(“yadda”)字符串名){
返回“本例中从未调用过Im”+名称;
}
}
公共静态类MyInterceptor实现预侦听器AcceptedByMethod{
@凌驾
公共布尔接受(类声明、方法){
System.out.println(“接受方法”+method.getName());
//您可以在此处检查此拦截器是否应作用于此方法
return true;//每次都会执行
}
@凌驾
公共服务器响应预处理(HttpRequest请求,ResourceMethod)
引发失败,WebApplicationException{
//解析表单参数
if(request.getHttpHeaders().getMediaType()!=null&&request.getHttpHeaders().getMediaType().isCompatible(MediaType.valueOf(“application/x-www-form-urlencoded”)){
多值Map formParameters=request.getFormParameters();
if(formParameters!=null){
for(字符串键:formParameters.keySet()){
System.out.println(“[FORM]”+key+”:“+formParameters.get(key));
}
}
}
//解析查询参数
多值Map queryParameters=request.getUri().getQueryParameters();
if(queryParameters!=null)
for(字符串键:queryParameters.keySet()){
System.out.println(“[QUERY]”+key+:“+queryParameters.get(key));
}
String responseText=“do something:”+request.getUri().getQueryParameters().getFirst(“测试”);
返回新的ServerResponse(responseText,200,newheaders());
}
}
@试验
public void test()引发异常{
Dispatcher=MockDispatcherFactory.createDispatcher();
dispatcher.getProviderFactory().getServerPreProcessInterceptorRegistry().register(新的MyInterceptor());
dispatcher.getRegistry().addSingletonResource(新的InterceptedResource());
MockHttpRequest请求=MockHttpRequest.get(“/?test=someStuff”);
MockHttpResponse response=新的MockHttpResponse();
调用(请求、响应);
System.out.println(response.getContentAsString());
Assert.assertEquals(“做某事:做某事”,res
@GET    
@Path("/")  
@Produces("application/json")
@Consumes("application/json")

public Response search(@Form CatalogSearchRequest reqObject)      
{

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


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