2014-10-07 4 views
8

Wie kann ich den Antwortstatuscode und die Daten im Antworthauptteil anpassen, wenn eine Ausnahme in einer Spring Boot-Webanwendung auftritt?Spring Boot anpassen HTTP-Fehlerreaktion?

Ich habe eine Webanwendung erstellt, die eine benutzerdefinierte Ausnahme auslöst, wenn aufgrund eines schlechten internen Status etwas unerwartetes auftritt. Folglich wird der Antworttext des Antrags, der den Fehler ausgelöst sieht ungefähr so ​​aus:

HTTP/1.1 500 Internal Server Error 
{ 
    "timestamp": 1412685688268, 
    "status": 500, 
    "error": "Internal Server Error", 
    "exception": "com.example.CustomException", 
    "message": null, 
    "path": "/example" 
} 

Nun, ich möchte den Statuscode ändern und die Felder im Antworttext festgelegt. Eine Lösung, die meinen Kopf gegangen war so etwas wie:

@ControllerAdvice 
class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { 

    @ExceptionHandler 
    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ResponseBody 
    ErrorMessage handleBadCredentials(CustomException e) { 
     return new ErrorMessage("Bad things happened"); 
    } 
} 

@XmlRootElement 
public class ErrorMessage(
    private String error; 

    public ErrorMessage() { 
    } 

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

    public String getError() { 
     return error; 
    } 

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

jedoch, dass erstellt (wie vermutet) eine ganz andere Antwort:

HTTP/1.1 400 Bad Request 
{ 
    "error": "Bad things happened" 
} 
+2

Also beide Sie tun und nicht wollen, eine eigene Antwort? – zeroflagL

+0

@zeroflag Vorzugsweise möchte ich die Antwort, die von Spring Boot (wenn möglich) generiert wird, anpassen. Das Implementieren einer vollständigen benutzerdefinierten Lösung (wie der in der Frage bereitgestellten) funktioniert, ist jedoch zwischen verschiedenen Projekten weniger wiederverwendbar. – matsev

+1

Es liegt ganz bei Ihnen, ob die benutzerdefinierte Lösung wiederverwendbar ist oder nicht. FWIW: Der Resposne-Body wird von 'DefaultErrorAttributes # getErrorAttributes' zusammengestellt. Sie können diese Klasse in Ihren 'CustomResponseEntityExceptionHandler' injizieren. – zeroflagL

Antwort

7

der HTTP-Antwort-Statuscode kann unter Verwendung des HttpServletResponse.sendError(int) Verfahrens geändert werden , z.B

@ExceptionHandler 
void handleIllegalArgumentException(IllegalArgumentException e, HttpServletResponse response) throws IOException { 
    response.sendError(HttpStatus.BAD_REQUEST.value()); 
} 

Alternativ können Sie auch den Ausnahmetyp in der @ExceptionHandler Anmerkung erklären, wenn Sie zwei oder mehr Ausnahmen die gleiche Antwort Status zu generieren:

@ExceptionHandler({IllegalArgumentException.class, NullPointerException.class}) 
void handleBadRequests(HttpServletResponse response) throws IOException { 
    response.sendError(HttpStatus.BAD_REQUEST.value()); 
} 

Weitere Informationen finden Sie in meinem blog post finden.

5

Da @zeroflagL bereits erwähnt wurde, fertigt Spring Boot das "Standard" -Error Response Body in org.springframework.boot.autoconfigure.web.DefaultErrorAttributes. Ähnlich wie bei Ihren Bedürfnissen wollte ich all das nutzen, aber einfach ein "Typ" -Feld erweitern, das von einigen meiner Ausnahmen bereitgestellt wurde.

Ich habe das durch die Implementierung einer Component, dass Unterklasse DefaultErrorAttributes. Spring Boot hat es automatisch aufgenommen und statt der Standardeinstellungen meine verwendet.

@Component 
public class ExtendedErrorAttributes extends DefaultErrorAttributes { 
    @Override 
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { 
     final Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace); 

     final Throwable error = super.getError(requestAttributes); 
     if (error instanceof TypeProvider) { 
      final TypeProvider typeProvider = (TypeProvider) error; 
      errorAttributes.put("type", typeProvider.getTypeIdentifier()); 
     } 

     return errorAttributes; 
    } 
} 

Damit erhalte ich eine Augmented-JSON-Antwort Körper, wie

{ 
    "timestamp": 1488058582764, 
    "status": 429, 
    "error": "Too Many Requests", 
    "exception": "com.example.ExternalRateLimitException", 
    "message": "DAILY_LIMIT: too many requests", 
    "path": "/api/lookup", 
    "type": "DAILY_LIMIT" 
} 
+0

Große Antwort! Kann auch einfach so geändert werden, dass das Attribut 'exception' aus der Fehlerreaktion in Produktionsbereitstellungen entfernt wird, wenn Sie nicht an solchen Details interessiert sind. – Andrew