Dans Spring Boot, je crée une classe d'exception personnalisée avec un code d'état spécifique, et je l'appelle pour lancer une exception avec le code: 100 et le message: "No have content" au contrôleur, mais la sortie renvoie toujours "status": 500 et " erreur ":" Erreur interne du serveur "
AppException.java
{ "timestamp": 1550987372934, "status": 100, "error": "No have content", "exception": "com.app.core.exception.AppException", "message": "No have content", "path": "/api/user" }
UserController.java
{ "timestamp": 1550987372934, "status": 500, "error": "Internal Server Error", "exception": "com.app.core.exception.AppException", "message": "No have content", "path": "/api/user" }
Résultat réel:
@RestController @RequestMapping("/api/user") public class UserController { @Autowired private UserService userService; @GetMapping() public ApiResponseDto getAllUsers(Pageable pageable) { Page<User> users = userService.getAllUsers(pageable); if (users.getSize() < 0) { throw new AppException(100, "No have content"); } return new ApiResponseDto(HttpStatus.OK.value(), users); }
Mes attentes:
public class AppException extends RuntimeException { private static final long serialVersionUID = 1L; private final Integer code; public AppException(Integer code, String message) { super(message); this.code = code; } public Integer getCode() { return code; } }
3 Réponses :
Si vous souhaitez une gestion globale des exceptions pour votre API, et préférez avoir des réponses d'erreur personnalisées, vous pouvez ajouter @ControllerAdvice
:
@ControllerAdvice public class ApiExceptionHandler { @ExceptionHandler({ ApiException.class }) protected ResponseEntity<ApiErrorResponse> handleApiException(ApiException ex) { return new ResponseEntity<>(new ApiErrorResponse(ex.getStatus(), ex.getMessage(), Instant.now()), ex.getStatus()); } } // you can put any information you want in ApiErrorResponse public class ApiErrorResponse { private final HttpStatus status; private final String message; private final Instant timestamp; public ApiError(HttpStatus status, String message, Instant timestamp) { this.status= status; this.message = message; this.timestamp = timestamp; } public HttpStatus getStatus() { return this.status; } public String getMessage() { return this.message; } public Instant getTimestamp() { return this.timestamp; } } // your custom ApiException class public class ApiException extends RuntimeException { private final HttpStatus status; public ApiException(HttpStatus status, String message) { super(message); this.status = status; } public HttpStatus getStatus() { return this.status; } }
p >
Merci, mais lancez une nouvelle AppException (100, "No have content"); est un exemple. Parce que je souhaite utiliser la classe AppException pour beaucoup de mon code d'état dans le projet
@Tony J'ai mis à jour la réponse au cas où vous voudriez avoir une gestion globale des exceptions pour votre API, et préférez avoir des réponses d'erreur personnalisées.
merci, mais je veux lancer une exception à n'importe quelle classe de service, classe java, ..., pas de retour pour le contrôleur. btw, en utilisant @ControllerAdvice, il ne renvoie pas non plus exactement le code d'état que j'ai mis pour ApiException (code entier, message String). Pouvez-vous me suggérer une autre façon?
@Tony Exception peut être lancée n'importe où dans votre code. Utilisez également HttpStatus
au lieu de Integer
dans ApiException
.
Il existe plusieurs façons d'y parvenir:
Vous pouvez ajouter une méthode annotée @ExceptionHandler
dans votre contrôleur: @ExceptionHandler({ CustomException1.class, CustomException2.class })
public void handleException() {
//
}
Vous pouvez également implémenter un résolveur personnalisé pour intercepter toutes les exceptions et les gérer globalement en remplaçant la méthode doResolveException
Plus de détails sur les deux approches ci-dessus peuvent être trouvés ici: https://www.baeldung.com/exception-handling-for-rest-with-spring
Si vous avez besoin d'un nombre limité de messages d'erreur différents ou si vous souhaitez réutiliser le même plusieurs fois, c'est tout ce dont vous avez besoin:
throw new AppException();
Pas besoin de classes et de gestionnaires supplémentaires . Votre code sera clair et simple.
Vous pouvez simplement le monter comme ceci:
@ResponseStatus(value = HttpStatus.CONTINUE, reason = "No have content") public class AppException extends RuntimeException { private static final long serialVersionUID = 1L; }