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

原创 编程疏影 路条编程 2024年08月23日 08:01 河北

图片

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 可以显著降低网络传输时间,提高用户体验,但也需要根据具体场景权衡压缩成本与传输收益。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值