Contenu du cours
Backend Spring Boot
Backend Spring Boot
Principes de Base de REST
Les principes fondamentaux de REST forment la base pour créer des services web efficaces et facilement évolutifs. Dans Spring Boot, ils sont fréquemment utilisés pour implémenter des APIs.
Explorons quels sont ces principes, pourquoi ils sont importants, et examinons des exemples de leur application dans Spring Boot.
Principes Fondamentaux de REST
REST (Representational State Transfer) est un style architectural basé sur six principes clés qui aident les développeurs à construire des APIs simples, flexibles et évolutives. Ces principes décrivent comment les systèmes doivent interagir pour rester adaptables et maintenables.
Architecture Client-Serveur
Une API REST doit séparer les responsabilités entre le client et le serveur. Le client est responsable de l'interface utilisateur et de faire des requêtes, tandis que le serveur gère le stockage des données et le traitement des requêtes.
L'API REST assure une séparation claire entre le côté client et le côté serveur de l'application, leur permettant d'évoluer indépendamment.
Le côté client pourrait être un navigateur web, une application mobile, ou toute autre application cliente, tandis que le côté serveur peut être implémenté dans n'importe quel langage de programmation.
Sans État
Chaque requête du client au serveur doit inclure toutes les informations nécessaires pour traiter cette requête. Le serveur ne doit pas conserver d'état entre les requêtes, garantissant que chaque requête est isolée des autres.
Par exemple, imaginons que nous ayons une application qui retourne une liste de produits en différentes langues. Le client doit inclure l'information de langue dans chaque requête afin que le serveur sache quelle langue utiliser pour la réponse. Le serveur ne stocke pas l'information de langue entre les requêtes. Implémentons cet exemple en code.
Main
@RestController @RequestMapping("/products") public class ProductController { @GetMapping public List<Product> getProducts(@RequestParam("lang") String language) { // Check the language requested by the client if ("en".equals(language)) { return productService.getProductsInEnglish(); } else if ("es".equals(language)) { return productService.getProductsInSpanish(); } else { return productService.getProductsInDefaultLanguage(); } } }
Ce code représente un contrôleur REST qui gère les requêtes HTTP GET
au point de terminaison /products
. La méthode getProducts()
prend un paramètre lang
, indiquant la langue dans laquelle le client souhaite recevoir les données.
En fonction de ce paramètre, la méthode retourne une liste de produits dans la langue spécifiée ou dans la langue par défaut.
Interface Uniforme
Pour rendre une API REST facile à utiliser, elle doit avoir une structure simple et organisée. Cela signifie que tous les points de terminaison doivent suivre quelques lignes directrices de base. Voici les principes clés :
Utilisez des noms pour représenter les ressources au lieu de verbes. Par exemple, au lieu d'utiliser GET /createProduct
, il est préférable d'utiliser POST /products
, où products est la ressource.
GET /products
— Récupère une liste de produits ;
POST /products
— Crée un nouveau produit ;
PUT /products/{id}
— Met à jour les informations sur un produit spécifique, où {id}
est l'identifiant unique du produit ;
DELETE /products/{id}
— Supprime le produit avec l'identifiant spécifié.
Décrivons un contrôleur REST Spring qui gère les produits en implémentant diverses méthodes HTTP pour créer, récupérer, mettre à jour et supprimer les données des produits, tout en suivant les meilleures pratiques pour une structure API conviviale.
Main
@RestController @RequestMapping("/products") public class ProductController { // Example of applying the client-server architecture principle private final ProductService productService; // Constructor injection ensures productService is provided by Spring public ProductController(ProductService productService) { this.productService = productService; } // Uniform interface principle: GET request to retrieve all products @GetMapping public List<Product> getAllProducts() { // Calls the service to return a list of all products return productService.getAllProducts(); } // Uniform interface principle: POST request to create a new product @PostMapping public Product createProduct(@RequestBody Product product) { // Calls the service to create a new product based on the provided request body return productService.createProduct(product); } // Uniform interface principle: GET request to retrieve a product by its ID @GetMapping("/{id}") public Product getProductById(@PathVariable Long id) { // Calls the service to find and return the product with the given ID return productService.getProductById(id); } // Uniform interface principle: PUT request to update a product by its ID @PutMapping("/{id}") public Product updateProduct(@PathVariable Long id, @RequestBody Product product) { // Calls the service to update the product details based on the provided request body and ID return productService.updateProduct(id, product); } // Uniform interface principle: DELETE request to remove a product by its ID @DeleteMapping("/{id}") public void deleteProduct(@PathVariable Long id) { // Calls the service to delete the product with the specified ID productService.deleteProduct(id); } }
L'annotation @RequestMapping("/products")
spécifie que l'URL de base /products
sera automatiquement préfixée à toutes les routes au sein de ce contrôleur.
Dans cet exemple, le contrôleur gère les opérations liées à l'entité Product
(classe Product), donc l'URL de base est /products
. Cette approche évite de répéter /products
pour chaque méthode. Au lieu de cela, nous spécifions simplement les méthodes HTTP (GET, POST, PUT, DELETE), qui seront appliquées à cette URL de base.
GET /products
— Récupère une liste de produits;
POST /products
— Crée un nouveau produit.
Nous pouvons avoir plusieurs points de terminaison avec la même URL mais des méthodes HTTP différentes. Par exemple, GET /products
et POST /products
partagent la même URL, mais ils utilisent des méthodes HTTP différentes. Le client spécifiera la méthode HTTP dans l'en-tête de la requête, indiquant quelle action effectuer.
Mise en cache
Pour améliorer les performances, le serveur peut indiquer au client quand mettre en cache les données. Cela réduit la charge du serveur et accélère le traitement des requêtes.
Cela signifie que lorsque la méthode est appelée avec les mêmes paramètres, le résultat sera récupéré du cache plutôt que de réexécuter la méthode. Cela peut améliorer les performances en réduisant la charge sur le service.
Dans Spring Boot, la mise en cache des réponses peut être gérée à l'aide d'annotations ou d'en-têtes HTTP. Voici un exemple de mise en cache des données :
Main
@Cacheable("products") @GetMapping public List<Product> getAllProducts() { return productService.getAllProducts(); }
Dans cet exemple, l'annotation @Cacheable
est utilisée pour mettre en cache le résultat de la méthode getAllProducts()
.
L'annotation @Cacheable("products")
indique que le résultat de la méthode getAllProducts()
sera stocké dans le cache sous le nom products
. Lorsque la méthode est appelée à nouveau avec les mêmes paramètres, Spring cherchera le résultat dans le cache products
plutôt que d'exécuter la méthode à nouveau.
Système en couches
Le principe du système en couches dans une API REST signifie que le client n'interagit pas avec un seul serveur; au lieu de cela, il fonctionne à travers plusieurs niveaux. Expliquons cela en utilisant l'architecture à trois niveaux dans Spring Boot.
Lorsque le client envoie une requête, elle passe par les trois niveaux : du contrôleur au service, puis au référentiel, et retour. Cette séparation aide à garder le système organisé et rend le code plus facile à maintenir.
Code à la demande
Bien que moins couramment utilisé, une API REST peut renvoyer du code exécutable au client pour exécution de leur côté. Ce principe est rarement appliqué et nécessite des mesures de sécurité supplémentaires.
Par exemple, une API pourrait retourner du code JavaScript qui s'exécute dans le navigateur du client pour traiter des données ou effectuer d'autres tâches. Cela peut être utile pour charger dynamiquement des fonctionnalités basées sur des requêtes, telles que la gestion de formulaires ou la validation des données côté client.
Résumé
Les principes fondamentaux de REST sont des lignes directrices essentielles pour créer des API flexibles et maintenables. Dans Spring Boot, ces principes sont implémentés à l'aide d'annotations telles que @RestController
, @Cacheable
qui facilitent le développement de systèmes bien structurés et efficaces pour interagir avec les clients.
1. Quel principe REST
permet au client d'interagir avec une ressource en utilisant des méthodes HTTP
standard ?
2. Que signifie le principe d'absence d'état dans REST
?
Merci pour vos commentaires !