ResponseEntity
ResponseEntity对象是Spring对请求响应的封装。它继承了HttpEntity对象,包含了Http的响应码(httpstatus)、响应头(header)、响应体(body)三个部分。一个获取用户信息的Spring MVC接口通常直接返回实体即可(配合@RestController):
@GetMapping("/user")public User userinfo() {User user = new User();user.setUsername("fcant.cn");return user;}
等同于使用ResponseEntity作为控制器接口的返回值:
@GetMapping("/userinfo")public ResponseEntity<User> user() {User user = new User();user.setUsername("fcant.cn");return ResponseEntity.ok(user);}
自定义响应码
上面的ResponseEntity.ok已经包含了返回200Http响应码,还可以通过ResponseEntity.status(HttpStatus|int)来自定义返回的响应码。
自定义响应体
放置响应的响应体,通常就是接口的数据,这里是一个例子:
ResponseEntity.status(HttpStatus.OK).body(Object)
响应头
通常指定Spring MVC接口的响应头是通过@RequestMapping和其Restful系列注解中的header()、consumes、produces()这几个属性设置。如果使用了ResponseEntity,可以通过链式调用来设置:
ResponseEntity.status(HttpStatus.OK).allow(HttpMethod.GET).contentType(MediaType.APPLICATION_JSON).contentLength(1048576).header("My-Header","fcant.cn").build();
所有的标准请求头都有对应的设置方法,也可以通过header(String headerName, String... headerValues)设置自定义请求头。
大致原理
来看一个用来处理Spring MVC控制器接口返回值的抽象接口HandlerMethodReturnValueHandler:
public interface HandlerMethodReturnValueHandler {/*** 支持的返回值类型*/boolean supportsReturnType(MethodParameter returnType);/*** 将数据绑定到视图,并设置处理标志以指示已直接处理响应,后续的其它方法就不处理了,优先级非常高*/void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;}
它的一个重要实现HttpEntityMethodProcessor就是处理返回类型为HttpEntity的控制器方法的处理器。它会把ResponseEntity携带的三种信息交给ServletServerHttpResponse对象渲染视图,并设置处理标志以指示已直接处理响应,后续的其它方法就不处理了,优先级非常高。
实战运用
通常让写个下载文件接口都是拿到HttpServletResponse对象,然后配置好Content-Type往里面写流。如果用ResponseEntity会更加简单优雅。
@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);}
上面是一个把Spring Boot配置文件 application.yml下载下来的例子。主要分为三步:
- 将要下载的文件封装成
org.springframework.core.io.Resource对象,它有很多实现。这里用了ClassPathResource,其它InputStreamResource、PathResource都是常用的实现。 - 然后配置下载文件请求头
Content-Disposition。针对下载它有两种模式:inline表示在浏览器直接展示文件内容;attachment表示下载为文件。另外下载后的文件名也在这里指定,请不要忘记文件扩展名,例如这里application.yml。如果不指定Content-Disposition,需要根据文件扩展名设置对应的Content-Type,会麻烦一些。 - 最后是组装
ResponseEntity<Resource>返回。
原理参见org.springframework.http.converter.ResourceHttpMessageConverterinline模式下载文件对应的可以显示文件的内容。
