[JAVA] Personnalisez la réponse aux erreurs de l'API REST avec Spring Boot (Partie 1)

Aperçu

J'ai essayé de personnaliser la réponse au moment de l'erreur avec Spring Boot, je la décrirai donc ici comme un mémorandum. Cette fois, j'aimerais personnaliser la partie du corps de la réponse comme suit.

Changer avant

{
  "timestamp": "2019-03-14T15:07:50.631+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "MyException s'est produite",
  "path": "/××××/××××"
}

Après le changement

{
  "timestamp": "2019-03-14T15:07:50.631+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "MyException s'est produite",
  "path": "/××××/××××",
  "errorDetail": {
    "detailMessage": "××××××××××××"
  }
}

Conditions préalables

environnement

Flux de processus

Les quatre personnages suivants sont à peu près les personnages cette fois.

--Classe de contrôleur qui accepte les demandes

De plus, le déroulement général du processus à mettre en œuvre désormais est le suivant.

  1. Explicitement «throw» du contrôleur avec votre propre exception définie en même temps que la requête
  2. (Créez une classe qui gère l'exception) Attrapez l'exception `throwʻed avec la classe handle
  3. Renvoie un corps de réponse personnalisé

Après cela, nous mettrons en œuvre le traitement ci-dessus. (Bien que la commande ne soit pas en ordre ...)

la mise en oeuvre

Définition de la classe de mappage

Ici, nous définissons la classe de mappage pour le corps de la réponse.

ErrorResponseBody.java


package com.example.demo.errorResponse;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Setter;

import java.time.ZonedDateTime;

@Setter
public class ErrorResponseBody {

        @JsonProperty("timestamp")
        private ZonedDateTime exceptionOccurrenceTime;
        @JsonProperty("status")
        private int status;
        @JsonProperty("error")
        private String error;
        @JsonProperty("message")
        private String message;
        @JsonProperty("path")
        private String path;
        @JsonProperty("errorDetail")
        private ErrorDetail errorDetail;
}

ErrorDetail.java


package com.example.demo.errorResponse;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Setter;

@Setter
public class ErrorDetail {
    @JsonProperty("detailMessage")
    String detailMessage;
}

Définition de la classe d'exception unique

MyException.java


package com.example.demo.errorResponse;

import lombok.Getter;

@Getter
public class MyException extends RuntimeException {

    private ErrorDetail errorDetails;

    public MyException(String message, ErrorDetail errorDetails) {
        super(message);
        this.errorDetails = errorDetails;
    }
}

Définition du contrôleur

HelloController.java


package com.example.demo.errorResponse;

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

@RestController
@RequestMapping("/exceptionhandle")
public class HelloController {

    @RequestMapping("/test")
    public String get() {
        ErrorDetail errorDetail = new ErrorDetail();
        errorDetail.setDetailMessage("Message détaillé");
        throw new MyException("MyException s'est produite", errorDetail);
    }
}

Définition de la classe du gestionnaire d'exceptions

C'est la partie la plus importante. Il y a quatre points.

  1. Ajoutez l'annotation @ RestControllerAdvice à la classe de descripteurs
  2. Hériter de la classe ResponseEntityExceptionHandler
  3. Ajoutez l'annotation @ ExceptionHandler et spécifiez la classe d'exception définie de manière unique à compléter.
  4. Passez l'instance de la classe définie pour le corps de la réponse au deuxième paramètre de la méthode super.handleExceptionInternal (à part, les arguments de cette méthode sont dans l'ordre suivant).

Et enfin, il renvoie ResponseEntity.

HelloExceptionHandler.java


package com.example.demo.errorResponse;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.time.ZonedDateTime;

@RestControllerAdvice
public class HelloExceptionHandler extends ResponseEntityExceptionHandler {
    //Attraper MyException lancée par le contrôleur
    @ExceptionHandler(MyException.class)
    public ResponseEntity<Object> handleMyException(MyException exception, WebRequest request) {
        HttpHeaders headers = new HttpHeaders();

        return super.handleExceptionInternal(exception,
                createErrorResponseBody(exception, request),
                headers,
                HttpStatus.BAD_REQUEST,
                request);
    }

    //Créer la partie du corps de la réponse
    private ErrorResponseBody createErrorResponseBody(MyException exception, WebRequest request) {

        ErrorResponseBody errorResponseBody = new ErrorResponseBody();
        int responseCode = HttpStatus.BAD_REQUEST.value();
        String responseErrorMessage = HttpStatus.BAD_REQUEST.getReasonPhrase();
        String uri = ((ServletWebRequest) request).getRequest().getRequestURI();

        errorResponseBody.setExceptionOccurrenceTime(ZonedDateTime.now());
        errorResponseBody.setStatus(responseCode);
        errorResponseBody.setError(responseErrorMessage);
        errorResponseBody.setMessage(exception.getMessage());
        errorResponseBody.setPath(uri);
        errorResponseBody.setErrorDetail(exception.getErrorDetails());

        return errorResponseBody;
    }
}

En passant, la méthode handleExceptionInternal de la classe parent ResponseEntityExceptionHandler ressemble à ceci: La partie qui passe l'instance pour la réponse d'erreur est @Nullable Object body, donc si vous ne la passez pas correctement, la partie du corps ne sera pas affichée.

ResponseEntityExceptionHandler.java


	/**
	 * A single place to customize the response body of all Exception types.
	 * <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
	 * request attribute and creates a {@link ResponseEntity} from the given
	 * body, headers, and status.
	 * @param ex the exception
	 * @param body the body for the response
	 * @param headers the headers for the response
	 * @param status the response status
	 * @param request the current request
	 */
	protected ResponseEntity<Object> handleExceptionInternal(
			Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {

		if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
			request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
		}
		return new ResponseEntity<>(body, headers, status);
	}

résultat

{
  "timestamp": "2019-03-18T10:11:13.795+09:00",
  "status": 400,
  "error": "Bad Request",
  "message": "MyException s'est produite",
  "path": "/exceptionhandle/test",
  "errorDetail": {
    "detailMessage": "Message détaillé"
  }
}

Article associé

Personnaliser la réponse d'erreur de l'API REST avec Spring Boot (Partie 2)

Article de référence

Cette fois, j'ai fait référence à l'article suivant lors de la rédaction de l'article.

Personnalisez la réponse d'erreur de l'API REST créée par Spring Boot Gestion des erreurs avec Spring Boot Gestion des exceptions avec @ RestController de Spring Boot

Recommended Posts

Personnalisez la réponse aux erreurs de l'API REST avec Spring Boot (Partie 1)
Hello World (API REST) avec Apache Camel + Spring Boot 2
[Spring Boot] Obtenez des informations utilisateur avec l'API Rest (débutant)
Implémentez une API Rest simple avec Spring Security avec Spring Boot 2.0
Spring avec Kotorin - 4 Conception d'API REST
Test de l'API REST à l'aide de REST Assured Part 2
Implémenter l'API REST avec Spring Boot
Implémenter l'API REST avec Spring Boot et JPA (Application Layer)
Implémenter l'API REST avec Spring Boot et JPA (couche d'infrastructure)
Implémenter l'API REST avec Spring Boot et JPA (Domain Layer Edition)
Implémentez une API Rest simple avec Spring Security & JWT avec Spring Boot 2.0
Implémentez un serveur API Web REST simple avec Spring Boot + MySQL
Changer la demande / réponse de l'API REST Spring Boot de CamelCase à SankeCase
[Débutant] Essayez d'écrire l'API REST pour l'application Todo avec Spring Boot
Créer un serveur API Web avec Spring Boot
Télécharger avec Spring Boot
J'ai créé un domaine api avec Spring Framework. Partie 2
Mappez automatiquement DTO aux entités avec l'API Spring Boot
Étendez Spring Boot DefaultErrorViewResolver pour personnaliser dynamiquement les écrans d'erreur
Un mémorandum lors de la création d'un service REST avec Spring Boot
J'ai créé un domaine api avec Spring Framework. Partie 1
Présentez swagger-ui à l'API REST implémentée dans Spring Boot
Générer un code à barres avec Spring Boot
Hello World avec Spring Boot
Implémenter GraphQL avec Spring Boot
Bonjour tout le monde avec Spring Boot!
Exécutez LIFF avec Spring Boot
Connexion SNS avec Spring Boot
Téléchargement de fichiers avec Spring Boot
Spring Boot commençant par copie
Spring Boot à partir de Docker
Hello World avec Spring Boot
Définir des cookies avec Spring Boot
Test de l'API REST avec REST Assured
Utiliser Spring JDBC avec Spring Boot
Ajouter un module avec Spring Boot
Lier l'API avec Spring + Vue.js
Introduction à Spring Boot, partie 1
Créer un micro service avec Spring Boot
Envoyer du courrier avec Spring Boot
Gérez l'API de date et d'heure Java 8 avec Thymeleaf avec Spring Boot
Essayez d'utiliser l'API de recherche de code postal avec Spring Boot
Découvrons comment recevoir avec Request Body avec l'API REST de Spring Boot
Utiliser l'authentification de base avec Spring Boot
Créons une application Web de gestion de livres avec Spring Boot part1
gRPC sur Spring Boot avec grpc-spring-boot-starter
Créez une application avec Spring Boot 2
Déploiement à chaud avec le développement Spring Boot
Liaison de base de données avec doma2 (Spring boot)
Créons une application Web de gestion de livres avec Spring Boot part3
Spring Boot: exemple de projet d'API Restful
Programmation Spring Boot avec VS Code
Créer une application d'enquête avec Spring Boot
Partie 1: Essayez d'utiliser la connexion OAuth 2.0 prise en charge par Spring Security 5 avec Spring Boot
Comment créer votre propre contrôleur correspondant à / error avec Spring Boot
Créons une application Web de gestion de livres avec Spring Boot part2
Obtenez des résultats de validation avec Spring Boot
API RESTful d'autorisation d'accès au démarrage de printemps
J'ai créé un formulaire de recherche simple avec Spring Boot + GitHub Search API.
(Intellij) Hello World avec Spring Boot
Créez une application avec Spring Boot