Dans Spring Boot, la gestion centralisée des exceptions permet d'intercepter et de traiter les erreurs de manière uniforme à travers l'application. Voici comment implémenter cette approche avec des exemples de code modifiés pour plus de clarté et d'originalité.
La classe principale pour capturer les exceptions est définie comme suit :
package com.example.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MissingServletRequestParameterException.class)
public String missingParamHandler(MissingServletRequestParameterException ex) {
log.error("Paramètre de requête manquant", ex);
return "Paramètre de requête manquant";
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public String parsingFailureHandler(HttpMessageNotReadableException ex) {
log.error("Échec de l'analyse des paramètres", ex);
return "Échec de l'analyse des paramètres";
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public String validationFailureHandler(MethodArgumentNotValidException ex) {
log.error("Échec de la validation des paramètres", ex);
BindingResult result = ex.getBindingResult();
FieldError error = result.getFieldError();
String champ = error.getField();
String message = error.getDefaultMessage();
return "Validation échouée : " + champ + " - " + message;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(BindException.class)
public String bindingFailureHandler(BindException ex) {
log.error("Échec de la liaison des paramètres", ex);
BindingResult result = ex.getBindingResult();
FieldError error = result.getFieldError();
String champ = error.getField();
String message = error.getDefaultMessage();
return "Liaison échouée : " + champ + " - " + message;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public String constraintViolationHandler(ConstraintViolationException ex) {
log.error("Violation de contrainte de validation", ex);
Set<constraintviolation>> violations = ex.getConstraintViolations();
if (!violations.isEmpty()) {
ConstraintViolation> violation = violations.iterator().next();
return "Violation de contrainte : " + violation.getMessage();
}
return "Violation de contrainte inconnue";
}
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoHandlerFoundException.class)
public String notFoundHandler(NoHandlerFoundException ex) {
log.error("Ressource non trouvée", ex);
return "Ressource non trouvée : " + ex.getRequestURL();
}
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public String methodNotAllowedHandler(HttpRequestMethodNotSupportedException ex) {
log.error("Méthode HTTP non supportée", ex);
return "Méthode HTTP non supportée";
}
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
public String unsupportedMediaTypeHandler(HttpMediaTypeNotSupportedException ex) {
log.error("Type de média non supporté", ex);
return "Type de média non supporté";
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(BusinessException.class)
public String businessExceptionHandler(BusinessException ex) {
log.error("Exception métier", ex);
return "Exception métier : " + ex.getMessage();
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(DatabaseOperationException.class)
public String databaseOperationHandler(DatabaseOperationException ex) {
log.error("Exception d'opération en base de données", ex);
return "Exception d'opération en base de données : " + ex.getMessage();
}
@ExceptionHandler(Exception.class)
public String generalExceptionHandler(Exception ex) {
log.error("Exception générale", ex);
return "Exception générale : " + ex.getMessage();
}
}</constraintviolation>
Les exceptions personnalisées sont définies pour des cas spécifiques :
package com.example.exception;
public class BusinessException extends RuntimeException {
public BusinessException(String message) {
super(message);
}
}
package com.example.exception;
public class DatabaseOperationException extends RuntimeException {
public DatabaseOperationException(String message) {
super(message);
}
}
Pour que Spring MVC lance des exceptions sur les routes non gérées, ajoutez cette configuraton dans le fichier application.yml :
spring:
mvc:
throw-exception-if-no-handler-found: true
resources:
add-mappings: false
Cette configuration garantit que les requêtes sans gestionnaire défini déclenchent une exception, facilitant ainsi la gestion globale des erreurs 404.