Spring Boot Rest Controller Wie werden verschiedene HTTP-Statuscodes zurückgegeben?

101

Ich verwende Spring Boot für eine einfache REST-API und möchte einen korrekten HTTP-Statuscode zurückgeben, wenn etwas fehlschlägt.

@RequestMapping(value="/rawdata/", method = RequestMethod.PUT)
@ResponseBody
@ResponseStatus( HttpStatus.OK )
public RestModel create(@RequestBody String data) {
    // code ommitted..
    // how do i return a correct status code if something fails?
}

Da Spring und Spring Boot neu sind, lautet die grundlegende Frage: Wie kann ich verschiedene Statuscodes zurückgeben, wenn etwas in Ordnung ist oder fehlschlägt?

Marco
quelle

Antworten:

116

Es gibt verschiedene Optionen, die Sie verwenden können. Ein guter Weg ist es, Ausnahmen und Klassen für die Behandlung zu verwenden, die wie folgt heißen @ControllerAdvice:

@ControllerAdvice
class GlobalControllerExceptionHandler {
    @ResponseStatus(HttpStatus.CONFLICT)  // 409
    @ExceptionHandler(DataIntegrityViolationException.class)
    public void handleConflict() {
        // Nothing to do
    }
}

Sie können auch an HttpServletResponsedie Controller-Methode übergeben und einfach den Antwortcode festlegen:

public RestModel create(@RequestBody String data, HttpServletResponse response) {
    // response committed...
    response.setStatus(HttpServletResponse.SC_ACCEPTED);
}

Weitere Informationen finden Sie in diesem großartigen Blog-Beitrag: Ausnahmebehandlung in Spring MVC


HINWEIS

In Spring MVC ist die Verwendung von @ResponseBodyAnnotation redundant - sie ist bereits in @RestControllerAnnotation enthalten.

Jakub Kubrynski
quelle
Genau wie ein Kommentar habe ich vor 15 Minuten einen Test durchgeführt, und ein '@RestController' ohne die Annotation '@ResponseBody' über seiner Methode platzierte die zurückgegebene Zeichenfolge nicht innerhalb des Körpers, sondern als ForwardedURL. Ich bin ziemlich noob mit spring / springboot selbst, kann also nicht herausfinden warum
Anearion
@Anearion Die Antwort enthält einen Tippfehler - wir benötigen tatsächlich '@RestControllerAdvice', nicht '@RestController'.
Yoliho
Es ist kein Tippfehler. Dieser Teil bezieht sich auf die Frage und Anmerkungen auf einem Controller
Jakub Kubrynski
1
Beachten Sie, dass javax.servlet.http.HttpServletResponseanscheinend nicht alle StatusCodes vorhanden sind org.springframework.http.HttpStatus. Sie können also HttpStatus.UNPROCESSABLE_ENTITY.value()den int-Wert an response.setStatus übergeben. Auch dies funktioniert perfekt zur Fehlerbehandlung mit@ExceptionHandler .
Igor
42

Eine Möglichkeit, dies zu tun, besteht darin, ResponseEntity als Rückgabeobjekt zu verwenden.

@RequestMapping(value="/rawdata/", method = RequestMethod.PUT)

public ResponseEntity<?> create(@RequestBody String data) {

if(everything_fine)
    return new ResponseEntity<>(RestModel, HttpStatus.OK);
else
    return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);

}
Ankit Basarkar
quelle
3
In späteren Versionen von Spring muss die Null nicht mehr verwendet werden: new ResponseEntity <> (HttpStatus.NOT_FOUND)
Kong
4

Versuchen Sie diesen Code:

@RequestMapping(value = "/validate", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<ErrorBean> validateUser(@QueryParam("jsonInput") final String jsonInput) {
    int numberHTTPDesired = 400;
    ErrorBean responseBean = new ErrorBean();
    responseBean.setError("ERROR");
    responseBean.setMensaje("Error in validation!");

    return new ResponseEntity<ErrorBean>(responseBean, HttpStatus.valueOf(numberHTTPDesired));
}
Rodrigo Hernandez
quelle
Da dies eine ziemlich alte Frage ist, sollten Sie Paket- und Versionsinformationen hinzufügen, auf die Sie sich beziehen.
ZF007
Können Sie eine Beispielimplementierung von einfügen ErrorBean?
Brent Bradburn
2

Wenn Sie einen benutzerdefinierten Statuscode zurückgeben möchten, können Sie die ResponseEntity wie folgt verwenden:

@RequestMapping(value="/rawdata/", method = RequestMethod.PUT)
public ResponseEntity<?> create(@RequestBody String data) {
    int customHttpStatusValue = 499;
    Foo foo = bar();
    return ResponseEntity.status(customHttpStatusValue).body(foo);
}

Der CustomHttpStatusValue kann eine beliebige Ganzzahl innerhalb oder außerhalb der Standard-HTTP-Statuscodes sein.

Vedant Goenka
quelle
Ich mag diesen fließenden API-Ansatz.
v.ladynev
2

Eine gute Möglichkeit ist die Verwendung der ResponseStatusException von Spring

Anstatt ein ResponseEntityoder ähnliches zurückzugeben, werfen Sie das einfach ResponseStatusExceptionvom Controller mit einem HttpStatusund Ursache, zum Beispiel:

throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Cause description here");

oder:

throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Cause description here");

Dies führt zu einer Antwort an den Client, die den HTTP-Status enthält (z. B. 400 Bad Request), mit einem Text wie:

{
  "timestamp": "2020-07-09T04:43:04.695+0000",
  "status": 400,
  "error": "Bad Request",
  "message": "Cause description here",
  "path": "/test-api/v1/search"
}
Kontinuität8
quelle