将 GZIP 压缩与 Spring Boot/MVC/JavaConfig 与 RESTful 结合使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21410317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:33:51  来源:igfitidea点击:

Using GZIP compression with Spring Boot/MVC/JavaConfig with RESTful

javarestspring-mvcgzipspring-java-config

提问by user3182614

We use Spring Boot/MVC with annotation-based java-config for series of RESTfulservices and we want to selectively enable HTTP GZIPstream compression on some API responses.

我们将 Spring Boot/MVC 与基于注解的 java-config 用于一系列RESTful服务,我们希望有选择地HTTP GZIP对某些 API 响应启用流压缩。

I know I can do this manually in my controller and a byte[] @ResponseBody, however we'd prefer to rely on the SpringMVC infrastructure (filters/etc) and have it automatically do the JSON conversion and compression (ie the method returns a POJO).

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

How can I enable GZIP compression in the ResponseBody or embedded Tomcat instance, and in a way we can selectively compress only some responses?

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

Thanks!

谢谢!

PS.: We don't currently have any XML based configuration.

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

回答by Andy Wilkinson

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

开启GZIP压缩需要修改内嵌Tomcat实例的配置。为此,您EmbeddedServletContainerCustomizer在 Java 配置中声明了一个bean,然后TomcatConnectorCustomizer用它注册了一个bean 。

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);
                }
            });
        }
    };
}

See the Tomcat documentationfor more details on the various compression configuration options that are available.

有关可用的各种压缩配置选项的更多详细信息,请参阅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.

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

If this doesn't meet your needs then I believe you will have to perform the compression in your controller and return a byte[] response with a gzip content-encoding header.

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

回答by matsev

This is basically the same solution as @andy-wilkinson provided, but as of Spring Boot 1.0 the customize(...)method has a ConfigurableEmbeddedServletContainerparameter.

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

Another thing that is worth mentioning is that Tomcat only compresses content types of text/html, text/xmland text/plainby default. Below is an example that supports compression of application/jsonas well:

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

回答by user1127860

Enabeling GZip in Tomcat doesn't worked in my Spring Boot Project. I used CompressingFilterfound here.

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

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

回答by John Culviner

The rest of these answers are out of date and/or over the top complicated for something that should be simple IMO (how long has gzip been around for now? longer than Java...) From the docs:

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

In application.properties 1.3+

在 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 

In application.properties 1.2.2 - <1.3

在 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

Older than 1.2.2:

早于 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 时才有效:

If you plan to deploy to a non embedded tomcat you will have to enable it in server.xml http://tomcat.apache.org/tomcat-9.0-doc/config/http.html#Standard_Implementation

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

IRL Production Note:

IRL 生产说明:

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

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

You don't want to throw 'cat in the bath because it's busy compressing stuff instead of serving up requests (or more likely spinning up threads/eating CPU/heap sitting around waiting for database IO to occur while running up your AWS bill which is why traditional Java/Tomcat might not be a good idea to begin with depending on what you are doing but I digress...)

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

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

参考文献: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

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

回答by M. Reza Nasirloo

On recents versions in application.ymlconfig:

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

---

spring:
  profiles: dev

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

---

回答by Ronny Shibley

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

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

回答by Serginho

I had the same problem into my Spring Boot+Spring Data project when invoking to a @RepositoryRestResource.

调用@RepositoryRestResource.

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

问题是返回的 MIME 类型;这是application/hal+json. 将它添加到server.compression.mime-types属性中为我解决了这个问题。

Hope this helps to someone else!

希望这对其他人有帮助!

回答by Oleksii Kyslytsyn

I have added for this:

我为此添加了:

Server compression

服务器压缩

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

taken from http://bisaga.com/blog/programming/web-compression-on-spring-boot-application/

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