Bonjour ! Bienvenue dans cette nouvelle leçon.
Dans la leçon précédente, nous avons plongé au cœur du framework Spring en maîtrisant l'inversion de contrôle (IoC) et l'injection de dépendances (DI). Vous avez appris à structurer votre logique métier en services (@Service) et à les assembler de manière souple grâce à @Autowired, le tout sans jamais utiliser l'opérateur new dans votre code applicatif. Nous avons testé cet assemblage via un CommandLineRunner, confirmant que Spring gérait bien le cycle de vie et les dépendances de nos objets.
Aujourd'hui, nous allons faire le lien entre cette logique interne et le monde extérieur. L'objectif est de créer des contrôleurs pour exposer une API REST avec @RestController et @RequestMapping. Nous allons transformer notre application en un serveur web capable de recevoir des requêtes HTTP et d'y répondre, en utilisant les services que nous avons appris à construire.
1. Le Rôle du Contrôleur dans notre Architecture
Jusqu'à présent, notre application ressemble à un moteur bien huilé mais isolé dans son garage. Le contrôleur est la carrosserie et le tableau de bord qui permettent à un utilisateur d'interagir avec ce moteur.
Dans une architecture logicielle en couches, le contrôleur appartient à la couche de Présentation (ou Presentation Layer). Son unique rôle est de :
- Recevoir les requêtes HTTP entrantes.
- Valider et extraire les informations nécessaires de la requête (paramètres, corps de la requête).
- Déléguer le traitement métier à la couche de Service appropriée.
- Recevoir le résultat du service et le formater en une réponse HTTP (souvent en JSON), avec le code de statut adéquat (200 OK, 201 Created, 404 Not Found, etc.).

Pour approfondir ce concept d'architecture en couches, que vous connaissez probablement déjà via des frameworks comme Laravel, je vous invite à regarder cette courte introduction.
Apprendre Spring Boot #2 HTTP POST & DTO : Controller → Service → JPA (RequestBody)
Cette vidéo de la chaîne JirAWS introduit de manière très claire les différentes couches d'une application backend (Présentation, Service, Données) et le rôle de chacune.
Regardez la section de 02:38 à 07:37. L'auteur explique le rôle de la couche de présentation (@RestController) comme étant la 'porte d'entrée' de l'application. Concentrez-vous sur la manière dont les trois couches collaborent : la présentation reçoit la requête, la transmet au service qui contient la logique métier, et le service s'appuie sur la couche de données pour interagir avec la base de données.
Un point crucial à retenir : le contrôleur ne doit contenir aucune logique métier. Il est un chef d'orchestre, pas un musicien.
2. Anatomie d'un Contrôleur REST avec Spring
Pour créer un contrôleur REST, Spring nous fournit des annotations très expressives qui simplifient grandement le travail.
-
@RestController: C'est l'annotation principale. Elle indique à Spring que cette classe est un contrôleur et que les valeurs retournées par ses méthodes doivent être directement écrites dans le corps de la réponse HTTP. Par défaut, Spring convertira les objets Java en JSON, ce qui est exactement ce que nous voulons pour une API REST. -
@RequestMapping("/api/..."): Placée au niveau de la classe, cette annotation définit un préfixe d'URL pour toutes les méthodes du contrôleur. C'est une excellente pratique pour organiser vos endpoints. Par exemple, tous les endpoints liés aux utilisateurs pourraient être sous/api/users. -
@GetMapping,@PostMapping,@PutMapping,@DeleteMapping: Ces annotations sont des spécialisations de@RequestMappingpour les verbes HTTP correspondants. Elles rendent le code plus lisible et moins verbeux.
Voici un exemple minimaliste de ce à quoi ressemble un contrôleur.
Mise en place d'une API Rest avec Spring
Ce document de l'Université d'Aix-Marseille montre un exemple très concis et clair d'un premier contrôleur REST. C'est une excellente référence pour voir les annotations de base en action.
Concentrez-vous sur le bloc de code de la section 5, "Un premier service WEB". Observez comment @RestController et @RequestMapping("/api") sont combinés. Notez l'utilisation de @GetMapping pour définir des routes et de @PathVariable pour extraire des parties de l'URL.
3. Implémentation des Endpoints (Points de terminaison)
Maintenant, mettons en pratique la création d'endpoints pour les opérations CRUD (Create, Read, Update, Delete). La vidéo suivante est un excellent tutoriel qui couvre la création d'une application CRUD complète. Nous allons nous en servir de guide, en nous concentrant sur la couche contrôleur.
Application CRUD en 30 minutes | Tutoriel Étape par Étape | Spring Boot | MySQL
Cette vidéo de la chaîne 'Coding With Armand' est un guide pratique parfait pour notre leçon. Elle montre, étape par étape, la création d'un contrôleur REST pour gérer une entité 'Personne'.
Cette vidéo sera notre fil rouge. Vous n'avez pas besoin de tout regarder d'un coup. Nous allons y faire référence section par section au fur et à mesure que nous avançons.
Étape 1 : Créer la structure du contrôleur et injecter le service
Comme nous l'avons appris, le contrôleur délègue à un service. Dans la leçon précédente, nous avons créé un UserService. Créons maintenant un UserController qui l'utilisera.
// src/main/java/com/.../web/UserController.java
package com.votreentreprise.premierprojetspring.web;
import com.votreentreprise.premierprojetspring.services.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/users") // Tous les endpoints de ce contrôleur commenceront par /api/users
public class UserController {
private final UserService userService;
// Injection du service par le constructeur (bonne pratique)
public UserController(UserService userService) {
this.userService = userService;
}
// Nos méthodes d'endpoints viendront ici...
}
Notez que la vidéo Coding With Armand injecte directement le Repository dans le Controller pour simplifier (voir à 19:10). Dans une application professionnelle, on injecte toujours un service, comme nous le faisons ici.
Étape 2 : Lire des données (GET)
Pour lire des données, on utilise le verbe HTTP GET.
-
Récupérer toutes les ressources : On utilise
@GetMappingsans chemin supplémentaire.// Dans UserController.java @GetMapping public ResponseEntity<List<User>> getAllUsers() { // Pour l'instant, nous n'avons pas de base de données, // alors nous allons simuler en demandant au service de nous renvoyer une liste. // Imaginons que userService a une méthode getUsers(). List<User> users = userService.getUsers(); return ResponseEntity.ok(users); }La vidéo
Coding With Armandmontre un exemple concret à 20:52 (@GetMappingpourfindAll). -
Récupérer une ressource par son ID : On utilise un chemin variable avec
@PathVariable.// Dans UserController.java @GetMapping("/{userId}") public ResponseEntity<User> getUserById(@PathVariable Long userId) { // Le service devrait avoir une méthode pour trouver un utilisateur par son ID. User user = userService.findUserById(userId); if (user != null) { return ResponseEntity.ok(user); } else { return ResponseEntity.notFound().build(); } }La vidéo
Coding With Armandillustre parfaitement l'utilisation de@PathVariableà 28:15.
Étape 3 : Créer une ressource (POST)
C'est ici que votre expérience full-stack est précieuse. Pour créer une ressource, le client (votre frontend React, par exemple) envoie une requête POST avec les données du nouvel objet en format JSON dans le corps de la requête.
Comment Spring récupère-t-il ce JSON ? Avec l'annotation @RequestBody.
Avant d'écrire le code, il est crucial de bien comprendre la différence entre passer des données dans l'URL (paramètres de requête) et dans le corps de la requête.
Apprendre Spring Boot #2 HTTP POST & DTO : Controller → Service → JPA (RequestBody)
Cette section de la vidéo de JirAWS est l'une des meilleures explications sur la différence conceptuelle et pratique entre GET et POST, et surtout sur l'introduction du @RequestBody.
Regardez la section de 01:00:34 à 01:26:25. Concentrez-vous sur les points suivants : Pourquoi on utilise POST pour la création (convention). L'introduction du Request Body par opposition aux Request Params. L'explication de ce qu'est un DTO (Data Transfer Object) pour représenter les données entrantes. L'utilisation de @RequestBody pour mapper le JSON entrant à un objet Java.
Fort de cette compréhension, voici comment l'implémenter :
// D'abord, on définit un 'DTO' pour représenter les données de création.
// C'est une simple classe Java (POJO).
public class CreateUserDto {
private String username;
private String email;
// Getters et Setters...
}
// Puis, dans UserController.java
@PostMapping
public ResponseEntity<User> createUser(@RequestBody CreateUserDto createUserDto) {
User newUser = userService.createUser(createUserDto);
// Le code 201 Created est la réponse standard pour une création réussie.
return new ResponseEntity<>(newUser, HttpStatus.CREATED);
}
Spring, en coulisses, utilise une bibliothèque comme Jackson pour lire le JSON de la requête et instancier automatiquement votre objet CreateUserDto. C'est extrêmement puissant.
La vidéo Coding With Armand montre un exemple pratique de @PostMapping avec @RequestBody à 25:10.
4. Exercice Pratique
Pour consolider ces connaissances, je vous propose de recréer une partie du projet de la vidéo Coding With Armand, mais en respectant l'architecture en couches que nous avons établie.
-
Créez les couches de base :
- Créez une classe d'entité
Personcomme montré à 11:13. - Créez une interface
PersonRepositoryqui étendJpaRepositorycomme montré à 15:01. (Nous verronsJpaRepositoryen détail plus tard, pour l'instant, suivez l'exemple).
- Créez une classe d'entité
-
Ajoutez la couche Service (notre amélioration) :
- Créez une classe
PersonService. - Injectez
PersonRepositorydansPersonService. - Créez des méthodes dans
PersonServicequi appellent le repository. Par exemple :public List<Person> getAllPersons() { return personRepository.findAll(); } public Person createPerson(Person person) { return personRepository.save(person); }
- Créez une classe
-
Créez le
PersonController:- Créez la classe
PersonControllerannotée avec@RestControlleret@RequestMapping("/api/persons"). - Injectez votre
PersonService(et non lePersonRepositorydirectement).
- Créez la classe
-
Implémentez les Endpoints :
- Créez une méthode
getAllPersons()annotée avec@GetMappingqui appellepersonService.getAllPersons(). Inspirez-vous de la vidéo à 20:52. - Créez une méthode
createPerson()annotée avec@PostMappingqui prend un@RequestBody Person. Elle appellerapersonService.createPerson(). Inspirez-vous de la vidéo à 25:10.
- Créez une méthode
-
Testez avec Postman :
- Lancez votre application.
- Utilisez Postman pour envoyer une requête
POSTàhttp://localhost:8080/api/personsavec un corps JSON comme{"name": "John Doe", "city": "Paris", "phoneNumber": "12345"}. N'oubliez pas de mettre leContent-Typeàapplication/json. - Envoyez une requête
GETàhttp://localhost:8080/api/personspour vérifier que votre personne a bien été créée.
Cet exercice vous permettra de mettre en pratique la création de contrôleurs tout en renforçant les bonnes pratiques d'architecture vues dans la leçon précédente.
Conclusion
Félicitations ! Vous avez franchi une étape décisive en exposant la logique de votre application au monde extérieur. Vous savez maintenant comment créer des points d'entrée pour une API REST.
Points clés à retenir :
- Le
@RestControllerest le stéréotype pour les contrôleurs d'API dans Spring. - Le
@RequestMappingpermet de mapper des URL à des contrôleurs et à des méthodes. @GetMapping,@PostMapping, etc., sont des raccourcis spécifiques aux verbes HTTP.- Le
@PathVariablesert à extraire des valeurs de l'URL (ex:/users/123). - Le
@RequestBodyest essentiel pour désérialiser le corps JSON d'une requête (typiquementPOSTouPUT) en un objet Java. - Un contrôleur doit rester "maigre" et déléguer toute la logique métier à la couche de service.
Dans la prochaine leçon, nous allons nous intéresser à un aspect plus opérationnel mais tout aussi crucial : gérer la configuration de l'application pour différents environnements (développement, production) avec application.properties et les profils Spring.