gus*_*nke 2 java rest web-services 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
}
Run Code Online (Sandbox Code Playgroud)
但是,如果不执行以下操作,我还没有找到一种方法:
@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);
}
Run Code Online (Sandbox Code Playgroud)
有谁知道如何使第一个例子工作,或者用尽可能少的代码的另一种方法?
使用JAX-RS引用RESTful Java一书:
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 {
}
Run Code Online (Sandbox Code Playgroud)
如果你打开它@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
{
Run Code Online (Sandbox Code Playgroud)
所以,就是这样,你不能在同一种方法中使用它们.
也就是说,如果你真的必须,你可以通过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());
}
}
Run Code Online (Sandbox Code Playgroud)
@GET
您不能使用使用多个、@POST
、@PUT
、注释之一进行注释的 REST 方法@DELETE
,因为这与 HTTP 规范相冲突。
另外,如果myMethod2
只返回 的结果myMethod
,您可以在应用程序中使用其中唯一的一个(例如,myMethod
),因为基本上myMethod2
只是从服务器读取和检索数据,但不更新任何内容。这意味着用 进行注释是不合适的@POST
,因为它不会更新服务器上的任何内容。如果用 注释@POST
,它仍然可以工作,但不符合 HTTP 规范。
CRUD 操作和 HTTP 动词之间存在映射。当您在服务器上创建资源时,您必须使用PUT
or 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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
9732 次 |
最近记录: |