使用 Spring Boot + Filter 实现 Gzip 压缩超大 JSON 对象,传输耗时大大减少
Spring Boot + Filter 实现 Gzip 压缩超大 JSON 对象,传输耗时大大减少
在现代 Web 应用中,JSON 是前后端数据交互的重要格式。然而,随着数据量的增加,JSON 对象的体积可能会变得非常大,导致网络传输的效率大幅降低。为了优化传输速度,我们可以通过 Gzip 压缩超大的 JSON 对象来减少传输时间。在本文中,我们将结合 Spring Boot、Filter、Thymeleaf 模板、JavaScript 和 Bootstrap,详细讲解如何实现 Gzip 压缩并提高数据传输效率。
项目配置
首先,我们需要在 pom.xml
中添加必要的依赖:
pom.xml
配置
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Thymeleaf 模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
application.yaml
配置
server:
port: 8080
compression:
enabled: true
min-response-size: 1024 # 启用压缩的最小响应大小,单位为字节
mime-types: application/json,application/xml,text/html,text/xml,text/plain
后端实现
在后端,我们将通过创建一个自定义的 GzipFilter
来实现 Gzip 压缩。
创建 GzipFilter
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
public class GzipFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 检查客户端是否支持 Gzip
if (isGzipSupported(httpRequest)) {
GzipResponseWrapper gzipResponseWrapper = new GzipResponseWrapper(httpResponse);
chain.doFilter(request, gzipResponseWrapper);
gzipResponseWrapper.close();
} else {
chain.doFilter(request, response);
}
}
private boolean isGzipSupported(HttpServletRequest request) {
String acceptEncoding = request.getHeader("Accept-Encoding");
return acceptEncoding != null && acceptEncoding.contains("gzip");
}
@Override
public void destroy() {
// 释放资源
}
}
创建 GzipResponseWrapper
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;
public class GzipResponseWrapper extends HttpServletResponseWrapper {
private GZIPOutputStream gzipOutputStream;
private ServletOutputStream outputStream;
public GzipResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
outputStream = new GzipServletOutputStream(response.getOutputStream());
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return outputStream;
}
@Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(new OutputStreamWriter(getOutputStream(), getCharacterEncoding()));
}
@Override
public void setContentLength(int len) {
// 禁止设置内容长度
}
@Override
public void setContentLengthLong(long len) {
// 禁止设置内容长度
}
public void close() throws IOException {
if (gzipOutputStream != null) {
gzipOutputStream.finish();
}
}
}
配置 GzipFilter
在 Spring Boot
中,通过 Java 配置类或直接在 application.yaml
中配置过滤器。
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<GzipFilter> gzipFilter() {
FilterRegistrationBean<GzipFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new GzipFilter());
registrationBean.addUrlPatterns("/api/*"); // 仅对 /api/ 下面的请求应用 Gzip 压缩
return registrationBean;
}
}
前端实现
在前端,我们将使用 Thymeleaf 模板引擎来生成 HTML 页面,并通过 JavaScript 发送 HTTP 请求。
Thymeleaf 模板
创建一个 index.html
文件,展示如何使用 Thymeleaf 与 Bootstrap 结合。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Gzip Compression Example</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
</head>
<body>
<div class="container">
<h1>Gzip Compression Example</h1>
<button id="loadData" class="btn btn-primary">加载大 JSON</button>
<div id="result" class="mt-3"></div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function () {
$('#loadData').click(function () {
$.ajax({
url: '/api/large-json',
method: 'GET',
success: function (data) {
$('#result').html('<pre>' + JSON.stringify(data, null, 2) + '</pre>');
}
});
});
});
</script>
</body>
</html>
后端控制器
java
复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class ApiController {
@GetMapping("/api/large-json")
public Map<String, Object> getLargeJson() {
// 模拟生成一个超大的 JSON 对象
Map<String, Object> data = new HashMap<>();
for (int i = 0; i < 10000; i++) {
data.put("key" + i, "value" + i);
}
return data;
}
}
测试与优化
在完成上述配置后,我们可以启动 Spring Boot 应用,并访问 http://localhost:8080
。点击按钮后,前端将请求一个超大的 JSON 数据,并通过 Gzip 压缩进行传输。使用浏览器开发者工具,可以查看请求的响应头,确认 Content-Encoding: gzip
说明数据确实被压缩了。
为了进一步优化性能,可以考虑以下几点:
使用异步请求处理,进一步减少服务器阻塞时间。
优化前端展示,避免一次性渲染超大数据。
总结
通过本文,我们详细讲解了如何在 Spring Boot 项目中通过 Filter 实现 Gzip 压缩,结合 Thymeleaf、JavaScript 和 Bootstrap 提高超大 JSON 对象的传输效率。合理地使用 Gzip 可以显著降低网络传输时间,提高用户体验,但也需要根据具体场景权衡压缩成本与传输收益。