ResponseEntity
ResponseEntity 类似于 @ResponseBody,但它允许你同时指定响应状态码和响应标头。
使用示例
java
@GetMapping("/something")
public ResponseEntity<String> handle() {
String body = "Hello World";
String etag = "v1-12345";
return ResponseEntity.ok()
.eTag(etag) // 设置 ETag 标头用于缓存
.header("Custom-Header", "value")
.body(body);
}kotlin
@GetMapping("/something")
fun handle(): ResponseEntity<String> {
val body = "Hello World"
val etag = "v1-12345"
return ResponseEntity.ok()
.eTag(etag)
.header("Custom-Header", "value")
.body(body)
}异步响应
Spring MVC 支持使用响应式类型来产生 ResponseEntity:
ResponseEntity<Mono<T>>:立即返回状态和标头,主体数据在未来(异步)产生。Mono<ResponseEntity<T>>:状态、标头和主体都将在未来产生,这允许状态码根据业务逻辑结果(如查到还是没查到)动态改变。
补充教学
1. 语义化响应的艺术
在 RESTful 设计中,状态码非常重要。
- 创建资源:返回
201 Created,并带上LocationHeader 指向新资源。 - 条件更新:返回
304 Not Modified配合 ETag 节省带宽。 - 业务错误:返回
422 Unprocessable Entity而不是通用的500。ResponseEntity是唯一能让你优雅地表达这些细节的工具。
2. 静态方法 vs 建造者模式
ResponseEntity 提供了两种风格:
- 静态方法快捷方式:
ResponseEntity.ok(data)。 - Fluent API:
ResponseEntity.status(403).build()。 推荐:对于简单的成功返回,用快捷方式;需要精细控制标头时,用 Fluent API。
3. ResponseEntity<Resource> 与文件描述
在处理文件下载时,你通常需要告诉浏览器这是个附件:
java
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"report.pdf\"")
.body(pdfResource);这能确保用户点击链接时弹出“保存”对话框,而不是直接在网页上乱码显示。