SpringBoot 接口资源大小压缩 gzip

1 篇文章 0 订阅
本文详细介绍了SpringBoot如何配置HTTP响应的GZIP压缩,包括自动压缩设置、配置参数解释,以及在实际应用中遇到的问题。当返回内容超过2KB时,SpringBoot会自动进行gzip压缩,但若返回对象时,由于缺少Content-Length字段,压缩可能不会生效。解决方案是添加一个Filter来设置Content-Length,确保内容长度可被正确判断,从而实现压缩。
摘要由CSDN通过智能技术生成

前言

springboot支持gzip压缩,并且支持自动压缩,即响应内容长度较短时不压缩,保证响应速度,响应内容长度较长时压缩,减轻带宽压力,并且配置起来十分简单

http响应的gzip压缩

当服务端对响应做了gzip压缩后,header里会添加:Content-Encoding: gzip用于表明返回结果做了gzip压缩。

如果客户端不希望该次请求会被压缩,则可以修改请求的header中的Accept-Encoding,去掉gzip即可

springboot配置

1、application.properties配置

server.compression.enabled=true
添加该配置后,springboot就开启了压缩。

springboot压缩还有以下配置:

server:
  port: 2222
  compression: #开启gzip压缩,返回内容大于2k的才会进行压缩
    enabled: true
    mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
    min-response-size: 2048

    

2、添加Content-Length

一般的教程到上一步就结束了,事实上上一步完成后确实已经开启了自动压缩,但是在测试时我发现,如果Controller返回的是普通的字符串,确实会有效果,如:

@RequestMapping(value = “/”, method = RequestMethod.GET)
@ResponseBody
public String test(){
return “test”;
}
当返回的字符串超过2KB时就会压缩,不超过则直接返回。

但是,当返回的是一个自定义的对象时,自动压缩不起效果,如:

@RequestMapping(value = “/”, method = RequestMethod.GET)
@ResponseBody
public Result test(){
return new Result(“test”);
}
server.compression.min-response-size不起作用,不管这个对象的大小,默认全部做gzip压缩。

经过排查是因为响应的header中没有Content-Length

当返回的是字符串,即Content-Type: text/plain 时,会设置Content-Length

而当返回的是对象,即Content-Type: application/json时,不会设置Content-Length,服务端无法判断长度,并且是通过Transfer-Encoding: chunked的方式发送给客户端,因此一定会做压缩。

因此只需要全局加上一个Content-Length即可:

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterBean = new FilterRegistrationBean();
        filterBean.setFilter(new AddContentLengthFilter());
        filterBean.setUrlPatterns(Arrays.asList("*"));
        return filterBean;
    }

}
class AddContentLengthFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        ContentCachingResponseWrapper cacheResponseWrapper;
        if (!(response instanceof ContentCachingResponseWrapper)) {
            cacheResponseWrapper = new ContentCachingResponseWrapper(response);
        } else {
            cacheResponseWrapper = (ContentCachingResponseWrapper) response;
        }

        filterChain.doFilter(request, cacheResponseWrapper);

        cacheResponseWrapper.copyBodyToResponse();
    }
}

这里添加了一个Filter,在这个Filter中,使用了ContentCachingResponseWrapper包装response

ContentCachingResponseWrapper会缓存所有写给OutputStream的数据,并且因为缓存了内容,所以可以获取Content-Length并帮忙设置。

测试

这里不细讲测试细节,可以用wireshark抓包,看看http响应的header中是否有Content-Encoding: gzip ,也可以看看具体的响应大小

总结

springboot的自动压缩看起来很容易设置,事实上自己在解决时也找了好久的资料。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值