The ResponseEntity object is Spring’s wrapper around the request response. It inherits from the HttpEntity object and contains the Http response code (httpstatus), the response header (header), and the response body (body). A Spring MVC interface to get user information usually we return the entity directly (with @RestController).

1
2
3
4
5
6
@GetMapping("/user")
public User userinfo() {
    User user = new User();
    user.setUsername("felord.cn");
    return user;
}

is equivalent to using ResponseEntity as the return value of the controller.

1
2
3
4
5
6
    @GetMapping("/userinfo")
    public ResponseEntity<User> user() {
        User user = new User();
        user.setUsername("felord.cn");
        return ResponseEntity.ok(user);
    }

But we can do much more when using ResponseEntity.

Customizing the response code

The ResponseEntity.ok above already contains the return 200 Http response code, we can also customize the return response code with ResponseEntity.status(HttpStatus|int).

Customizing the response body

The response body that places the response is usually the data of our interface, here is an example.

1
2
ResponseEntity.status(HttpStatus.OK)
               .body(Object)

Response headers

Typically we specify the response headers for the Spring MVC interface by setting the header(), consumes, produces() attributes in the @RequestMapping and its Restful family of annotations. If you are using ResponseEntity, you can set it via a chain call.

1
2
3
4
5
6
ResponseEntity.status(HttpStatus.OK)
               .allow(HttpMethod.GET)
               .contentType(MediaType.APPLICATION_JSON)
               .contentLength(1048576)
               .header("My-Header","felord.cn")
               .build();

All standard request headers have their corresponding setting methods, you can also set custom request headers with header(String headerName, String... headerValues) to set a custom request header.

General principles

Let’s look at an abstract interface for handling return values of Spring MVC controller interfaces HandlerMethodReturnValueHandler .

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public interface HandlerMethodReturnValueHandler {

    /**
     * 支持的返回值类型
     */
    boolean supportsReturnType(MethodParameter returnType);

    /**
     *  将数据绑定到视图,并设置处理标志以指示已直接处理响应,后续的其它方法就不处理了,优先级非常高
     */
    void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;

}

One of its key implementations, HttpEntityMethodProcessor, is the processor that handles controller methods that return a type of HttpEntity. It will give the three kinds of information carried by ResponseEntity to the ServletServerHttpResponse object to render the view and set the processing flag to indicate that the response has been processed directly, and other subsequent methods will not be processed, with a very high priority.

Practical use

Usually you write a download file interface is to get the HttpServletResponse object, and then configure the Content-Type to write a stream inside. If you use ResponseEntity will be more simple and elegant.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@GetMapping("/download")
public ResponseEntity<Resource> load() {
    ClassPathResource classPathResource = new ClassPathResource("application.yml");
    String filename = classPathResource.getFilename();
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentDisposition(ContentDisposition.inline().filename(filename, StandardCharsets.UTF_8).build());
    return ResponseEntity.ok()
            .headers(httpHeaders)
            .body(classPathResource);
}

Above is an example of downloading the Spring Boot configuration file application.yml. There are three main steps.

  • Wrap the file to be downloaded into an org.springframework.core.io.Resource object, which has a number of implementations. Here we use ClassPathResource, other InputStreamResource, PathResource are common implementations.
  • Then configure the download file request header Content-Disposition. It has two modes for downloading: inline means show the file content directly in the browser; attachment means download as a file. Please don’t forget the file extension, e.g. application.yml here. If you don’t specify Content-Disposition, you’ll need to set the corresponding Content-Type according to the file extension, which can be a bit tricky.
  • Finally, the ResponseEntity<Resource> is assembled and returned.

The above interface corresponds to the following effect.

spring

See org.springframework.http.converter.ResourceHttpMessageConverter for the principle

Summary

Today we have shared the role and mechanism of ResponseEntity in Spring and also shared an alternative way to download files. Interested to see the source code implementation.

Reference https://felord.cn/responseEntity.html