You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot JSON数据Gzip压缩:自动解压是否生效?Jetty适配疑问

问题解答

1. Jetty版SpringBoot应用能否自动解压并解析Gzip压缩的JSON?

可以,但需要正确配置和请求头配合:

  • Spring Boot内嵌Jetty时,默认已支持Gzip请求解压能力,但需通过配置显式开启。在application.yml或application.properties中添加如下配置:
    server:
      jetty:
        gzip:
          enabled: true
          min-gzip-size: 256 # 可选,设置触发解压的最小字节阈值
          mime-types: application/json,text/plain # 指定需要处理的MIME类型
    
  • 发送请求时必须携带Content-Encoding: gzip请求头,Spring MVC的MappingJackson2HttpMessageConverter会自动识别该头,先完成数据流解压,再将JSON内容解析为对应Java对象,无需额外编写解析逻辑。

2. Baeldung指南之外的实现方式

除了容器级的常规配置,还有以下几种实用实现思路:

自定义全局Filter处理解压

编写一个Filter,在请求到达控制器前手动完成请求体解压,示例代码:

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

public class GzipRequestFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String encoding = httpRequest.getHeader("Content-Encoding");
        if ("gzip".equalsIgnoreCase(encoding)) {
            chain.doFilter(new GzipHttpServletRequestWrapper(httpRequest), response);
        } else {
            chain.doFilter(request, response);
        }
    }

    static class GzipHttpServletRequestWrapper extends HttpServletRequestWrapper {
        public GzipHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return new GZIPInputStream(super.getInputStream());
        }
    }
}

然后在Spring Boot中注册该Filter:

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<GzipRequestFilter> gzipRequestFilter() {
        FilterRegistrationBean<GzipRequestFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new GzipRequestFilter());
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }
}

WebFlux场景下的自定义解码器

如果是Spring WebFlux应用,可以自定义HttpMessageReader来处理Gzip解压逻辑:

import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.ByteArrayInputStream;
import java.util.zip.GZIPInputStream;

public class GzipJsonDecoder extends Jackson2JsonDecoder {
    @Override
    public Mono<Object> readMono(Class<?> elementType, ServerHttpRequest request, ServerHttpResponse response, Map<String, Object> hints) {
        HttpHeaders headers = request.getHeaders();
        if ("gzip".equalsIgnoreCase(headers.getFirst(HttpHeaders.CONTENT_ENCODING))) {
            Flux<DataBuffer> decompressedBody = request.getBody()
                    .collectList()
                    .map(buffers -> {
                        byte[] bytes = new byte[buffers.stream().mapToInt(DataBuffer::readableByteCount).sum()];
                        int offset = 0;
                        for (DataBuffer buffer : buffers) {
                            int length = buffer.readableByteCount();
                            buffer.read(bytes, offset, length);
                            offset += length;
                            DataBufferUtils.release(buffer);
                        }
                        try {
                            GZIPInputStream gzipIn = new GZIPInputStream(new ByteArrayInputStream(bytes));
                            return DataBufferUtils.readInputStream(() -> gzipIn, response.bufferFactory(), 4096);
                        } catch (IOException e) {
                            throw new RuntimeException("Failed to decompress Gzip data", e);
                        }
                    })
                    .flatMapMany(flux -> flux);

            ServerHttpRequest wrappedRequest = new ServerHttpRequestDecorator(request) {
                @Override
                public Flux<DataBuffer> getBody() {
                    return decompressedBody;
                }
            };
            return super.readMono(elementType, wrappedRequest, response, hints);
        }
        return super.readMono(elementType, request, response, hints);
    }
}

随后在配置类中替换默认的JSON解码器:

import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.config.WebFluxConfigurer;

@Configuration
public class WebFluxConfig implements WebFluxConfigurer {
    @Override
    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
        configurer.defaultCodecs().jackson2JsonDecoder(new GzipJsonDecoder());
    }
}

客户端侧主动适配(跨服务场景)

如果是跨服务调用场景,可在发送请求的客户端(如RestTemplate或WebClient)配置Gzip压缩,同时服务端通过上述任一方式处理,这种组合方式能更灵活地控制压缩解压逻辑。

内容的提问来源于stack exchange,提问作者BugsOverflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:03:16