在 Spring Boot/MVC/JavaConfig 和 RESTful 中使用 GZIP 压缩

问题描述 投票:0回答:9

我们使用 Spring Boot/MVC 和基于注释的 java-config 来实现一系列 RESTful 服务,并且我们希望有选择地在某些 API 响应上启用 HTTP GZIP 流压缩。

我知道我可以在我的控制器和

byte[] @ResponseBody
中手动执行此操作,但是我们更愿意依赖 Spring MVC 基础设施(过滤器/等)并让它自动执行 JSON 转换和压缩(即该方法返回POJO)。

如何在 ResponseBody 或嵌入式 Tomcat 实例中启用 GZIP 压缩,并且以某种方式我们可以有选择地仅压缩某些响应?

我们目前没有任何基于 XML 的配置。

java spring rest spring-mvc gzip
9个回答
226
投票

这些答案的其余部分已经过时和/或对于本应简单的事情来说过于复杂(IMO)(gzip 已经存在多久了?比 Java 还要长......)来自文档:

在 application.properties 1.3+

# 🗜️🗜️🗜️
server.compression.enabled=true
# opt in to content types
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
# not worth the CPU cycles at some point, probably
server.compression.min-response-size=10240 

在 application.properties 中 1.2.2 - <1.3

server.tomcat.compression=on
server.tomcat.compressableMimeTypes=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css

1.2.2 之前:

@Component
public class TomcatCustomizer implements TomcatConnectorCustomizer {

  @Override
  public void customize(Connector connector) {
    connector.setProperty("compression", "on");
    // Add json and xml mime types, as they're not in the mimetype list by default
    connector.setProperty("compressableMimeType", "text/html,text/xml,text/plain,application/json,application/xml");
  }
}

另请注意,这仅在您运行嵌入式 tomcat 时才有效:

如果您计划部署到非嵌入式 tomcat,则必须在 server.xml 中启用它 http://tomcat.apache.org/tomcat-9.0-doc/config/http.html#Standard_Implementation

IRL 生产说明:

为了避免所有这些,请考虑在 Tomcat 前面使用带有 nginx 和/或 haproxy 或类似的代理/负载均衡器设置,因为它比 Java/Tomcat 的线程模型更有效、更轻松地处理静态资产和 gzip .

你不想把“猫扔进浴缸里”,因为它忙着压缩东西而不是提供请求(或者更有可能在运行你的 AWS 账单时旋转线程/消耗 CPU/堆等待数据库 IO 发生,这这就是为什么传统的 Java/Tomcat 可能不是一个好主意,具体取决于您正在做什么,但我离题了......)

参考文献: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/howto.html#how-to-enable-http-response-compression

https://github.com/spring-projects/spring-boot/issues/2031


17
投票

application.yml
配置中的最新版本:

---

spring:
  profiles: dev

server:
  compression:
    enabled: true
    mime-types: text/html,text/css,application/javascript,application/json

---

13
投票

这与 @andy-wilkinson 提供的解决方案基本相同,但从 Spring Boot 1.0 开始, customize(...) 方法有一个 ConfigurableEmbeddedServletContainer 参数。

另外值得一提的是,Tomcat 默认只压缩

text/html
text/xml
text/plain
的内容类型。下面是一个也支持压缩
application/json
的示例:

@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer servletContainer) {
            ((TomcatEmbeddedServletContainerFactory) servletContainer).addConnectorCustomizers(
                    new TomcatConnectorCustomizer() {
                        @Override
                        public void customize(Connector connector) {
                            AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
                            httpProtocol.setCompression("on");
                            httpProtocol.setCompressionMinSize(256);
                            String mimeTypes = httpProtocol.getCompressableMimeTypes();
                            String mimeTypesWithJson = mimeTypes + "," + MediaType.APPLICATION_JSON_VALUE;
                            httpProtocol.setCompressableMimeTypes(mimeTypesWithJson);
                        }
                    }
            );
        }
    };
}

11
投票

我为此添加了:

服务器压缩

server.compression.enabled=true
server.compression.min-response-size=2048
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain

取自http://bisaga.com/blog/programming/web-compression-on-spring-boot-application/


10
投票

Spring Boot 1.4 使用它进行 Javascript HTML Json 所有压缩。

server.compression.enabled: true
server.compression.mime-types: application/json,application/xml,text/html,text/xml,text/plain,text/css,application/javascript

7
投票

在 Tomcat 中启用 GZip 在我的 Spring Boot 项目中不起作用。我使用了CompressingFilter,在here找到。

@Bean
public Filter compressingFilter() {
    CompressingFilter compressingFilter = new CompressingFilter();
    return compressingFilter;
}

5
投票

要启用GZIP压缩,您需要修改嵌入式Tomcat实例的配置。为此,您需要在 Java 配置中声明一个

EmbeddedServletContainerCustomizer
bean,然后向其注册一个
TomcatConnectorCustomizer

例如:

@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
            ((TomcatEmbeddedServletContainerFactory) factory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
                @Override
                public void customize(Connector connector) {
                    AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
                    httpProtocol.setCompression("on");
                    httpProtocol.setCompressionMinSize(64);
                }
            });
        }
    };
}

有关可用的各种压缩配置选项的更多详细信息,请参阅 Tomcat 文档

你说你想有选择地启用压缩。根据您的选择标准,上述方法可能就足够了。它使您能够通过请求的用户代理、响应的大小和响应的 mime 类型来控制压缩。

如果这不能满足您的需求,那么我相信您将必须在控制器中执行压缩并返回带有 gzip 内容编码标头的 byte[] 响应。


3
投票

在调用

@RepositoryRestResource
时,我的 Spring Boot+Spring Data 项目也遇到了同样的问题。

问题是返回的MIME类型;这是

application/hal+json
。将其添加到
server.compression.mime-types
属性为我解决了这个问题。

希望这对其他人有帮助!


0
投票

在pom.xml中添加以下依赖

<dependency>
    <groupId>net.sourceforge.pjl-comp-filter</groupId>
    <artifactId>pjl-comp-filter</artifactId>
    <version>1.6.4</version>
</dependency>

将以下 bean 配置添加到您的配置文件中。

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.DispatcherServlet;
import com.planetj.servlet.filter.compression.CompressingFilter;

@Bean
public FilterRegistrationBean<CompressingFilter> dispatcherRegistration(DispatcherServlet dispatcherServlet) {
    FilterRegistrationBean<CompressingFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new CompressingFilter());
    registrationBean.setEnabled(true);
    registrationBean.addUrlPatterns("/*");
    return registrationBean;
}

CompressingFilter
有助于压缩响应。

您可以使用

addUrlPatterns(String)
中的
FilterRegistrationBean
方法设置选择性端点的GZIP压缩。 如果您有多个端点,请使用
setUrlPatterns(Collection<String>)
方法。

如果未设置 URL 模式,过滤器将压缩所有响应。

注意:这甚至不需要在 application.properties 文件中添加任何属性。

© www.soinside.com 2019 - 2024. All rights reserved.