背景
在 WebGIS 应用中,GeoJSON 数据通常包含大量坐标点和几何形状,传输体积较大。以行政区划数据为例,西藏范围的数据可能达到 14MB,直接影响地图加载速度和用户体验。针对这一问题,在 SpringBoot 中开启 Gzip 压缩是降低带宽占用、提升性能的有效手段。
GZIP 压缩知识简介
GZIP 是一种基于 LZ77 算法和 Huffman 编码结合的数据压缩格式,主要用于网络传输和本地存储。
什么是 Gzip
LZ77 算法通过滑动窗口查找重复字节序列,用指针替代;Huffman 编码则根据字符频率分配长短不一的编码。Gzip 文件结构包含文件头、压缩数据块(DEFLATE 算法)和文件尾(CRC32 校验)。
Gzip 特点
- 无损压缩:解压后可完全还原。
- 高效压缩率:文本文件(HTML/JSON/XML)通常在 50%-90%。
- 广泛支持:现代浏览器和服务器均支持
Accept-Encoding: gzip。 - 适用场景:适合文本类数据,对已压缩图片效果不明显。
Gzip 在 GIS 方面的应用
地理数据传输、服务器端优化(如 Nginx)、前端构建优化及数据存储均可应用 Gzip。它能显著减少 GeoJSON 体积,加快地图加载。
SpringBoot 中开启 Gzip 的方式
在 SpringBoot 中,主要有全局配置和局部编程两种实现方式。
全局配置方式
适用于大多数需要统一压缩的场景。在 application.yml 中添加如下配置即可对整个应用的 HTTP 响应启用 GZIP:
server:
compression:
enabled: true
mime-types: application/json
min-response-size: 1KB
或在 application.properties 中:
server.compression.enabled=true
server.compression.mime-types=application/json
server.compression.min-response-size=1024
注意:该配置会对所有返回 application/json 的接口生效。
局部约定配置
若只想对特定接口生效,可通过自定义 Filter 精确控制路径。
实现原理
基于自定义 Filter 拦截请求,匹配指定路径后手动设置响应头并包装输出流进行压缩。
具体代码实现
创建一个过滤器,关键代码如下:
package com.yelang.framework.interceptor.gzip;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpServletResponseWrapper;
java.io.IOException;
java.util.Arrays;
java.util.List;
java.util.zip.GZIPOutputStream;
{
();
List<String> gzipPatterns = Arrays.asList(
,
);
IOException, ServletException {
(HttpServletRequest) request;
req.getRequestURI();
req.getContextPath();
requestUri.substring(contextPath.length());
gzipPatterns.stream()
.anyMatch(pattern -> pathMatcher.match(pattern, relativePath));
(match) {
(HttpServletResponse) response;
res.setHeader(, );
res.setHeader(, );
(res);
chain.doFilter(request, gzipResponse);
gzipResponse.finish();
} {
chain.doFilter(request, response);
}
}
{
GZIPOutputStream gzipOutputStream;
IOException {
(response);
gzipOutputStream = (response.getOutputStream());
}
ServletOutputStream {
() {
IOException {
gzipOutputStream.write(b);
}
{ ; }
{
();
}
};
}
IOException {
gzipOutputStream.finish();
}
}
}


