本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
(...)アノテーションは、
この@GET
Java メソッドが 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());
}
}