我们梳理一下 Spring Boot 项目中是如何对 HTTP 请求的响应体 (Response Body) 进行压缩。
(请注意:压缩是针对服务器返回给客户端的响应体,而不是客户端发给服务器的请求 URL 或请求体)。
核心思想:减少网络传输的数据量,加快客户端加载速度。
Spring Boot 默认开启了对常见文本类型(如 JSON, HTML, CSS, JS)的响应体压缩(Gzip),通常我们不需要做任何配置!只需要确保:
Content-Type
是默认支持压缩的类型之一 (如 application/json
)。Accept-Encoding: gzip
(目前浏览器和工具默认都会加)。下面是详细的解释和配置方法:
压缩过程是由客户端和服务器自动协商完成的,对Controller 代码透明:
Accept-Encoding
字段,告知服务器它支持哪些压缩算法。 GET /api/data HTTP/1.1
Host: example.com
Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Encoding
中包含服务器支持的算法(如 gzip
)。Content-Type
在配置的 mime-types
列表中。min-response-size
。Content-Encoding
字段,告知客户端使用了何种算法。Content-Length
变为压缩后的大小。 HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: gzip
Content-Length: 850 // <- 压缩后的大小 (例如原始大小是 3KB)
...
[压缩后的二进制数据]
Content-Encoding: gzip
后,自动对收到的响应体进行解压,再处理原始数据。你可以在 application.properties
或 application.yml
中进行配置和微调。
使用 application.properties
:
# 1. 启用响应压缩 ( ⭐ 默认值: true )
# 如果你确定前端有反向代理(如 Nginx)在做压缩,可以在这里设为 false,避免重复压缩。
server.compression.enabled=true
# 2. 配置需要压缩的内容类型 MIME types ( ⭐ 默认值已包含常见类型)
# 只有 Content-Type 匹配这里的列表,才会被考虑压缩。
# 默认值包括: text/html, text/xml, text/plain, text/css, text/javascript,
# application/javascript, application/json, application/xml 等等。
# 注意:不要添加已经压缩过的类型,如 image/jpeg, image/png, application/zip 等,重复压缩浪费 CPU 且效果差。
server.compression.mime-types=application/json,application/xml,text/html,text/plain,application/javascript,text/css
# 3. 触发压缩的最小响应体大小 ( ⭐ 默认值: 2048 bytes,即 2KB )
# 如果响应体小于此值,即使满足其他条件也不会压缩。
# 因为对小数据进行压缩的 CPU 开销可能大于节省的带宽,得不偿失。
# 单位是字节。
server.compression.min-response-size=1024 # 例如,改为 1KB
# (可选) 排除某些 User-Agent
# server.compression.excluded-user-agents=some-bad-client
使用 application.yml
:
server:
compression:
enabled: true # 默认 true
mime-types: # 默认包含常见类型
- application/json
- application/xml
- text/html
- text/plain
- application/javascript
- text/css
min-response-size: 1024 # 默认 2048 bytes
你的 Controller 代码无需做任何修改!Spring Boot / 内嵌服务器会自动处理。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@RestController
public class MyController {
// 模拟一个返回较大数据,用于测试 GET 请求的响应压缩
@GetMapping("/api/users")
public List<String> getUsers() {
// 生成一个较大的列表,确保 JSON 序列化后大小超过 server.compression.min-response-size
return IntStream.range(0, 1000)
.mapToObj(i -> "User Name - " + i + " with some description text here.")
.collect(Collectors.toList());
}
// 模拟一个 POST 请求,它的响应体同样会被压缩
@PostMapping("/api/users/filter")
public List<String> filterUsers(@RequestBody String filter) {
// 假设过滤后仍然返回一个大数据
return IntStream.range(0, 800)
.mapToObj(i -> "Filtered User Name - " + i + " for filter " + filter)
.collect(Collectors.toList());
}
}
当客户端(带上Accept-Encoding: gzip
)请求 /api/users
或 /api/users/filter
时,如果返回的 JSON 大小超过了 min-response-size
,Spring Boot 就会自动返回 Content-Encoding: gzip
的压缩响应。
使用浏览器的开发者工具 (F12) -> 网络 (Network) 面板:
Content-Encoding: gzip
(或 br
, deflate
),则表示压缩成功。或者使用 curl
命令:
# -v 显示详细信息(包含头)
# --compressed 告诉 curl 自动请求并解压 (它会自动加上 Accept-Encoding: gzip, deflate 并根据 Content-Encoding 解压)
# -o /dev/null 不输出内容到屏幕
curl -v --compressed http://localhost:8080/api/users -o /dev/null
在 curl 的输出中查找 Response Headers 是否包含 Content-Encoding: gzip
。
server.compression.enabled=false
),以避免重复压缩和减轻应用服务器的 CPU 负担。mime-types
里不包含图片 (jpg, png, gif)、视频、zip 包等,它们本身就是压缩格式,再次压缩基本无效甚至可能增大体积,且浪费 CPU。StreamingResponseBody
或 WebFlux 的 Flux
),压缩机制依然有效,但实现方式略有不同(边生成边压缩边发送)。总的来说,Spring Boot 提供了开箱即用的响应体压缩功能,通过简单的 server.compression.*
属性即可配置,无需修改业务代码。