Dans Spring MVC, l'annotation @ControllerAdvice sert à définir des composants partagés pour tous les contrôleurs. Elle facilite la gestion centralisée de certaines opérations. Voici trois cas d'usage principaux.
Gestion des exceptions globales
Grâce à @ControllerAdvice, on peut capturer et traiter les exceptions provenant de n'importe quel contrôleur. Il suffit de créer une classe annotée et d'y placer des méthodes dédiées aux différentes erreurs.
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView traiterException(Exception ex) {
ModelAndView modelView = new ModelAndView();
modelView.addObject("erreur", ex.getMessage());
modelView.setViewName("vue_erreur");
return modelView;
}
}
La méthode peut être adaptée pour des exceptions spécifiques comme NullPointerException. L'annotation @ExceptionHandler définit le type d'exception à intercepter.
Liaison de données globales
Cette fonctionnalité permet d'injecter des attributs communs dans tous les modèles de contrôleur. On utilise l'annotation @ModelAttribute dans une classe @ControllerAdvice.
@ControllerAdvice
public class GlobalDataProvider {
@ModelAttribute(name = "donneesCommunes")
public Map<String, Object> obtenirDonnees() {
Map<String, Object> attributs = new HashMap<>();
attributs.put("version", "2.0");
attributs.put("environnement", "production");
return attributs;
}
}
Dans tout contrôleur, les données définies précédemment sont accessibles via le modèle, par exemple en récupérant la carte d'attributs.
Prétraitement des données globales
Pour éviter les conflits de noms entre paramètres, on peut préfixer les champs de différentes entités. Cela est utile lorsque plusieurs objets partagent des propriétés similaires.
Considérons deux classes simples :
public class Livre {
private String titre;
private Double prix;
// accesseurs et mutateurs
}
public class Auteur {
private String nom;
private Integer age;
// accesseurs et mutateurs
}
Dans un contrôleur, on applique des alias via @ModelAttribute :
@PostMapping("/ajouter-livre")
public void ajouterLivre(@ModelAttribute("l") Livre livre, @ModelAttribute("a") Auteur auteur) {
System.out.println(livre.getTitre());
System.out.println(auteur.getNom());
}
Ensuite, dans la classe @ControllerAdvice, on configure des préfixes pour chaque alias :
@ControllerAdvice
public class GlobalDataPreprocessor {
@InitBinder("l")
public void initBinderLivre(WebDataBinder binder) {
binder.setFieldDefaultPrefix("l.");
}
@InitBinder("a")
public void initBinderAuteur(WebDataBinder binder) {
binder.setFieldDefaultPrefix("a.");
}
}
Lors de la requête, les paramètres correspondant à Livre doivent commencer par l., et ceux de Auteur par a., assurant ainsi une distinction claire.