web-dev-qa-db-fra.com

Pouvons-nous avoir plus d'une annotation @Path pour la même REST

Pouvons-nous avoir plus d'une annotation @Path Pour la même REST c'est-à-dire que la méthode exécutée est la même, mais elle est exécutée lors de l'accès à plusieurs URL?

Par exemple: je veux exécuter la méthode searchNames() sur http://a/b/c Et http://a/b.

31
Unreal user

Vous ne pouvez pas avoir plusieurs annotations @Path Sur une seule méthode. Il provoque une erreur de syntaxe "annotation en double".

Cependant, il existe plusieurs façons de mapper efficacement deux chemins vers une méthode.

Expressions régulières dans l'annotation @Path

L'annotation @Path Dans JAX-RS accepte les paramètres, dont les valeurs peuvent être restreintes à l'aide d'expressions régulières.

Cette annotation:

@Path("a/{parameter: path1|path2}")

permettrait à la méthode d'être atteinte par des demandes pour /a/path1 et /a/path2. Si vous devez travailler avec des sous-chemins, échappez les barres obliques: {a:path1\\/subPath1|path2\\/subPath2}

Présentation des réponses avec un code d'état de redirection

Vous pouvez également configurer une redirection. Voici un moyen de le faire dans Jersey (l'implémentation de référence de JAX-RS), en définissant une autre sous-ressource. Ceci est juste un exemple, si vous préférez une autre façon de gérer les redirections, n'hésitez pas à l'utiliser.

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

}

Utilisation d'un filtre de servlet pour réécrire les URL

Si vous avez souvent besoin de telles fonctionnalités, je vous suggère d'intercepter les demandes entrantes à l'aide d'un filtre de servlet et de réécrire les chemins à la volée. Cela devrait vous aider à conserver toutes les redirections au même endroit. Idéalement, vous pourriez utiliser une bibliothèque prête. UrlRewriteFilter peut faire l'affaire, tant que vous êtes bien avec une licence BSD (consultez leur site de code Google pour plus de détails)

Une autre option consiste à gérer cela avec un proxy installé devant votre application Java. Vous pouvez configurer un serveur Apache pour offrir des règles de mise en cache et de réécriture de base sans compliquer votre Java code.

44
toniedzwiedz

Comme expliqué dans réponse de Tom , vous ne pouvez pas utiliser plus d'un @Path annotation sur une seule méthode, car vous allez rencontrer error: duplicate annotation au moment de la compilation.

Je pense que le moyen le plus simple de contourner cela est d'utiliser la surcharge de méthode:

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

Vous pouvez également utiliser des noms de méthode plus différents si vous rencontrez le cas où plusieurs méthodes surchargées ont la signature.

14
yegeniy

Une autre solution pour votre exemple particulier:

Supposons que:

  • /a est pour la classe de ressources
  • /b/c et /b sont les chemins des méthodes

car un chemin complet ressemble à:

<protocol><Host><port><app><url-pattern><resource-path><method-path>.

Utilisez le paramètre facultatif

@Path("/b{c : (/c)?}")
public Response searchNames(@PathParam("c") String val) {
    ...
}

L'exemple ci-dessus fonctionne pour tous les exemples comme:

  • /b
  • /b/
  • /b/c
  • /b/c/

mais lorsque c est fourni, le val est /c (il a un / avant).

Si vous souhaitez résoudre le problème ci-dessus (pour éviter Java), vous avez besoin de quelque chose de plus complexe:

@Path("/b{slash : (/)?}{c:((?<=/).*)?}")

qui renverra uniquement c (pas /c) pour le 3rd puce, mais pour le 4e puce, il renverra c/ qui doit être analysé en Java.

Mais pour votre cas ( "la méthode exécutée est la même"), ne vous inquiétez pas de l'analyse car vous n'avez pas d'actions différentes.

6
ROMANIA_engineer