目录

前言

一、GZIP压缩知识简介

1、什么是Gzip

2、Gzip特点

3、Gzip在GIS方面的应用

二、SpringBoot中开启Gzip的方式

1、在SpringBoot中开启Gzip的知识简介

2、SpringBoot中GeoJSON的实例

三、全局开启Gzip实现

1、实现原理

2、实现效果

四、局部约定配置

1、实现原理

2、具体代码实现

五、总结


前言

        在当今数字化时代,随着互联网应用的飞速发展,数据传输的效率和性能成为了至关重要的问题。GeoJSON 是一种基于 JSON 格式的地理空间数据交换格式,它广泛应用于地理信息系统(GIS)领域,用于描述地理空间数据的几何形状、属性等信息。GeoJSON 数据通常包含大量的地理坐标点、几何形状等信息,数据量往往较大。在 Web 地理信息系统应用中,如地图展示、地理数据可视化等场景,GeoJSON 数据的传输效率直接关系到地图加载的速度和用户体验。因此,对 GeoJSON 数据进行有效的压缩,以减少数据传输的体积,显得尤为重要。对于基于SpringBoot 框架构建的 WebGIS 应用来说,如何高效地传输数据、减少网络带宽的占用,是提升用户体验和系统性能的关键所在。而 Gzip 压缩技术,作为一种被广泛采用的解决方案,无疑为这一问题的解决提供了强大的助力。

        以 GeoJSON 数据为例,通过在 SpringBoot 应用中开启 Gzip 压缩,对 GeoJSON 数据进行瘦身,不仅可以显著减少数据传输的体积,提高地图加载的速度,还可以提升用户的交互体验。在实际的 Web 地理信息系统开发中,这种优化手段是非常实用和有效的。通过对 GeoJSON 数据的压缩处理,我们可以更好地满足用户对于地图快速加载和流畅交互的需求,同时也为整个应用的性能优化提供了有力的支持。

        在接下来的内容中,我们将详细介绍在 SpringBoot 中开启 Gzip 压缩的两种方式的具体实现步骤,并通过实际的 GeoJSON 数据压缩案例,展示这两种方式的应用效果和优缺点。希望通过本文的介绍,能够帮助读者更好地理解和掌握在 SpringBoot 应用中使用 Gzip 压缩技术的方法,从而提升自己开发的 WebGIS 应用的性能和用户体验。

一、GZIP压缩知识简介

        GZIP 是一种数据压缩格式,只能用于压缩单个文件。它可用于网络文件传输时的压缩,例如 nginx 中的 ngx_http_gzip_module,启用压缩功能后可以节约带宽;也可用于本地文件存储时的压缩。本节将重点对Gzip进行一个简单的介绍,让大家对Gzip的相关知识有一个简单的了解。

1、什么是Gzip

        Gzip 的压缩算法基于 LZ77 算法Huffman 编码 的结合。具体过程如下:

        LZ77 算法:LZ77 算法通过查找和替换重复的字节序列来压缩数据。它维护一个滑动窗口,在窗口内查找匹配的字符串,然后使用指针来替代这些重复的字符串。例如,对于字符串 "http://jiurl.yeah.nethttp://jiurl.nease.net",LZ77 算法会将其压缩为 "http://jiurl.yeah.net(22,13)nease(23,4)",其中 (22,13) 表示距离当前位置 22 个字符处的 13 个字符与当前位置的字符相同。

        Huffman 编码:Huffman 编码是一种基于字符频率的编码方法。它为出现频率高的字符分配较短的编码,为出现频率低的字符分配较长的编码,从而达到压缩的目的。在 Gzip 中,LZ77 算法的输出结果会进一步通过 Huffman 编码进行压缩。

        Gzip 文件结构:Gzip 文件包含文件头、压缩数据块和文件尾。文件头存储文件的元数据,如压缩方法、时间戳等;压缩数据块是使用 DEFLATE 算法压缩后的数据;文件尾存储校验和(CRC32)和原始文件大小,以确保文件的完整性

2、Gzip特点

        无损压缩:Gzip 是一种无损压缩算法,数据在解压缩后可以完全还原,没有任何损失。

        高效的压缩率:对于文本文件(如 HTML、JSON、XML),Gzip 的压缩率通常在 50%-90% 之间。它通过查找重复的字符串并用较短的指针替代,以及根据字符频率进行编码,从而实现高效压缩。

        广泛支持:Gzip 被几乎所有现代浏览器、服务器和编程语言支持。在 HTTP 传输中,服务器可以根据浏览器的请求头(如 Accept-Encoding: gzip)来判断是否使用 Gzip 压缩响应内容。

        压缩和解压速度较快:Gzip 的压缩和解压速度相对较快,尤其是解压过程,因为解压时只需根据指针和编码还原数据,计算量相对较小。

        适用于特定文件类型:Gzip 对文本文件的压缩效果较好,但对于已经压缩过的文件(如图片、音乐、视频)效果不明显,甚至可能导致文件变大

3、Gzip在GIS方面的应用

        地理数据传输:在 GIS 应用中,地理数据(如 GeoJSON 文件)通常包含大量的坐标点和几何形状信息,数据量较大。使用 Gzip 压缩可以显著减少数据传输的体积,加快地图加载速度,提升用户体验。

        服务器端优化:在服务器端,可以配置 Web 服务器(如 Nginx)开启 Gzip 压缩功能。当客户端请求地理数据时,服务器会自动对响应内容进行压缩,减少网络带宽的占用。

        前端性能优化:在前端开发中,可以通过工具(如 Webpack 的 Compression-webpack-plugin 插件)在构建过程中对地理数据文件进行 Gzip 压缩,然后在服务器上直接提供压缩后的文件,减少服务器的实时压缩负载。

        数据存储优化:对于存储在服务器上的地理数据文件,使用 Gzip 压缩可以节省存储空间。在需要读取数据时,再进行解压处理。

        总之,Gzip 压缩技术在 GIS 领域的应用,不仅可以提高数据传输效率,还可以优化服务器性能和存储空间,是提升 GIS 应用性能的重要手段之一。

二、SpringBoot中开启Gzip的方式

        SpringBoot 是一个非常流行的 Java 基于 Spring 框架的快速开发框架,它极大地简化了 Spring 应用的开发过程。在 SpringBoot 应用中,通过合理的配置和编程,可以很方便地集成 Gzip 压缩功能,从而实现对响应数据的自动压缩。这不仅可以提高数据传输的效率,还可以减轻服务器的负载,提升整个应用的性能。本节将重点介绍在SpringBoot中关于Gzip的相关知识以及在SpringBoot中GeoJSON的一些实践案例。      

1、在SpringBoot中开启Gzip的知识简介

        在 SpringBoot 中,开启 Gzip 压缩主要有两种方式:一种是通过配置文件进行全局配置,另一种是通过编程的方式在特定的控制器或方法上进行局部配置。这两种方式各有优缺点,适用于不同的应用场景。

        全局配置方式 :通过在 SpringBoot 的配置文件(如 application.yml 或 application.properties)中添加相关的 Gzip 压缩配置,可以实现对整个应用的 HTTP 响应进行统一的压缩处理。这种方式简单方便,适用于大多数需要压缩的场景,但缺乏对特定数据类型的针对性处理。

        局部配置方式 :通过在控制器或方法上添加自定义的注解或逻辑,可以实现对特定数据类型的压缩处理。这种方式更加灵活,可以根据不同的数据类型和业务需求,定制不同的压缩策略,但相对来说实现起来较为复杂,需要更多的编程工作。

        这里首先简单介绍了两种在SpringBoot中开启Gzip压缩的方式,为下文全面讲解这两种方式做准备,先让大家了解相关知识。

2、SpringBoot中GeoJSON的实例

        GeoJSON在WebGIS中的用处很多,很多矢量数据的边界,范围点等数据,我们都是直接以GeoJSON的格式返回给前端,并直接进行展示的。比如之前很多的行政区划展示,省市县等不同的行政区划范围展示等,我们的实现过程都是在后台的Controller层中返回一个包含GeoJSON的对象,方法如下:

package com.yelang.project.meteorology.domain;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
@ToString(callSuper=true)//callSuper=true表示输出父类属性
@EqualsAndHashCode(callSuper=false)
public class AreaWeatherVO extends WeatherNow implements Serializable{
	private static final long serialVersionUID = -7559774548761847068L;
	@TableField(exist = false,value= "province_code")
	private String provinceCode;
	@TableField(exist = false,value= "province_name")
	private String provinceName;
	@TableField(exist = false,value= "city_code")
	private String cityCode;
	@TableField(exist = false,value= "city_name")
	private String cityName;
	@TableField(exist = false,value= "area_name")
	private String areaName;
	@TableField(exist = false)
	private String geomJson;
	private String lat;
	private String lon;
}

        上面是一个视图对象的具体代码,在Controller的方法中我们调用如下:

@RequiresPermissions("met:province:weather:list")
@GetMapping("/list/{pcode}")
@ResponseBody
public AjaxResult ewsnProvinceList(@PathVariable("pcode") String pcode){
    String day = "2025-08-17";
    List<AreaWeatherVO> dataList = weatherNowService.getWeatherByProvinceAndday(pcode,day);
    return AjaxResult.success().put("data", dataList);
 }

        经过以上的代码输出接口中就包含GeoJOSN数据,如下图所示:

        其具体的geoJSON值如下图:

        在网络窗口中可以看到整个接口返回的数据大小大约为5MB,如果遇到更大范围的行政区划,返回的数据肯定会大,比如西藏的行政区划大约有14MB,如图所示:

        那么如何通过开启Gzip来减少这些数据的输出呢?下面两个部分来重点讲解。

三、全局开启Gzip实现

        本节将详细介绍如何在SpringBoot中开启Gzip压缩的配置。

1、实现原理

        在 application.ymlapplication.properties 中添加以下配置:

        示例:application.yml

server:
  compression:
    enabled: true
    mime-types: application/json
    min-response-size: 1KB  # 小于1KB的响应不压缩

        或者application.properties中:

server.compression.enabled=true
server.compression.mime-types=application/json
server.compression.min-response-size=1024

        请注意:该配置会对所有返回 application/json 的接口启用 GZIP 压缩。

2、实现效果

        在我们的工程中配置文件是以yml的形式配置的,按照上面的步骤进行设置后,重新启动应用程序后来看一下同样的接口,其返回的数据量大小是多少:

        通过以上图片可以直观的看到,开启全局压缩后,我们的接口返回大小,从14.4M下降了5MB,几乎是原来的1/3,这个压缩比例还是可以的。

四、局部约定配置

上面的这种实现方式全局的开启,也就是所有的接口都会开启,虽然可以设置mime-types来进行一定的过滤,但是依然会有很大的覆盖面。如果只想对某个接口生效或者指定一些接口生效又应该怎么实现呢?本节来讲讲针对这种情况的实现。

1、实现原理

        基于局部约定配置的方式的实现原理其实是通过自定义 Filter 来精确控制哪些接口启用压缩,因此通过过滤器就可以将我们需要设定的请求路径进行针对性过滤,从而开启针对这些接口的Gzip过滤压缩。下面我们来看看在SpringBoot中如何实现呢?

2、具体代码实现

首先在SpringBoot中直接创建一个过滤器Filter,关键代码如下:

package com.yelang.framework.interceptor.gzip;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.zip.GZIPOutputStream;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
@Component
public class SelectiveGzipFilter implements Filter {

	private final AntPathMatcher pathMatcher = new AntPathMatcher();
    private final List<String> gzipPatterns = Arrays.asList(
        "/eq/province/geojson/**",
        "/eq/province/detourcoefficient/list/**",
        "/eq/info/home/earthinfo",
        "/eq/province/abbreviations/list"
    );

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String requestUri = req.getRequestURI();
        String contextPath = req.getContextPath();
        boolean match = gzipPatterns.stream()
                .anyMatch(pattern -> pathMatcher.match(pattern, requestUri));
        if (match) {
        	System.out.println("成功匹配");
            // 启用 GZIP 压缩逻辑(同上)
            HttpServletResponse res = (HttpServletResponse) response;
            res.setHeader("Content-Encoding", "gzip");
            res.setHeader("Content-Type", "application/json");
            GZIPResponseWrapper gzipResponse = new GZIPResponseWrapper(res);
            chain.doFilter(request, gzipResponse);
            gzipResponse.finish();
        } else {
        	System.out.println("未匹配上...");
            chain.doFilter(request, response);
        }
    }
   
    static class GZIPResponseWrapper extends HttpServletResponseWrapper {
        private final GZIPOutputStream gzipOutputStream;
        public GZIPResponseWrapper(HttpServletResponse response) throws IOException {
            super(response);
            gzipOutputStream = new GZIPOutputStream(response.getOutputStream());
        }
        @Override
        public ServletOutputStream getOutputStream() {
            return new ServletOutputStream() {
                @Override
                public void write(int b) throws IOException {
                    gzipOutputStream.write(b);
                }
                @Override
                public boolean isReady() {
                    return true;
                }
                @Override
                public void setWriteListener(WriteListener writeListener) {
                    throw new UnsupportedOperationException();
                }
            };
        }
        public void finish() throws IOException {
            gzipOutputStream.finish();
        }
    }
}

        这里演示了如何设置多个目标URL地址的配置方式,使用AntPathMatcher 来进行匹配实现。需要注意的是,这里我们没有区分请求的头地址,以若依为例,可能会在匹配时无法正确对应,导致无法正常的开启Gzip压缩,因此为了保证正确的启用,我们在进行地址匹配时,需要自动过滤项目的服务名称,详细代码如下:

String contextPath = req.getContextPath();
// 去掉 context-path 部分,只匹配相对路径
String relativePath = requestUri.substring(contextPath.length());
System.out.println("relativePath==>" + relativePath);
/*boolean match = gzipPatterns.stream()
                .anyMatch(pattern -> pathMatcher.match(pattern, requestUri));*/
boolean match = gzipPatterns.stream()
                .anyMatch(pattern -> pathMatcher.match(pattern, relativePath));

        其实这里的contenxPath对应的就是配置文件中定义的参数:

# 开发环境配置
server:
  # 服务器的HTTP端口,默认为80
  port: 8080
  servlet:
    # 应用的访问路径
    context-path: /earthqadmin

        GeoJSON 数据通常体积较大,压缩后可显著减少传输时间。以下是实战建议:      

项目 建议值 说明
压缩类型 GZIP 浏览器原生支持
最小压缩阈值 1KB 或更小 GeoJSON 一般远大于此值
MIME 类型 application/json 保持标准兼容
实测效果 原始 15MB → 压缩后 300KB 压缩率可达 90%+

        只有加上以上代码后才能实现正确匹配,在访问地址被请求是输出如下信息:

五、总结

        以上就是本文的主要内容,我们将详细介绍在 SpringBoot 中开启 Gzip 压缩的两种方式的具体实现步骤,并通过实际的 GeoJSON 数据压缩案例,展示这两种方式的应用效果和优缺点。希望通过本文的介绍,能够帮助读者更好地理解和掌握在 SpringBoot 应用中使用 Gzip 压缩技术的方法,从而提升自己开发的 WebGIS 应用的性能和用户体验。博文首先简单介绍了Gzip的相关知识,然后介绍了在SpringBoot中开启Gzip的方式,最后以代码加案例的形式详细的介绍全局开启Gzip和局部开启Gzip的两种不同模式实现原理及具体代码实现。行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐