2017-12-20 3 views
3

werfen -Wie eine Ausnahme zurück in JSON in Spring-Boot Ich habe Mapping eine Anfrage

@RequestMapping("/fetchErrorMessages") 
    public @ResponseBody int fetchErrorMessages(@RequestParam("startTime") String startTime,@RequestParam("endTime") String endTime) throws Exception 
    { 
     if(SanityChecker.checkDateSanity(startTime)&&SanityChecker.checkDateSanity(endTime)) 
     { 
      return 0; 
     } 
     else 
     { 
      throw new NotFoundException("Datetime is invalid"); 
     } 
    } 

Wenn die Startzeit und endTime ungültig ist, möchte ich ein 500-Fehler werfen, sondern die Ausnahme Zeichenfolge in JSON zurück. Ich bekomme jedoch eine HTML-Seite statt

Whitelabel-Fehler Seite Diese Anwendung hat keine explizite Zuordnung für/Fehler, so dass Sie dies als Fallback sehen.

Mi Dezember 20 10:49:37 IST 2017 Es gab einen unerwarteten Fehler (Typ = Interner Serverfehler, Status = 500). für Datum und Uhrzeit ist ungültig

ich stattdessen mit einem JSON

{"error":"Date time format is invalid"} 

Wie kann ich über diese gehen zurück 500 wollte?

Antwort

3

Angenommen, Sie eine benutzerdefinierte Exception-Klasse NotFoundException und ihre Implementierungen etwas wie dieses:

public class NotFoundException extends Exception { 

    private int errorCode; 
    private String errorMessage; 

    public NotFoundException(Throwable throwable) { 
     super(throwable); 
    } 

    public NotFoundException(String msg, Throwable throwable) { 
     super(msg, throwable); 
    } 

    public NotFoundException(String msg) { 
     super(msg); 
    } 

    public NotFoundException(String message, int errorCode) { 
     super(); 
     this.errorCode = errorCode; 
     this.errorMessage = message; 
    } 


    public void setErrorCode(int errorCode) { 
     this.errorCode = errorCode; 
    } 

    public int getErrorCode() { 
     return errorCode; 
    } 

    public void setErrorMessage(String errorMessage) { 
     this.errorMessage = errorMessage; 
    } 

    public String getErrorMessage() { 
     return errorMessage; 
    } 

    @Override 
    public String toString() { 
     return this.errorCode + " : " + this.getErrorMessage(); 
    } 
} 

Jetzt wollen Sie eine Ausnahme von der Steuerung werfen. Wenn Sie eine Ausnahme auslösen, müssen Sie sie von einer Standard-Error-Handler-Klasse abfangen, sagen wir zum Beispiel, dass sie im Frühjahr @ControllerAdvice Annotation bereitstellt, die angewendet werden soll, um eine Klasse Standard Error Handler zu erstellen. Wenn es auf eine Klasse angewendet wird, kann diese Federkomponente (ich meine die Klasse, die Sie annotiert haben) jede vom Controller geworfene Ausnahme abfangen. Aber wir müssen die Ausnahmeklasse mit der richtigen Methode abbilden. Also haben wir eine Methode mit Ihrer Ausnahme NotFoundException Handler etwas wie unten definiert.

@ControllerAdvice 
public class RestErrorHandler { 

    @ExceptionHandler(NotFoundException.class) 
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 
    @ResponseBody 
    public Object processValidationError(NotFoundException ex) { 
     String result = ex.getErrorMessage(); 
     System.out.println("###########"+result); 
     return ex; 
    } 
} 

Sie wollen gesendet http Status interner Serverfehler (500), so hier haben wir @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR). Da Sie Spring-Boot verwendet haben, müssen Sie keine JSON-Zeichenkette erstellen, außer eine einfache Annotation @ResponseBody kann dies automatisch für Sie tun.

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 
public class NotFoundException extends RuntimeException { 
    public NotFoundException() { 
    } 

    public NotFoundException(String message) { 
    super(message); 
    } 

} 
0

Dies ist, wie ich habe es in meiner Anwendung:

import org.springframework.web.bind.annotation.ControllerAdvice; 
import org.springframework.web.bind.annotation.ExceptionHandler; 

@ControllerAdvice 
public class ExceptionHandlingControllerAdvice { 

    @ExceptionHandler(ExecutionRestrictionViolationException.class) 
    public ResponseEntity<String> handleExecutionRestrictionViolationException(ExecutionRestrictionViolationException ex) { 
    return response("Invalid Query", ex.getMessage(), HttpStatus.UNPROCESSABLE_ENTITY); 
    } 

    private static String createJson(String message, String reason) { 
    return "{\"error\" : \"" + message + "\"," + 
      "\"reason\" : \"" + reason + "\"}"; 
    } 

    private static ResponseEntity<String> response(String message, 
               String reason, 
               HttpStatus httpStatus) { 
    String json = createJson(message, reason); 
    return new ResponseEntity<>(json, httpStatus); 
    } 

} 

Erläuterung:

  1. Sie eine Controller Beratung schaffen, es mit einer speziellen Anmerkung markiert und wie jede andere Bohne definieren (in meinem Fall war es eine Java-Konfiguration, aber es ist nicht wirklich wichtig)

  2. Für jede Ausnahme möchten Sie so umgehen - definieren Sie einen Handler, der wird Ich erzeuge eine Antwort in einem Format, das Sie wollen

  3. Es gibt eine statische Methode createJson - Sie können einen anderen Weg verwenden, es spielt auch keine Rolle.

Nun ist dies nur ein Weg zur Arbeit (seine in neueren Frühjahr Boot-Versionen) - aber es gibt auch andere:

Alle Methoden, die ich bin mir dessen bewusst (und noch mehr) aufgelistet here .

+0

Wenn er wirft 'NotFoundException' sollte dann nicht' @ ExceptionHandler' Klasse '@ExceptionHandler (NotFoundException.class)' sein? –

+0

Ja sicher, du hast vollkommen recht damit. Ich habe gerade ein Code-Snippet (die Idee) aus meiner Anwendung gezeigt. Es sollte eine Methode pro Ausnahmetyp sein, glaube ich. –

+0

Sieht so aus, als könnte ich einfach accept headers vom Client senden und die Antwort wird in JSON sein (danke an Jackson) –

0

können Sie NotFoundException Klasse mit @ResponseStatus Anmerkung wie unten erstellen. Bitte beachten Sie das folgende Code-Snippet. Für jede RuntimeException in Ihrer Anwendung wird es auf eine Json Response Entity abgebildet.

public class RuntimeExceptionMapper implements ExceptionMapper <RuntimeException> { 

@Override 
public Response toResponse(RuntimeException exception) { 
    ErrorResponse errorResponse = new ErrorResponse(); 
    errorResponse.setMessage(exception.getMessage); 
    if (exception== null) { 
     logger.error("Exception Details Not found");    
    } else { 
     return Response.status(Status.INTERNAL_SERVER_ERROR) 
      .entity(errorResponse) 
       .type(MediaType.APPLICATION_JSON) 
        .header("trace-id", "1234").build(); 
    } 


} 

}

+0

Das funktioniert, aber ich würde diesen Ansatz nicht empfehlen. Es gibt keine Möglichkeit, eine benutzerdefinierte Nachricht anzuzeigen, wenn Sie eine möchten, und sie ist auch nicht sicher, weil sie immer noch etwas wie "Apache Tomcat/8.0.18" anzeigt, so dass Personen mit schlechten Absichten jetzt spezifischer suchen können für Verletzungen in Ihrem System. –

0

Javax hat einen Schnittstellennamen als ExceptionMapper:

0

eine benutzerdefinierte Ausnahme erstellen.

public class SecurityException extends RuntimeException { 

    private static final long serialVersionUID = -7806029002430564887L; 

    private String message; 

    public SecurityException() { 
    } 

    public SecurityException(String message) { 
     this.message = message; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 

} 

Erstellen Sie eine benutzerdefinierte Antworteinheit.

public class SecurityResponse { 

    private String error; 

    public SecurityResponse() { 

    } 

    public SecurityResponse(String error) { 
     this.error = error; 
    } 

    public String getError() { 
     return error; 
    } 

    public void setError(String error) { 
     this.error = error; 
    } 

} 

erstellen ControllerAdvice mit Exception für benutzerdefinierte Ausnahme, wird die benutzerdefinierte Ausnahme behandeln, bevölkern und die benutzerdefinierte Reaktion wie unten zurück.

@ControllerAdvice 
public class SecurityControllerAdvice { 

    @ExceptionHandler(SecurityException.class) 
    @ResponseBody 
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 
    public SecurityResponse handleSecurityException(SecurityException se) { 
     SecurityResponse response = new SecurityResponse(se.getMessage()); 
     return response; 
    } 
} 

Werfen Sie die benutzerdefinierte Ausnahme basierend auf Ihrer Bedingung.

throw new SecurityException("Date time format is invalid"); 

Jetzt starten und testen Sie Ihre App. Z.B. :

enter image description here

Verwandte Themen