Quand utiliser @QueryParam vs @PathParam

277

Je ne pose pas la question qui est déjà posée ici: Quelle est la différence entre @PathParam et @QueryParam

Il s'agit d'une question de «meilleures pratiques» ou de convention.

Quand souhaitez - vous utiliser @PathParamvs @QueryParam.

Ce que je peux penser que la décision pourrait être d'utiliser les deux pour différencier le modèle d'information. Permettez-moi d'illustrer ci-dessous mon LTPO - observation moins que parfaite.

L'utilisation de PathParam pourrait être réservée à la catégorie d'informations, qui tomberait bien dans une branche d'un arbre d'informations. PathParam peut être utilisé pour explorer la hiérarchie des classes d'entités.

Considérant que, QueryParam pourrait être réservé pour spécifier des attributs pour localiser l'instance d'une classe.

Par exemple,

  • /Vehicle/Car?registration=123
  • /House/Colonial?region=newengland

/category?instance

@GET
@Path("/employee/{dept}")
Patient getEmployee(@PathParam("dept")Long dept, @QueryParam("id")Long id) ;

contre /category/instance

@GET
@Path("/employee/{dept}/{id}")
Patient getEmployee(@PathParam("dept")Long dept, @PathParam("id")Long id) ;

contre ?category+instance

@GET
@Path("/employee")
Patient getEmployee(@QueryParam("dept")Long dept, @QueryParam("id")Long id) ;

Je ne pense pas qu'il existe une convention standard de le faire. Y a-t-il? Cependant, j'aimerais savoir comment les gens utilisent PathParam vs QueryParam pour différencier leurs informations comme je l'ai illustré ci-dessus. J'aimerais aussi entendre la raison de cette pratique.

Geek béni
la source
4
doublon possible de Quand utiliser pathParams ou QueryParams
Joachim Sauer

Réponses:

245

REST n'est peut-être pas un standard en tant que tel, mais la lecture de la documentation générale REST et des articles de blog devrait vous donner quelques directives pour un bon moyen de structurer les URL d'API. La plupart des API de repos ont tendance à avoir uniquement des noms et des ID de ressource dans le chemin. Tel que:

/departments/{dept}/employees/{id}

Certaines API REST utilisent des chaînes de requête pour le filtrage, la pagination et le tri, mais comme REST n'est pas une norme stricte, je recommanderais de vérifier certaines API REST telles que github et stackoverflow et de voir ce qui pourrait bien fonctionner pour votre cas d'utilisation.

Je recommanderais de mettre tous les paramètres requis dans le chemin, et tous les paramètres facultatifs devraient certainement être des paramètres de chaîne de requête. Mettre des paramètres facultatifs dans le chemin finira par devenir vraiment compliqué lorsque vous essayez d'écrire des gestionnaires d'URL qui correspondent à différentes combinaisons.

theon
la source
73
" Je recommanderais de mettre tous les paramètres requis dans le chemin, et tous les paramètres facultatifs devraient certainement être des paramètres de chaîne de requête. " - thumbs up +1 yes def
smeeb
1
si cette convention est également utilisée pour la requête Put, disons que nous voulons mettre à jour une version spécifique de l'entité db, si l'URI est PUT /depatments/{dept}/employees/{id}/{version}et la version est facultative ou doit-elle être PUT /depatments/{dept}/employees/{id}?version=12et la version est facultative
meilleurs voeux
Dans ce cas, je recommanderais: - PUT /depatments/{dept}/employees/{id}/versions/{version}de créer un employé avec une version choisie - POST /depatments/{dept}/employees/{id}/versionsde créer un employé avec une version déterminée par le backend
Guillaume Vauvert
90

C'est ce que je fais.

S'il existe un scénario pour récupérer un enregistrement basé sur l'ID, par exemple, vous devez obtenir les détails de l'employé dont l'ID est 15, vous pouvez disposer de ressources avec @PathParam.

GET /employee/{id}

S'il y a un scénario où vous devez obtenir les détails de tous les employés mais seulement 10 à la fois, vous pouvez utiliser le paramètre de requête

GET /employee?start=1&size=10

Cela signifie que le premier ID d'employé obtient dix enregistrements.

Pour résumer, utilisez @PathParam pour la récupération basée sur l'id. L'utilisateur @QueryParam pour le filtre ou si vous avez une liste fixe d'options que l'utilisateur peut transmettre.

Arun B Chandrasekaran
la source
'@PathParam' et '@QueryParam' offrent-ils les mêmes fonctionnalités? '@QueryParam' est-il juste une autre façon d'écrire la même chose?
Rishabh Agarwal
1
@RishabhAgarwal même si les deux fournissent les mêmes fonctionnalités, la pratique du code propre est qu'il est conseillé de mettre un paramètre requis comme variable de chemin et tout paramètre facultatif comme paramètre de requête.
Akhil Ghatiki
@RishabhAgarwal Pour plus d'informations, vous pouvez vous référer à mon article Meilleures pratiques d'API Rest
Arun B Chandrasekaran
43

Je pense que si le paramètre identifie une entité spécifique, vous devez utiliser une variable de chemin. Par exemple, pour obtenir tous les messages sur mon blog, je demande

GET: myserver.com/myblog/posts

pour obtenir le message avec id = 123, je demanderais

GET: myserver.com/myblog/posts/123

mais pour filtrer ma liste de messages et obtenir tous les messages depuis le 1er janvier 2013, je demanderais

GET: myserver.com/myblog/posts?since=2013-01-01

Dans le premier exemple, "posts" identifie une entité spécifique (l'ensemble de la collection de billets de blog). Dans le deuxième exemple, "123" représente également une entité spécifique (un seul article de blog). Mais dans le dernier exemple, le paramètre "since = 2013-01-01" est une demande de filtrage de la collection de publications et non une entité spécifique. La pagination et l'ordre seraient un autre bon exemple, à savoir

GET: myserver.com/myblog/posts?page=2&order=backward

J'espère que cela pourra aider. :-)

10GritSandpaper
la source
8

J'ai personnellement utilisé l'approche "s'il est logique pour l'utilisateur de mettre en signet une URL qui inclut ces paramètres, alors utiliser PathParam".

Par exemple, si l'URL d'un profil utilisateur comprend un paramètre d'ID de profil, car cela peut être mis en signet par l'utilisateur et / ou envoyé par e-mail, j'inclurais cet ID de profil comme paramètre de chemin. En outre, une autre considération à cela est que la page indiquée par l'URL qui inclut le paramètre de chemin ne change pas - l'utilisateur va configurer son profil, l'enregistrer, puis il est peu probable qu'il change beaucoup à partir de là; cela signifie que les webcrawlers / moteurs de recherche / navigateurs / etc peuvent bien mettre en cache cette page en fonction du chemin d'accès.

Si un paramètre passé dans l'URL est susceptible de modifier la mise en page / le contenu de la page, je l'utiliserais comme un queryparam. Par exemple, si l'URL du profil prend en charge un paramètre qui spécifie s'il faut afficher l'e-mail de l'utilisateur ou non, je considérerais qu'il s'agit d'un paramètre de requête. (Je sais, sans doute, vous pourriez dire que le &noemail=1paramètre ou quel qu'il soit peut être utilisé comme paramètre de chemin d'accès et génère 2 pages distinctes - une avec le courrier électronique, une sans) - mais logiquement ce n'est pas le cas: il est toujours la même page avec ou sans certains attributs affichés.

J'espère que cela aide - j'apprécie que l'explication soit un peu floue :)

Liv
la source
Je pense que cette réponse confond les ressources avec les itinéraires. La question concerne les ressources d'une API REST, renvoyant généralement JSON ou XML, et non les itinéraires d'une application Web, qui vous aident à naviguer dans l'application.
Hampus
5

C'est une question très intéressante.

Vous pouvez les utiliser tous les deux, il n'y a pas de règle stricte à ce sujet, mais l'utilisation de variables de chemin URI présente certains avantages:

  • Cache : la plupart des services de cache Web sur Internet ne mettent pas en cache la requête GET lorsqu'ils contiennent des paramètres de requête. Ils le font parce qu'il y a beaucoup de systèmes RPC qui utilisent des requêtes GET pour changer des données sur le serveur (échec !! Get doit être une méthode sûre)

Mais si vous utilisez des variables de chemin, tous ces services peuvent mettre en cache vos demandes GET.

  • Hiérarchie : les variables de chemin peuvent représenter la hiérarchie: / Ville / Rue / Lieu

Il donne à l'utilisateur plus d'informations sur la structure des données.

Mais si vos données n'ont pas de relation hiérarchique, vous pouvez toujours utiliser des variables Path, en utilisant des virgules ou des points-virgules:

/ Ville / longitude, latitude

En règle générale, utilisez une virgule lorsque l'ordre des paramètres est important, utilisez le point-virgule lorsque l'ordre n'a pas d'importance:

/ IconGenerator / rouge; bleu; vert

En dehors de ces raisons, il existe des cas où il est très courant d'utiliser des variables de chaîne de requête:

  • Lorsque vous avez besoin du navigateur pour mettre automatiquement des variables de formulaire HTML dans l'URI
  • Lorsque vous traitez avec un algorithme. Par exemple, le moteur Google utilise des chaînes de requête:

http: // www.google.com/search?q=rest

Pour résumer, il n'y a aucune raison valable d'utiliser l'une de ces méthodes, mais chaque fois que vous le pouvez, utilisez des variables URI.

jfcorugedo
la source
2

Comme theon l'a noté, REST n'est pas une norme. Cependant, si vous cherchez à implémenter une convention d'URI basée sur des normes, vous pouvez envisager la convention d'URI oData . La version 4 a été approuvée en tant que norme OASIS et des bibliothèques existent pour oData pour divers langages, y compris Java via Apache Olingo . Ne vous laissez pas rebuter par le fait que c'est un rejeton de Microsoft, car il a également obtenu le soutien d'autres acteurs de l'industrie , notamment Red Hat, Citrix, IBM, Blackberry, Drupal, Facebook Netflix et SAP

Plus d'adoptants sont répertoriés ici

MikeM
la source
2

De Wikipédia: Uniform Resource Locator

Un chemin d'accès , qui contient des données, généralement organisées sous forme hiérarchique , qui apparaît comme une séquence de segments séparés par des barres obliques.

Une requête facultative , séparée de la partie précédente par un point d'interrogation (?), Contenant une chaîne de requête de données non hiérarchiques .

- Selon la conception conceptuelle de l'URL, nous pouvons implémenter un PathParam pour les composants hiérarchiques de données / directives / localisateurs, ou implémenter un QueryParam lorsque les données ne sont pas hiérarchiques. Cela est logique car les chemins sont naturellement ordonnés, tandis que les requêtes contiennent des variables qui peuvent être ordonnées arbitrairement (paires variable / valeur non ordonnées).

Un commentateur précédent a écrit:

Je pense que si le paramètre identifie une entité spécifique, vous devez utiliser une variable de chemin.

Un autre a écrit:

Utilisez @PathParam pour la récupération en fonction de l'ID. L'utilisateur @QueryParam pour le filtre ou si vous avez une liste fixe d'options que l'utilisateur peut transmettre.

Un autre,

Je recommanderais de mettre tous les paramètres requis dans le chemin, et tous les paramètres facultatifs devraient certainement être des paramètres de chaîne de requête.

- Cependant, on pourrait mettre en œuvre un système flexible et non hiérarchique pour identifier des entités spécifiques! On peut avoir plusieurs index uniques sur une table SQL et permettre aux entités d'être identifiées à l'aide de n'importe quelle combinaison de champs qui composent un index unique! Différentes combinaisons (peut-être également ordonnées différemment) peuvent être utilisées pour les liens provenant de diverses entités liées (référents). Dans ce cas, nous pouvons avoir affaire à des données non hiérarchiques, utilisées pour identifier des entités individuelles - ou dans d'autres cas, ne spécifier que certaines variables / champs - certains composants d'index uniques - et récupérer une liste / un ensemble d'enregistrements. Dans de tels cas, il pourrait être plus facile, plus logique et raisonnable d'implémenter les URL en tant que QueryParams!

Une longue chaîne hexadécimale pourrait-elle diluer / diminuer la valeur des mots clés dans le reste du chemin? Cela pourrait valoir la peine considérer les implications SEO potentielles du placement de variables / valeurs dans le chemin ou dans la requêteet les implications pour l'interface humaine de savoir si nous voulons que les utilisateurs puissent parcourir / explorer la hiérarchie des URL en modifiant le contenu de la barre d'adresse. Ma page 404 Not Found utilise des variables SSI pour rediriger automatiquement les URL cassées vers leur parent! Les robots de recherche peuvent également parcourir la hiérarchie des chemins. D'un autre côté, personnellement, lorsque je partage des URL sur les réseaux sociaux, je supprime manuellement tous les identifiants uniques privés - généralement en tronquant la requête de l'URL, en ne laissant que le chemin d'accès: dans ce cas, il est utile de placer des identifiants uniques dans le chemin d'accès plutôt que dans la requête. Que nous voulions faciliter l'utilisation des composants de chemin d'accès en tant qu'interface utilisateur brute, cela dépend peut-être si les données / composants sont lisibles par l'homme ou non. La question de la lisibilité humaine se rattache quelque peu à la question de la hiérarchie: souvent, les données qui peuvent être exprimées sous forme de mots clés lisibles par l'homme sont également hiérarchiques; tandis que les données hiérarchiques peuvent souvent être exprimées sous forme de mots clés lisibles par l'homme. (Les moteurs de recherche eux-mêmes peuvent être définis comme augmentant l'utilisation des URL comme interface utilisateur.) Les hiérarchies de mots clés ou de directives peuvent ne pas être strictement ordonnées, mais elles sont généralement suffisamment proches pour que nous puissions couvrir d'autres cas dans le chemin, etétiqueter une option comme cas "canonique" .

Il existe fondamentalement plusieurs types de questions auxquelles nous pourrions répondre avec l'URL de chaque demande:

  1. Quel genre de document / chose demandons-nous / servons-nous?
  2. Quels sont ceux qui nous intéressent?
  3. Comment voulons-nous présenter les informations / enregistrements?

Q1 est presque certainement mieux couvert par le chemin ou par PathParams. Q3 (qui est probablement contrôlé via un ensemble de paramètres optionnels et de valeurs par défaut arbitrairement ordonnés); est presque certainement mieux couvert par QueryParams. Q2: Cela dépend…

Matthew Slyman
la source
2

Vous pouvez prendre en charge à la fois les paramètres de requête et les paramètres de chemin, par exemple, dans le cas de l'agrégation de ressources - lorsque la collection de sous-ressources a un sens en soi.

/departments/{id}/employees
/employees?dept=id

Les paramètres de requête peuvent prendre en charge un sous-ensemble hiérarchique et non hiérarchique; les paramètres de chemin sont hiérarchiques uniquement.

Les ressources peuvent présenter plusieurs hiérarchies. Prend en charge les chemins d'accès courts si vous interrogez de larges sous-collections qui traversent des limites hiérarchiques.

/inventory?make=toyota&model=corolla
/inventory?year=2014

Utilisez des paramètres de requête pour combiner des hiérarchies orthogonales.

/inventory/makes/toyota/models/corolla?year=2014
/inventory/years/2014?make=toyota&model=corolla
/inventory?make=toyota&model=corolla&year=2014

Utilisez uniquement les paramètres de chemin dans le cas de la composition - lorsqu'une ressource n'a pas de sens divorcée de son parent et que la collection globale de tous les enfants n'est pas une ressource utile en soi.

/words/{id}/definitions
/definitions?word=id   // not useful
Steve Mitchell
la source
1

La raison est en fait très simple. Lorsque vous utilisez un paramètre de requête, vous pouvez saisir des caractères tels que "/" et votre client n'a pas besoin de les coder en HTML. Il y a d'autres raisons, mais c'est un exemple simple. Quant à savoir quand utiliser une variable de chemin. Je dirais chaque fois que vous traitez avec des identifiants ou si la variable de chemin est une direction pour une requête.

Tony
la source
1

Je donne un exemple à underandand quand utilisons-nous @Queryparamet@pathparam

Par exemple, je prends une ressource est la carResourceclasse

Si vous souhaitez rendre obligatoires les entrées de votre méthode de recherche, utilisez le type param comme @pathaparam , si les entrées de votre méthode de ressource doivent être facultatives, conservez ce type de @QueryParamparamètre comme param

@Path("/car")
class CarResource
{
    @Get
    @produces("text/plain")
    @Path("/search/{carmodel}")
    public String getCarSearch(@PathParam("carmodel")String model,@QueryParam("carcolor")String color) {
        //logic for getting cars based on carmodel and color
            -----
        return cars
    }
}

Pour cette ressource passez la demande

req uri ://address:2020/carWeb/car/search/swift?carcolor=red

Si vous donnez une demande comme celle-ci, la ressource donnera le modèle et la couleur de la voiture

 req uri://address:2020/carWeb/car/search/swift

Si vous donnez une demande comme celle-ci, la méthode resoce n'affichera que la voiture basée sur un modèle rapide

req://address:2020/carWeb/car/search?carcolor=red

Si vous donnez comme ceci, nous obtiendrons l'exception ResourceNotFound parce que dans la classe de recherche de voitures, j'ai déclaré carmodel car @pathPramc'est que vous devez et devez donner le carmodel comme reQ uri sinon il ne passera pas la demande à resouce mais si vous ne passez pas la couleur il passera également la demande à la ressource pourquoi, car la couleur @quetyParamest facultative dans la demande.

DB5
la source
0
  1. @QueryParam peut être utilisé de manière pratique avec l'annotation Valeur par défaut afin que vous puissiez éviter une exception de pointeur nul si aucun paramètre de requête n'est transmis.

Lorsque vous souhaitez analyser des paramètres de requête à partir d'une demande GET, vous pouvez simplement définir le paramètre respectif pour la méthode qui gérera la demande GET et les annoter avec une @QueryParamannotation

  1. @PathParamextrait les valeurs URI et correspond à @Path. Et donc obtient le paramètre d'entrée. 2.1 @PathParampeut être plus d'un et est défini sur des arguments de méthodes

    @Path("/rest")
    public class Abc {
    
        @GET
        @Path("/msg/{p0}/{p1}")
        @Produces("text/plain")
        public String add(@PathParam("p0") Integer param1, @PathParam("p1")  Integer param2 )
        {
            return String.valueOf(param1+param2);
        }
    } 

Dans l'exemple ci-dessus
http://localhost:8080/Restr/rest/msg/{p0}/{p1},
p0correspond param1et p1correspond param2. Donc, pour l'URI
http://localhost:8080/Restr/rest/msg/4/6,
nous obtenons le résultat 10.

Dans le service REST, JAX-RS fournit @QueryParamet les @FormParamdeux pour accepter les données de la requête HTTP. Un formulaire HTTP peut être soumis par différentes méthodes comme GET et POST.

@QueryParam : Accepte la requête GET et lit les données de la chaîne de requête.

@FormParam: Accepte la demande POST et récupère les données du formulaire HTML ou de toute demande des médias

Amlesh Kumar
la source
0

En résumé,

@Pathparam fonctionne pour la valeur passant par les ressources et la chaîne de requête

  • /user/1
  • /user?id=1

@Queryparam fonctionne pour la valeur passant uniquement la chaîne de requête

  • /user?id=1
ArulRajP
la source