Using GZIP compression with Spring Boot/MVC/JavaCo

2019-01-04 19:31发布

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

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).

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

Thanks!

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

8条回答
祖国的老花朵
2楼-- · 2019-01-04 19:50

On recents versions in application.yml config:

---

spring:
  profiles: dev

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

---
查看更多
来,给爷笑一个
3楼-- · 2019-01-04 19:50

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

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

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.

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.

查看更多
一夜七次
4楼-- · 2019-01-04 19:55

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

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.

Hope this helps to someone else!

查看更多
疯言疯语
5楼-- · 2019-01-04 19:56

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:

In application.properties 1.3+

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

In 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:

@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:

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

IRL Production Note:

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

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...)

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

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

查看更多
你好瞎i
6楼-- · 2019-01-04 19:59

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

@Bean
public Filter compressingFilter() {
    CompressingFilter compressingFilter = new CompressingFilter();
    return compressingFilter;
}
查看更多
爱情/是我丢掉的垃圾
7楼-- · 2019-01-04 20:02

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/

查看更多
登录 后发表回答