java - error - ¿Podemos tener más de una anotación @Path para el mismo método REST?
private void initcomponents() (3)
¿Podemos tener más de una anotación @Path
para el mismo método REST, es decir, el método ejecutado es el mismo, pero se ejecuta al acceder a más de una URL?
Por ejemplo: quiero ejecutar el método searchNames()
tanto en http://a/b/c
como http://a/b
.
Como se explica en la respuesta de Tom , no puede usar más de una anotación @Path
en un solo método, porque se encontrará con el error: duplicate annotation
en tiempo de compilación.
Creo que la forma más sencilla de evitar esto es utilizar la sobrecarga de métodos:
@Path("{foo}")
public Response rest(@PathParam("foo") final String foo) {
return this.rest(foo, "");
}
@Path("{foo}/{bar}")
public Response rest(@PathParam("foo") final String foo,
@PathParam("bar") final String bar) {
return Response.ok(foo + " " + bar).build();
}
También podría usar más nombres de métodos diferentes si se encuentra con el caso en que múltiples métodos sobrecargados tienen la firma.
No puede tener anotaciones @Path
en un único método. Causa un error de sintaxis de "anotación duplicada".
Sin embargo, hay una serie de formas en que puede asignar efectivamente dos rutas a un método.
Expresiones regulares en la anotación @Path
La anotación @Path
en JAX-RS acepta parámetros, cuyos valores pueden restringirse utilizando expresiones regulares.
Esta anotación:
@Path("a/{parameter: path1|path2}")
permitiría que el método sea alcanzado por las solicitudes para /a/path1
y /a/path2
. Si necesita trabajar con subtrazos, escapes de escape: {a:path1///subPath1|path2///subPath2}
Sirviendo respuestas con un código de estado de redirección
Alternativamente, puede configurar una redirección. Aquí hay una manera de hacerlo en Jersey (la implementación de referencia de JAX-RS), definiendo otro subrecurso. Esto es solo un ejemplo, si prefiere una forma diferente de manejar las redirecciones, siéntase libre de usarla.
@Path("basepath")
public class YourBaseResource {
//this gets injected after the class is instantiated by Jersey
@Context
UriInfo uriInfo;
@Path("a/b")
@GET
public Responce method1(){
return Response.ok("blah blah").build();
}
@Path("a/b/c")
@GET
public Response method2(){
UriBuilder addressBuilder = uriInfo.getBaseUriBuilder();
addressBuilder.path("a/b");
return Response.seeOther(addressBuilder.build()).build();
}
}
Usar un filtro de servlet para reescribir las URL
Si va a necesitar dicha funcionalidad con frecuencia, sugiero interceptar las solicitudes entrantes utilizando un filtro de servlet y reescribir las rutas sobre la marcha. Esto debería ayudarte a mantener todas las redirecciones en un solo lugar. Idealmente, podría usar una biblioteca preparada. UrlRewriteFilter
puede hacer el truco, siempre y cuando esté bien con una licencia BSD (consulte su sitio de código de google para más detalles)
Otra opción es manejar esto con un proxy configurado en frente de su aplicación Java. Puede configurar un servidor Apache para ofrecer reglas básicas de caché y reescritura sin complicar su código Java.
Otra solución para tu ejemplo particular:
Supongamos que:
-
/a
es para la clase de recursos -
/b/c
y/b
son las rutas para los métodos
porque una ruta completa se ve así:
<protocol><host><port><app><url-pattern><resource-path><method-path>
.
Use el parámetro opcional
@Path("/b{c : (/c)?}")
public Response searchNames(@PathParam("c") String val) {
...
}
El ejemplo anterior funciona para todos los ejemplos como:
-
/b
-
/b/
-
/b/c
-
/b/c/
pero cuando se proporciona c
, el val
es /c
(tiene a /
antes).
Si desea solucionar el problema anterior (para evitar el análisis de Java), necesita algo más complejo:
@Path("/b{slash : (/)?}{c:((?<=/).*)?}")
que devolverá solo c
(no /c
) para el tercer punto, pero para el cuarto punto devolverá c/
que se debe analizar en Java.
Pero para su caso ( "el método ejecutado es el mismo" ), no se preocupe por el análisis porque no tiene diferentes acciones.