Contactez-nous

Gestion des paramètres de requête (`@RequestParam`, `@PathVariable`, `@RequestHeader`)

Maîtrisez l'extraction des paramètres de requête, des variables de chemin et des en-têtes HTTP dans Spring Boot en utilisant @RequestParam, @PathVariable et @RequestHeader.

Rendre vos endpoints dynamiques : extraire les données entrantes

Pour qu'une API REST soit réellement utile, elle doit pouvoir réagir aux informations spécifiques envoyées par le client. Un endpoint statique qui retourne toujours la même chose a une utilité limitée. Il est essentiel de pouvoir extraire des données de la requête HTTP entrante pour personnaliser la réponse, filtrer des résultats, identifier des ressources spécifiques ou vérifier des autorisations. Spring Web MVC fournit un ensemble d'annotations puissantes et pratiques pour lier les données de la requête aux paramètres de vos méthodes de contrôleur.

Dans ce chapitre, nous allons nous concentrer sur trois des annotations les plus couramment utilisées pour extraire des informations de différentes parties de la requête HTTP :

  • @RequestParam : Pour extraire les paramètres de la chaîne de requête (query parameters, après le `?` dans l'URL) ou les données d'un formulaire (application/x-www-form-urlencoded).
  • @PathVariable : Pour extraire des valeurs directement depuis le chemin (path) de l'URL, souvent utilisées pour identifier une ressource spécifique.
  • @RequestHeader : Pour lire les valeurs des en-têtes HTTP de la requête (comme Authorization, Accept, User-Agent, ou des en-têtes personnalisés).

Maîtriser ces annotations vous permettra de construire des endpoints flexibles et capables de s'adapter aux besoins du client.

@RequestParam : Lier les paramètres de requête et de formulaire

L'annotation @RequestParam est utilisée pour lier la valeur d'un paramètre de requête HTTP (query parameter) ou d'un champ de formulaire soumis à un paramètre de méthode dans votre contrôleur. C'est l'outil idéal pour gérer les filtres, la pagination, ou toute autre information optionnelle ou obligatoire passée après le `?` dans une URL (ex: /search?query=springboot&page=1).

Utilisation basique : Si le nom du paramètre dans la méthode correspond exactement au nom du paramètre de requête, l'annotation est simple :

@GetMapping("/search")
public String searchByQuery(@RequestParam String query) {
    // La variable 'query' contiendra la valeur du paramètre 'query' de l'URL
    return "Résultats de recherche pour: " + query;
}
// Appel exemple: GET /search?query=java

Attributs utiles :

  • name ou value : Pour spécifier le nom exact du paramètre de requête si celui-ci diffère du nom du paramètre de la méthode.
  • required : Un booléen (true par défaut) indiquant si le paramètre est obligatoire. Si required=true et que le paramètre est absent, Spring lèvera une exception (résultant en une erreur 400 Bad Request). Si required=false, la valeur sera null si le paramètre est absent (attention aux types primitifs, préférez les types wrapper comme Integer, Boolean).
  • defaultValue : Une chaîne de caractères fournissant une valeur par défaut si le paramètre est absent de la requête. Cela implique required=false. Spring tentera de convertir cette chaîne vers le type du paramètre.

Exemple plus complet :

@GetMapping("/items")
public String findItems(
        @RequestParam(name = "category", required = false) String itemCategory,
        @RequestParam(defaultValue = "1") int page, // page est optionnel, défaut à 1
        @RequestParam(defaultValue = "10") int size,
        @RequestParam(required = false) List tags) { // Gérer plusieurs valeurs pour 'tags'

    String response = String.format("Recherche d'items: Categorie='%s', Page=%d, Taille=%d",
                                   itemCategory != null ? itemCategory : "N/A", page, size);
    if (tags != null && !tags.isEmpty()) {
        response += ", Tags=" + String.join(", ", tags);
    }
    return response;
}
// Appel exemple 1: GET /items?category=books&page=2
// Appel exemple 2: GET /items?tags=promo&tags=new

Lier tous les paramètres : Vous pouvez également lier tous les paramètres de requête à une Map ou MultiValueMap :

@GetMapping("/allparams")
public Map getAllParams(@RequestParam Map allParams) {
    return allParams;
}
// Appel exemple: GET /allparams?a=1&b=hello

@PathVariable : Extraire des valeurs du chemin de l'URL

L'annotation @PathVariable est utilisée pour extraire des valeurs directement depuis le chemin (path) de l'URI, en utilisant des modèles d'URI avec des placeholders. C'est la méthode standard pour identifier une ressource spécifique dans un style RESTful (ex: /users/{userId}, /orders/{orderId}/items/{itemId}).

Utilisation basique : Définissez un placeholder dans l'annotation de mapping (ex: @GetMapping) en utilisant des accolades {}, puis utilisez @PathVariable sur le paramètre de méthode correspondant.

@GetMapping("/users/{userId}")
public String getUserDetails(@PathVariable String userId) {
    // La variable 'userId' contiendra la valeur extraite de l'URL
    return "Détails pour l'utilisateur ID: " + userId;
}
// Appel exemple: GET /users/abc-123

Attributs et comportement :

  • name ou value : Pour spécifier le nom du placeholder dans l'URI si celui-ci diffère du nom du paramètre de la méthode.
  • Obligatoire par défaut : Contrairement à @RequestParam, une variable de chemin est intrinsèquement requise. Si l'URL appelée ne correspond pas au modèle (placeholder manquant), la requête ne sera pas routée vers cette méthode (erreur 404 Not Found). Il n'y a pas d'attribut `required` ou `defaultValue`.
  • Conversion de type : Spring tente automatiquement de convertir la valeur extraite (qui est une chaîne) vers le type du paramètre de la méthode (ex: Long, int). Une erreur surviendra si la conversion échoue (ex: passer "abc" pour un Long).

Exemple avec type et nom différent :

@GetMapping("/orders/{orderId}/items/{itemId}")
public String getOrderItemDetails(
        @PathVariable("orderId") Long oId, // Lie {orderId} au paramètre Long oId
        @PathVariable Long itemId) {        // Lie {itemId} au paramètre Long itemId (noms identiques)
    return String.format("Détails de l'article %d de la commande %d", itemId, oId);
}
// Appel exemple: GET /orders/12345/items/987

Variables de chemin optionnelles et expressions régulières : Il est possible de gérer des variables de chemin optionnelles (bien que moins courant que les `RequestParam` optionnels) et d'utiliser des expressions régulières pour contraindre les valeurs acceptées dans les placeholders, mais cela sort du cadre de l'utilisation basique.

@RequestHeader : Accéder aux en-têtes HTTP

L'annotation @RequestHeader permet d'accéder aux valeurs des en-têtes (headers) de la requête HTTP. Les en-têtes transportent des métadonnées importantes sur la requête, comme le type de contenu acceptable par le client (Accept), le type de contenu du corps de la requête (Content-Type), les informations d'authentification (Authorization), la langue préférée (Accept-Language), ou des informations sur le client (User-Agent).

Utilisation basique : Spécifiez le nom de l'en-tête à extraire. Les noms d'en-tête sont insensibles à la casse.

@GetMapping("/show-user-agent")
public String showUserAgent(@RequestHeader("User-Agent") String userAgent) {
    return "Votre User-Agent est: " + userAgent;
}
// Le client doit envoyer l'en-tête User-Agent (ce que font les navigateurs et curl)

Attributs utiles (similaires à @RequestParam) :

  • name ou value : Nom de l'en-tête (insensible à la casse).
  • required : Booléen (true par défaut). Si true et l'en-tête est absent, une erreur 400 est générée. Si false, la valeur sera null.
  • defaultValue : Valeur par défaut si l'en-tête est absent (implique required=false).

Exemple avec optionnel et défaut :

@GetMapping("/check-custom-header")
public String checkCustomHeader(
        @RequestHeader(name = "X-Custom-Info", required = false) String customInfo,
        @RequestHeader(name = "Accept-Language", defaultValue = "en-US") String acceptLanguage) {

    return String.format("Custom Info: '%s', Langue acceptée: '%s'",
                                   customInfo != null ? customInfo : "Non fourni", acceptLanguage);
}
// Appel exemple: GET /check-custom-header (avec ou sans l'en-tête X-Custom-Info)

Lier tous les en-têtes : Vous pouvez capturer tous les en-têtes dans une Map, MultiValueMap ou un objet HttpHeaders.

import org.springframework.http.HttpHeaders;
// ...
@GetMapping("/allheaders")
public Map displayAllHeaders(@RequestHeader HttpHeaders headers) {
    // HttpHeaders offre des méthodes pratiques pour accéder aux en-têtes
    System.out.println("Content-Type: " + headers.getContentType());
    System.out.println("Accept: " + headers.getAccept());
    // Retourne une Map pour l'affichage
    return headers.toSingleValueMap();
}

Ces trois annotations, @RequestParam, @PathVariable, et @RequestHeader, constituent la base pour extraire les informations nécessaires des requêtes HTTP entrantes, rendant vos contrôleurs Spring Boot interactifs et capables de s'adapter au contexte fourni par le client.