[JAVA] Je veux contrôler le message d'erreur par défaut de Spring Boot

Objectif

Je souhaite contrôler le message d'erreur par défaut renvoyé lorsqu'une erreur se produit dans l'API REST créée par Spring Boot.

Contexte

Supposons que vous ayez préparé le RestController suivant.

MyRestController.java


package demo;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyRestController {
    
    @RequestMapping(value="/test/{id}")
    private String hello(@PathVariable String id){
        if ("0000".equals(id)) {
            throw new MyCustomException(); //Exception attendue
        }
        
        return "Hello world!!";
    }

    @RequestMapping(value="/test-null")
    private String hello(){
        String s = null;
        s.equals("hoge"); //Épidémie de NPE par inadvertance
        
        return "Hello world!!";
    }
}

Spring Boot renverra alors le message d'erreur suivant par défaut.

$ curl http://localhost:8080/test/0000 #MyCustomError attendu
{"timestamp":1526654632290,"status":500,"error":"Internal Server Error","exception":"my.spring.MySpringBootSample.MyCustomError","message":"No message available","path":"/test/0000"}%
$ curl http://localhost:8080/test-null #NPE que j'ai éteint accidentellement
{"timestamp":1526654636310,"status":500,"error":"Internal Server Error","exception":"java.lang.NullPointerException","message":"No message available","path":"/test-null"}%
$ curl http://localhost:8080/wrong-path #Mauvais chemin
{"timestamp":1526654639289,"status":404,"error":"Not Found","message":"No message available","path":"/wrong-path"}%

Cependant, il est trop cool et pas bon pour la sécurité de voir l'exception NullPointerException qui est arrivée par inadvertance à l'utilisateur. Je suis également exposé à l'utilisation de Spring Boot.

Contrôle des erreurs possibles

En préparant une classe avec l'annotation @ ControllerAdvice, il est possible de contrôler les messages d'erreur dans RestController.

MyControllerAdvice.java


package demo;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class MyControllerAdvice {

    /**
     *Gestionnaire lorsque MyCustomException se produit
     * 
     * @réponse de retour
     */
    @ExceptionHandler(MyCustomException.class)
    public ResponseEntity<String> handleControllerException() {
        return new ResponseEntity<String>("customized message for MyCustomError.", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
$ curl http://localhost:8080/test/0000
customized message for MyCustomError.%

Contrôle contre les erreurs inattendues

En plus de ce qui précède, si vous créez un ExceptionHandler qui reçoit Exception.class, il est possible de renvoyer un message d'erreur personnalisé de manière uniforme pour toute erreur inattendue qui se produit dans RestController.

MyControllerAdvice.java


package demo;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class MyControllerAdvice {

    /**
     *Gestionnaire lorsque MyCustomException se produit
     * 
     * @réponse de retour
     */
    @ExceptionHandler(MyCustomException.class)
    public ResponseEntity<String> handleControllerException() {
        return new ResponseEntity<String>("customized message for MyCustomError.", HttpStatus.INTERNAL_SERVER_ERROR);
    }
    
    /**
     *Gestionnaire lorsqu'une exception se produit
     * 
     * @réponse de retour
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleControllerException2() {
        return new ResponseEntity<String>("customized message for any unexpected exception.", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Cependant, cette méthode ne contrôle pas les erreurs avant d'entrer RestController, telles que des chemins d'accès incorrects.

$ curl http://localhost:8080/test/0000
customized message for MyCustomError.%
$ curl http://localhost:8080/test-null
customized message for any unexpected exception.%
$ curl http://localhost:8080/wrong-path #Une erreur par défaut est renvoyée pour un chemin erroné
{"timestamp":1526655182855,"status":404,"error":"Not Found","message":"No message available","path":"/wrong-path"}%

Quand je l'ai recherché, c'était [Officiel](https://docs.spring.io/spring-boot/docs/1.5.3.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features -error-handling) a la description suivante.

Spring Boot provides an /error mapping by default that handles all errors in a sensible way, and it is registered as a ‘global’ error page in the servlet container.

Le fait est que chaque erreur est mappée sous / error par défaut. Si vous voulez le contrôler comme vous le souhaitez, réalisez ErrorController, alors préparez la classe suivante.

MyErrorController.java


package demo;

import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyErrorController implements ErrorController {

    @RequestMapping("/error")
    public ResponseEntity<String> handleError() {
        return new ResponseEntity<String>("customized message for any unhandled error.", HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @Override
    public String getErrorPath() {
        return "/error";
    }
}

Ensuite, le message d'erreur par défaut a disparu.

$ curl http://localhost:8080/test/0000
customized message for MyCustomError.%
$ curl http://localhost:8080/test-null
customized message for any unexpected exception.%
$ curl http://localhost:8080/wrong-path
customized message for any unhandled error.%

Recommended Posts

Je veux contrôler le message d'erreur par défaut de Spring Boot
05. J'ai essayé de supprimer la source de Spring Boot
J'ai essayé de réduire la capacité de Spring Boot
Je veux comprendre le flux des paramètres de demande de traitement Spring
Je souhaite contrôler la taille de fichier maximale pour le téléchargement de fichiers pour chaque URL dans Spring Boot
L'histoire de la montée de la série Spring Boot 1.5 à la série 2.1
Je souhaite afficher un message d'erreur lors de l'inscription dans la base de données
Je veux connaître la méthode du contrôleur où l'exception a été levée dans le ExceptionHandler de Spring Boot
Je veux connaître la réponse de l'application Janken
Je veux retourner la position de défilement de UITableView!
L'histoire de la montée de Spring Boot de la série 1.5 à la série 2.1 part2
À propos de la fonction de Spring Boot en raison de différentes versions
Je souhaite modifier le paramètre de sortie du journal de UtilLoggingJdbcLogger
[Ruby] Je souhaite inverser l'ordre de la table de hachage
Sortie de message (Spring boot)
Je souhaite contrôler l'affichage de la barre de navigation de gestion supérieure (menu Contrôle) dans Liferay 7 / DXP
Je souhaite changer la couleur du menu de contrôle en haut de Liferay 7 / DXP
L'histoire de Collectors.groupingBy que je veux garder pour la postérité
J'ai essayé de traduire le message d'erreur lors de l'exécution d'Eclipse (Java)
Ce que j'ai fait lors de la migration de la série Spring Boot 1.4 vers la série 2.0
Je veux limiter l'entrée en réduisant la plage de nombres
Ce que j'ai fait lors de la migration de la série Spring Boot 1.5 vers la série 2.0
Je veux changer la valeur de l'attribut dans Selenium of Ruby
Je souhaite éliminer les messages d'erreur en double
[Spring Boot] Je veux ajouter mon propre fichier de propriétés et obtenir la valeur avec env.getProperty ().
Je veux rendre le cadre de la zone de texte rouge lorsqu'il y a une erreur de saisie
Comment diviser un fichier de message Spring Boot
Je veux écrire une JSP dans Emacs plus facilement que la valeur par défaut.
Spring Boot + MyBatis J'obtiens cette erreur si je ne configure pas la base de données
Étapes pour rendre Spring Boot capable de faire référence à la valeur dans le fichier de propriétés
Je veux connaître le JSP du portlet ouvert lors du développement de Liferay
[Ruby] Je souhaite extraire uniquement la valeur du hachage et uniquement la clé
J'ai utilisé Docker pour solidifier le modèle à développer avec Spring Boot.
Je veux passer l'argument d'Annotation et l'argument de la méthode d'appel à aspect
Mon mémorandum que je veux faire ValidationMessages.properties UTF8 dans Spring Boot
Je veux obtenir le nom de champ du champ [Java]. (Vieux ton d'histoire)
Je veux que vous utilisiez Enum # name () pour la clé de SharedPreference
Comment trouver la cause de l'erreur Ruby
[FCM] Implémentation de la transmission de messages en utilisant FCM + Spring boot
Je voulais classer la botte à ressort dans un multi-projet
[Spring Boot] Comment se référer au fichier de propriétés
Je veux obtenir la valeur en Ruby
Je veux obtenir la valeur de Cell de manière transparente quel que soit CellType (Apache POI)
03. J'ai envoyé une demande de Spring Boot à l'API de recherche de code postal
Lorsque vous souhaitez notifier une erreur quelque part lors de l'utilisation de graphql-spring-boot avec Spring Boot
J'ai essayé de cloner une application Web pleine de bugs avec Spring Boot
À partir de Spring Boot 2.3, la page d'erreur par défaut ne contient plus d'informations détaillées sur l'erreur
Comment définir des variables d'environnement dans le fichier de propriétés de l'application Spring Boot
[Ruby on Rails] Comment japonaisiser le message d'erreur de l'objet Form (ActiveModel)
Je veux voir le contenu de Request sans dire quatre ou cinq
Je veux obtenir récursivement la superclasse et l'interface d'une certaine classe