用 Spring Boot/MVC/JavaConfig 和 RESTful 实现 GZIP 压缩

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

我知道我可以在我的控制器和 byte[] @ResponseBody中手动完成,但是我们更愿意依赖 Spring MVC 基础设施(过滤器/等) ,并让它自动执行 JSON 转换和压缩(即该方法返回一个 POJO)。

如何在 ResponseBody 或嵌入式 Tomcat 实例中启用 GZIP 压缩,并且在某种程度上我们只能选择性地压缩一些响应?

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

131803 次浏览

To enable GZIP compression, you need to modify the configuration of the embedded Tomcat instance. To do so, you declare a EmbeddedServletContainerCustomizer bean in your Java configuration and then register a TomcatConnectorCustomizer with it.

For example:

@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 文档

You say that you want to selectively enable compression. Depending on your selection criteria, then the above approach may be sufficient. It enables you to control compression by the request's user-agent, the response's size, and the response's mime type.

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

这与@andy-wilkinson 提供的解决方案基本相同,但是在 Spring Boot 1.0中,自定义(...)方法有一个 ConfigurableEmbeddedServletContainer参数。

另一件值得一提的事情是,Tomcat 默认情况下只压缩 text/htmltext/xmltext/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);
}
}
);
}
};
}

在 Tomcat 中启用 GZip 在我的 Spring 引导项目中不起作用。

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

其余的这些答案都过时了,或者对于一些应该是简单的 IMO (gzip 已经存在多久了?比 Java 还长...)来自文档:

在 application.properties < a href = “ https://docs.spring.io/spring-boot/docs/1.3.3.3.RELEASE/reference/html/howto- 嵌入式 servlet-conters.html # how-to-able-http-response- rel = “ noReferrer”> 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 < a href = “ https://docs.spring.io/spring-boot/docs/1.2.2.2.RELEASE/reference/html/howto- 嵌入式 servlet-conters.html # how-to-able-http-response- rel = “ noReferrer”> 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

Older than 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");
}
}

Also note this will ONLY work if you are running embedded tomcat:

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

IRL 制作说明:

Also to avoid all of this consider using a proxy/load balancer setup in front of Tomcat with Nginx and/or 代理人 or similar since it will handle static assets and gzip MUCH more efficiently and easily than Java/Tomcat's threading model.

你不想把‘ cat’扔进浴缸里,因为它忙着压缩东西而不是提供请求(或者更可能的是在运行 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

On recents versions in application.yml config:

---


spring:
profiles: dev


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


---

Spring Boot 1.4 Use this for Javascript HTML Json all compressions.

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

当调用 @RepositoryRestResource时,我在 Spring Boot + Spring Data 项目中遇到了同样的问题。

The problem is the MIME type returned; which is application/hal+json. Adding it to the server.compression.mime-types property solved this problem for me.

希望这对别人有帮助!

我为此补充说明:

服务器压缩

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/