Spring dans un contexte web
Introduction
Spring MVC (Model-View-Controller) est un framework puissant pour le développement d’applications web, offrant flexibilité pour créer des IHM via des technologies telles que JSP, JSF, Thymeleaf, et facilitant l’exposition d’API SOAP et REST. Ce chapitre détaille l’utilisation de Spring MVC, abordant les tendances actuelles comme le déclin des JSP au profit des SPA et la préférence pour WebClient sur RestTemplate pour les nouveaux projets.
Serveurs de pages
Nous traiterons dans ce chapitre des serveurs de pages, principalement à travers l’utilisation du moteur de template Thymeleaf.
Configuration par annotation
Les serveurs web demandent généralement un fichier web.xml. Il est utilisé dans les applications déployées sur des serveurs de servlet, tels qu’Apache Tomcat, pour configurer divers aspects du comportement de l’application web.
La version avec annotation permet de ne pas avoir de fichier web.xml.
Pour la partie back :
@Configuration
@ComponentScan({ "fr.eni.mvc.annot.service" })
public class SpringArriereConfig {
Pour la partie web, dans le cas particulier de JSP :
@EnableWebMvc
@Configuration
@ComponentScan({ "fr.eni.mvc.annot.web" })
public class SpringWebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry
registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/"); ...
Contrôleur
Une classe contrôleur dans le modèle MVC (modèle-vue-contrôleur) est marquée avec l’annotation @Controller. Son rôle principal est de gérer les requêtes HTTP entrantes et de renvoyer une réponse appropriée.
1. Fonctionnement du contrôleur
Le contrôleur gère les requêtes, interprète des données de requête, traite de la logique métier, prépare la réponse et enfin renvoie la réponse au client.
Le @Controller sert de point d’entrée pour les requêtes HTTP dans une application Spring MVC, orchestrant la logique de traitement de ces requêtes et la préparation des réponses appropriées. Il joue un rôle central dans la gestion du flux de contrôle dans une application Spring MVC.
Nous utilisons encore parfois Thymeleaf pour de petits projets ou pour fabriquer des outils. Pour les applications plus exigeantes, nous utilisons Spring MVC pour faire un backend basé sur les API REST que nous verrons un peu plus loin dans ce chapitre.
2. Gestion des requêtes HTTP
Un @Controller est chargé de traiter les requêtes HTTP envoyées par le client (navigateur, application, etc.). Chaque méthode du contrôleur peut être associée à une URL spécifique et à un type de requête HTTP (GET, POST, etc.) à l’aide d’annotations telles que @GetMapping ou @PostMapping.
Dans une application Spring MVC qui utilise Thymeleaf pour la génération de pages HTML et un @Controller pour la gestion des requêtes, plusieurs annotations de mapping courantes sont utilisées pour définir les routes et manipuler les requêtes HTTP. Ces annotations sont similaires à celles utilisées dans les applications REST, mais elles sont généralement orientées vers le renvoi de vues plutôt que de données JSON. Voici les mappings les plus courants dans ce contexte.
a. @RequestMapping
C’est l’annotation de mapping la plus générique dans Spring MVC. Elle peut gérer tout type de requête HTTP. En contexte Thymeleaf, elle est typiquement utilisée pour renvoyer le nom d’une vue Thymeleaf.
Exemple :
@RequestMapping(value = "/home"...
Gestion des exceptions et des erreurs
Dans Spring MVC, la gestion des erreurs et des exceptions sont deux aspects liés, mais distincts du traitement des situations anormales ou inattendues qui peuvent survenir lors de l’exécution d’une application. Comprendre la différence entre ces deux concepts est crucial pour une bonne conception d’une application Spring MVC.
La gestion des exceptions dans Spring MVC est axée sur la capture et le traitement des exceptions Java spécifiques, tandis que la gestion des erreurs est centrée sur le traitement des erreurs au niveau HTTP.
Les deux mécanismes permettent de répondre de manière appropriée et cohérente aux situations d’erreur, améliorant ainsi la robustesse et la fiabilité de l’application.
1. Gestion des exceptions
La gestion des exceptions concerne le traitement des exceptions Java qui sont levées au cours du traitement d’une requête. Cela comprend les exceptions de la logique métier, les exceptions de la couche de persistance, les violations de contraintes, etc.
a. @ExceptionHandler et @ControllerAdvice
Pour gérer ces exceptions, Spring MVC utilise des annotations telles que @ExceptionHandler et @ControllerAdvice. @ExceptionHandler permet de gérer des exceptions spécifiques au sein d’un contrôleur, tandis que @ControllerAdvice permet de gérer...
@RestController
Le @RestController dans Spring MVC est une spécialisation du @Controller, apportant des fonctionnalités supplémentaires qui facilitent grandement le développement d’API REST. La principale différence entre @RestController et @Controller réside dans leur traitement des réponses des méthodes de contrôleur. Alors que @Controller est typiquement utilisé pour renvoyer des vues ou des pages HTML en utilisant des moteurs de rendu, @RestController est conçu pour créer des contrôleurs qui retournent directement des données, généralement au format JSON ou XML. Cela en fait une solution plus pratique et épurée, idéale pour le développement d’API REST dans nos applications Spring MVC, où l’accent est mis sur le renvoi de données plutôt que de vues.
1. Annotation @ResponseBody par défaut
Dans une classe annotée avec @RestController, toutes les méthodes de contrôleur ont implicitement l’annotation @ResponseBody. Cela signifie que le résultat de chaque méthode est écrit directement dans le corps de la réponse, généralement au format JSON ou XML, sans nécessiter de vue ou de moteur de template.
2. Pas de vues ou de rendu de page
Contrairement à @Controller, qui est souvent utilisé avec des moteurs de rendu...
Classes UriComponentsBuilder
La classe UriComponentsBuilder est une classe utile de Spring Framework utilisée pour construire et manipuler des URI de manière programmatique. Elle est particulièrement pratique pour créer des URI complexes de manière dynamique, par exemple lors de la construction de liens d’API REST.
UriComponentsBuilder permet de construire un URI en ajoutant différents composants tels que le schéma, l’hôte, le port, le chemin, les paramètres de requête, etc. Il gère également l’encodage correct des composants de l’URI et permet de manipuler facilement les URI existants.
Imaginons que nous développions une API REST où nous devons créer un lien vers une ressource spécifique après sa création. Par exemple, après avoir créé un nouvel utilisateur, nous souhaitons renvoyer un en-tête Location avec l’URI de cette nouvelle ressource utilisateur.
Voici comment nous pourrions faire :
@RestController
public class UserController {
@PostMapping("/users")
public ResponseEntity<Object> createUser(@RequestBody
User user, UriComponentsBuilder uriBuilder) {
User createdUser = userService.createUser(user);
//...
Client REST
Dans Spring MVC, nous disposons de plusieurs clients REST adaptés pour consommer des services web RESTful, permettant d’envoyer des requêtes HTTP et de recevoir des réponses depuis des applications externes. Chaque client REST présente des avantages et des cas d’utilisation spécifiques. RestTemplate est une option simple et directe, bien adaptée pour les besoins standards. Cependant, pour les applications nécessitant des fonctionnalités asynchrones ou réactives, WebClient est souvent le meilleur choix, offrant plus de flexibilité et une meilleure gestion des flux de données. Pour les applications orientées cloud, Feign se révèle particulièrement utile, en facilitant la création de clients d’API web de manière déclarative. Par ailleurs, Apache HttpClient est idéal pour les situations nécessitant un contrôle très fin sur les requêtes HTTP, comme dans des cas d’utilisation plus complexes ou personnalisés.
1. RestTemplate
Le RestTemplate est le client REST traditionnel de Spring et a longtemps été la solution standard pour effectuer des appels REST dans les applications Spring. Il fournit des méthodes pour envoyer des requêtes et recevoir des réponses, avec un support pour la conversion automatique des données (par exemple, conversion d’objets en JSON/XML et vice-versa). Le RestTemplate peut être personnalisé avec des convertisseurs de messages et des intercepteurs de requêtes pour manipuler les requêtes et réponses. Bien que toujours utilisé, RestTemplate ne prend pas en charge les appels asynchrones ou réactifs de manière native et est maintenant en mode de maintenance, sans développement actif de nouvelles fonctionnalités.
Exemple d’utilisation :
import org.springframework.web.client.RestTemplate; ...
Spring Security
Spring Security est un framework de sécurité puissant et hautement personnalisable qui facilite l’ajout de fonctionnalités de sécurité robustes aux applications Java et Spring. Il offre des mécanismes pour gérer l’authentification, l’autorisation, la protection contre les attaques courantes, et bien plus encore. Voici les principaux aspects de Spring Security.
1. Authentification
Spring Security gère l’authentification des utilisateurs. Il permet de vérifier si un utilisateur est qui il prétend être. Cela peut être réalisé en utilisant divers mécanismes d’authentification tels que l’authentification basée sur un formulaire, l’authentification via des certificats X.509, l’authentification via des jetons (comme JWT), l’authentification par LDAP, etc.
a. Authentification basée sur un formulaire
C’est l’un des mécanismes d’authentification les plus couramment utilisés dans les applications web. Les utilisateurs saisissent leurs identifiants (nom d’utilisateur et mot de passe) dans un formulaire HTML, qui est ensuite soumis au serveur. Spring Security vérifie les informations d’authentification et authentifie l’utilisateur.
Par exemple :
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.logout((logout) -> logout.permitAll());
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder() ...
Spring et HATEOAS
Spring HATEOAS est une extension de Spring qui simplifie la création d’API REST conformes à l’approche HATEOAS, un principe de conception des services web RESTful favorisant l’utilisation de liens hypertextes pour une navigation et une interaction dynamiques avec les ressources. En s’intégrant avec Spring MVC, Spring HATEOAS facilite l’incorporation automatique de liens hypertextes dans les réponses d’API, permettant ainsi une découverte intuitive des fonctionnalités disponibles sans que les clients aient besoin de connaître les URL ou points de terminaison à l’avance.
Cette intégration rend le développement d’API RESTful respectant HATEOAS plus simple et moins sujet à erreurs, grâce à l’usage des annotations et classes de Spring HATEOAS pour générer ces liens dynamiquement, améliorant ainsi l’expérience de développement au sein des applications Spring.
1. Simplification de la création de liens hypertexte
Spring HATEOAS fournit des classes et des méthodes qui facilitent la création de liens hypertextes pour les ressources.
Ces classes et méthodes permettent de créer des liens hypertextes de manière intuitive pour les ressources, les actions et les états dans une application Spring HATEOAS. Elles simplifient la génération...
Utilisation de MapStruct
Dans les architectures logicielles multicouches, le recours au modèle DTO (Data Transfer Object) facilite le transfert de données entre différentes couches, mais soulève le défi de l’écriture manuelle de code de mappage, souvent volumineuse et répétitive. MapStruct, une bibliothèque Java, adresse ce problème en automatisant le mappage des données grâce à la génération de code basée sur des interfaces annotées, simplifiant ainsi le processus. Cette bibliothèque s’intègre harmonieusement avec le CDI de Spring et Lombok, permettant la création de mappers sous forme de beans Spring, ce qui optimise la conversion entre entités JPA et DTO correspondantes. Pour les développeurs cherchant à minimiser le code de mappage manuel tout en maintenant une architecture propre, MapStruct représente une solution efficace, avec une documentation complète disponible pour faciliter son intégration et son utilisation dans des projets Spring.
Pour créer une interface MapStruct qui automatise la conversion entre une entité JPA et un DTO correspondant, vous pouvez suivre cet exemple :
Définissez votre entité JPA :
public class User {
private Long id;
private...
Approche API-First
La conception des backends pour les Web Services SOAP ou REST a évolué. Initialement, l’API était créée après le développement du service backend. Cette approche pouvait conduire à des API non optimales. Récemment, une méthode "API-First" a été adoptée, où l’API est définie avant le développement du service, favorisant ainsi une meilleure conception et intégration.
Pour les API REST, il n’y avait pas de norme standard jusqu’à l’émergence de Swagger, remplacé plus tard par OpenAPI. Ces standards facilitent la cohérence, la réutilisation et l’automatisation partielle du codage des API. L’approche API-First favorise également un découplage entre le producteur et le consommateur de l’API. Les normes actuelles pour REST incluent Swagger 2.0 et OpenAPI 3.0.
1. Outils
Swagger et OpenAPI, bien que souvent mentionnés ensemble, représentent un ensemble unifié d’outils et de spécifications pour la gestion efficace des API. Ils adhèrent aux mêmes standards, offrant une suite d’outils complémentaires qui facilitent la conception, le développement, la documentation, et les tests des API. Parmi ces outils, Swagger UI permet de visualiser et d’interagir avec l’API de manière intuitive, Swagger Editor aide à sa conception et documentation, et Swagger Codegen simplifie la génération de code pour les clients et serveurs. Avec l’évolution des standards, les outils OpenAPI sont désormais privilégiés pour leur capacité à offrir des fonctionnalités avancées, assurant une gestion des API plus intégrée et efficace.
a. Swagger
Les sources sont disponibles sur GitHub ici :...
Spring Actuator
Spring Boot Actuator est un module qui permet d’obtenir des informations opérationnelles sur notre application.
Pour l’utiliser avec Spring Boot, il suffit d’ajouter la dépendance maven :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Le module fonctionne avec les applications Spring MVC et Spring Webflux et il utilise les endpoints HTTP et JMX pour exposer les informations.
Avec Spring Boot 2, seuls les endpoints /health et /info sont exposés pour limiter les problèmes de sécurité.
Endpoints disponibles :
Endpoint |
Usage |
/auditevents |
Liste les événements liés à l’audit de sécurité tels que la connexion/déconnexion de l’utilisateur. Nous pouvons appliquer des filtres. |
/beans |
Liste tous les beans disponibles dans notre BeanFactory. Contrairement à /auditevents, il ne prend pas en charge le filtrage. |
/conditions |
Crée un rapport de conditions autour de la configuration automatique. |
/configprops |
Liste tous les beans @ConfigurationProperties. |
/env |
Liste les propriétés d’environnement actuelles. |
/flyway |
Détaille nos migrations de base de données Flyway. |
/health |
Résume l’état de santé de notre application.... |
Points clés
Points à retenir :
-
Spring MVC est très puissant et permet de couvrir les besoins courants des applications web.
-
Nous pouvons tester la majorité de notre code.
-
Le mode MVC standardise le développement de l’application.