Usando Spring ResponseEntity para manipular a resposta HTTP

Usando Spring ResponseEntity para manipular a resposta HTTP

1. Introdução

Usando o Spring, geralmente temos várias maneiras de atingir o mesmo objetivo, incluindo o ajuste fino das respostas HTTP.

Neste breve tutorial, veremos como definir o corpo, o status e os cabeçalhos de uma resposta HTTP usandoResponseEntity.

Leitura adicional:

Obtendo e verificando dados de resposta com garantia REST

Veja como usar a garantia REST para validar e extrair a resposta de um terminal REST

Read more

Usando Spring @ResponseStatus para definir o código de status HTTP

Dê uma olhada na anotação @ResponseStatus e como usá-la para definir o código de status da resposta.

Read more

2. ResponseEntity

ResponseEntityrepresents the whole HTTP response: status code, headers, and body. Por isso, podemos usá-lo para configurar totalmente a resposta HTTP.

Se quisermos usá-lo, precisamos devolvê-lo do ponto final; A primavera cuida do resto.

ResponseEntity é um tipo genérico. Como resultado, podemos usar qualquer tipo como corpo de resposta:

@GetMapping("/hello")
ResponseEntity hello() {
    return new ResponseEntity<>("Hello World!", HttpStatus.OK);
}

Como especificamos o status da resposta programaticamente, podemos retornar com diferentes códigos de status para diferentes cenários:

@GetMapping("/age")
ResponseEntity age(
  @RequestParam("yearOfBirth") int yearOfBirth) {

    if (isInFuture(yearOfBirth)) {
        return new ResponseEntity<>(
          "Year of birth cannot be in the future",
          HttpStatus.BAD_REQUEST);
    }

    return new ResponseEntity<>(
      "Your age is " + calculateAge(yearOfBirth),
      HttpStatus.OK);
}

Além disso, podemos definir cabeçalhos HTTP:

@GetMapping("/customHeader")
ResponseEntity customHeader() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Custom-Header", "foo");

    return new ResponseEntity<>(
      "Custom header set", headers, HttpStatus.OK);
}

Além disso,ResponseEntityprovides two nested builder interfaces:HeadersBuilder e sua subinterface,BodyBuilder. Portanto, podemos acessar seus recursos por meio dos métodos estáticos deResponseEntity.

O caso mais simples é uma resposta com um corpo e um código de resposta HTTP 200:

@GetMapping("/hello")
ResponseEntity hello() {
    return ResponseEntity.ok("Hello World!");
}

Para os códigos de status HTTP mais populares, obtemos métodos estáticos:

BodyBuilder accepted();
BodyBuilder badRequest();
BodyBuilder created(java.net.URI location);
HeadersBuilder noContent();
HeadersBuilder notFound();
BodyBuilder ok();

Além disso, podemos usar os métodosBodyBuilder status(HttpStatus status)eBodyBuilder status(int status) para definir qualquer status HTTP.

Finalmente, comResponseEntity<T> BodyBuilder.body(T body), podemos definir o corpo da resposta HTTP:

@GetMapping("/age")
ResponseEntity age(@RequestParam("yearOfBirth") int yearOfBirth) {
    if (isInFuture(yearOfBirth)) {
        return ResponseEntity.badRequest()
            .body("Year of birth cannot be in the future");
    }

    return ResponseEntity.status(HttpStatus.OK)
        .body("Your age is " + calculateAge(yearOfBirth));
}

Também podemos definir cabeçalhos personalizados:

@GetMapping("/customHeader")
ResponseEntity customHeader() {
    return ResponseEntity.ok()
        .header("Custom-Header", "foo")
        .body("Custom header set");
}

Portanto,BodyBuilder.body() retorna umResponseEntity em vez deBodyBuilder,, deveria ser a última chamada.

Observe que comHeaderBuilder não podemos definir nenhuma propriedade do corpo da resposta.

Ao retornar o objetoResponseEntity<T> do controlador, podemos obter alguma exceção ou erro ao processar a solicitação e gostaríamos dereturn error-related information to the user represented as some other type let’s say E.

O Spring 3.2 traz suporte para um@ExceptionHandler with the new @ControllerAdvice annotation global que lida com esses tipos de cenários. Para obter detalhes aprofundados, consulte nosso artigo existentehere.

While ResponseEntity is very powerful, we shouldn’t overuse it. Em casos simples, existem outras opções que atendem às nossas necessidades e resultam em um código muito mais limpo.

3. Alternativas

3.1. @ResponseBody

Nos aplicativos clássicos do Spring MVC, os pontos de extremidade geralmente retornam páginas HTML renderizadas. Às vezes, precisamos apenas retornar os dados reais, por exemplo, quando usamos o terminal com o AJAX.

Nesses casos, podemos marcar o método do manipulador de solicitação com@ResponseBodyeSpring treats the result value of the method as the HTTP response body.

Para obter mais informações,this article is a good place to start.

3.2. @ResponseStatus

Quando um nó de extremidade retorna com êxito, o Spring fornece uma resposta HTTP 200 (OK). Se o nó de extremidade lança uma exceção, o Spring procura um manipulador de exceções que informe qual status HTTP usar.

Podemos marcar esses métodos com @ResponseStatus. Portanto Springreturns with a custom HTTP status.

Para mais exemplos, visite nosso artigo sobrecustom status codes.

3.3. Manipule a resposta diretamente

O Spring também nos permite acessar o objetojavax.servlet.http.HttpServletResponse diretamente; só temos que declará-lo como um argumento do método:

@GetMapping("/manual")
void manual(HttpServletResponse response) throws IOException {
    response.setHeader("Custom-Header", "foo");
    response.setStatus(200);
    response.getWriter().println("Hello World!");
}

Como o Spring fornece abstrações e recursos adicionais acima da implementação subjacente,we shouldn’t manipulate the response this way.

4. Conclusão

Neste artigo, vimos várias maneiras com seus benefícios e desvantagens de manipular a resposta HTTP no Spring.

Como de costume, os exemplos estão disponíveisover on GitHub.