Использование сжатия GZIP с Spring Boot/MVC/JavaConfig с RESTful

Мы используем Spring Boot/MVC с java-config на основе аннотаций для серии RESTful услуги, и мы хотим, чтобы выборочно включить HTTP GZIP сжатие потока на некоторых ответах API.

Я знаю, что могу сделать это вручную в моем контроллере и byte[] @ResponseBodyОднако мы бы предпочли полагаться на инфраструктуру SpringMVC (фильтры / и т. д.), чтобы она автоматически выполняла преобразование и сжатие JSON (т. е. метод возвращает POJO).

Как я могу включить сжатие GZIP в ResponseBody или встроенном экземпляре Tomcat, и таким образом мы можем выборочно сжимать только некоторые ответы?

Спасибо!

PS: В настоящее время у нас нет конфигурации на основе XML.

8 ответов

Остальные ответы устарели и / или слишком сложны для чего-то, что должно быть простым IMO (как долго gzip существует сейчас? Дольше, чем Java...) Из документации:

В приложении. Свойства 1.3+

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

В заявке. Свойства 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

Производственное примечание IRL:

Также, чтобы избежать всего этого, рассмотрите возможность использования настройки прокси / балансировщика нагрузки перед Tomcat с nginx и / или haproxy или аналогичной, так как он будет обрабатывать статические ресурсы и намного эффективнее и проще gzip, чем модель потоков Java/Tomcat.

Вы не хотите бросать "кошку в ванну", потому что она занята сжатием вещей вместо того, чтобы обслуживать запросы (или, более вероятно, раскручивает потоки / ест процессор / кучу, бездельничая, ожидая ввода-вывода базы данных при выполнении счета AWS, который почему традиционный Java/Tomcat может не быть хорошей идеей для начала, в зависимости от того, что вы делаете, но я отвлекся...)

ссылки: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/

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

На последних версиях в 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

Enabeling GZip в Tomcat не работает в моем проекте Spring Boot. Я использовал CompressingFilter, найденный здесь.

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

Чтобы включить сжатие GZIP, вам нужно изменить конфигурацию встроенного экземпляра Tomcat. Для этого вы объявляете EmbeddedServletContainerCustomizer боб в вашей конфигурации Java, а затем зарегистрировать 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 для получения более подробной информации о различных доступных параметрах конфигурации сжатия.

Вы говорите, что хотите выборочно включить сжатие. В зависимости от ваших критериев выбора, вышеупомянутый подход может быть достаточным. Это позволяет вам контролировать сжатие с помощью пользовательского агента запроса, размера ответа и типа пантомимы ответа.

Если это не отвечает вашим потребностям, то я считаю, что вам придется выполнить сжатие в вашем контроллере и вернуть ответ byte[] с заголовком gzip content-encoding.

У меня была такая же проблема в моем проекте Spring Boot+Spring Data при вызове @RepositoryRestResource,

Проблема в возвращаемом типе MIME; который application/hal+json, Добавление его в server.compression.mime-types собственность решила эту проблему для меня.

Надеюсь, это поможет кому-то еще!

Другие вопросы по тегам