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
相关产品推荐
相关产品推荐

