我们使用 Spring Boot/MVC 和基于注释的 java-config 来实现一系列 RESTful 服务,并且我们希望有选择地在某些 API 响应上启用 HTTP GZIP 流压缩。
我知道我可以在我的控制器和
byte[] @ResponseBody
中手动执行此操作,但是我们更愿意依赖 Spring MVC 基础设施(过滤器/等)并让它自动执行 JSON 转换和压缩(即该方法返回POJO)。
如何在 ResponseBody 或嵌入式 Tomcat 实例中启用 GZIP 压缩,并且以某种方式我们可以有选择地仅压缩某些响应?
我们目前没有任何基于 XML 的配置。
这些答案的其余部分已经过时和/或对于本应简单的事情来说过于复杂(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,则必须在 server.xml 中启用它 http://tomcat.apache.org/tomcat-9.0-doc/config/http.html#Standard_Implementation
为了避免所有这些,请考虑在 Tomcat 前面使用带有 nginx 和/或 haproxy 或类似的代理/负载均衡器设置,因为它比 Java/Tomcat 的线程模型更有效、更轻松地处理静态资产和 gzip .
你不想把“猫扔进浴缸里”,因为它忙着压缩东西而不是提供请求(或者更有可能在运行你的 AWS 账单时旋转线程/消耗 CPU/堆等待数据库 IO 发生,这这就是为什么传统的 Java/Tomcat 可能不是一个好主意,具体取决于您正在做什么,但我离题了......)
在
application.yml
配置中的最新版本:
---
spring:
profiles: dev
server:
compression:
enabled: true
mime-types: text/html,text/css,application/javascript,application/json
---
这与 @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);
}
}
);
}
};
}
我为此添加了:
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/
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
在 Tomcat 中启用 GZip 在我的 Spring Boot 项目中不起作用。我使用了CompressingFilter,在here找到。
@Bean
public Filter compressingFilter() {
CompressingFilter compressingFilter = new CompressingFilter();
return compressingFilter;
}
要启用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[] 响应。
在调用
@RepositoryRestResource
时,我的 Spring Boot+Spring Data 项目也遇到了同样的问题。
问题是返回的MIME类型;这是
application/hal+json
。将其添加到 server.compression.mime-types
属性为我解决了这个问题。
希望这对其他人有帮助!
在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 文件中添加任何属性。