查看原文
其他

使用 Spring Boot + Filter 实现 Gzip 压缩超大 JSON 对象,传输耗时大大减少

编程疏影 路条编程
2024-09-05


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 说明数据确实被压缩了。

为了进一步优化性能,可以考虑以下几点:

  1. 使用异步请求处理,进一步减少服务器阻塞时间。

  2. 优化前端展示,避免一次性渲染超大数据。

总结

通过本文,我们详细讲解了如何在 Spring Boot 项目中通过 Filter 实现 Gzip 压缩,结合 Thymeleaf、JavaScript 和 Bootstrap 提高超大 JSON 对象的传输效率。合理地使用 Gzip 可以显著降低网络传输时间,提高用户体验,但也需要根据具体场景权衡压缩成本与传输收益。


今天就讲到这里,如果有问题需要咨询,大家可以直接留言或扫下方二维码来知识星球找我,我们会尽力为你解答。


AI资源聚合站已经正式上线,该平台不仅仅是一个AI资源聚合站,更是一个为追求知识深度和广度的人们打造的智慧聚集地。通过访问 AI 资源聚合网站 https://ai-ziyuan.techwisdom.cn/,你将进入一个全方位涵盖人工智能和语言模型领域的宝藏库。


作者:路条编程(转载请获本公众号授权,并注明作者与出处)
继续滑动看下一个
路条编程
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存