RESTful ile Spring Boot / MVC / JavaConfig ile GZIP sıkıştırmasını kullanma


98

Bir dizi RESTfulhizmet için ek açıklama tabanlı java yapılandırması ile Spring Boot / MVC kullanıyoruz ve HTTP GZIPbazı API yanıtlarında seçici olarak akış sıkıştırmasını etkinleştirmek istiyoruz .

Bunu kontrol byte[] @ResponseBodycihazımda ve a'da manuel olarak yapabileceğimi biliyorum , ancak SpringMVC altyapısına (filtreler / vb.) Güvenmeyi ve JSON dönüştürme ve sıkıştırmayı otomatik olarak yapmasını tercih ederiz (yani yöntem bir POJO döndürür).

ResponseBody veya gömülü Tomcat örneğinde GZIP sıkıştırmasını nasıl etkinleştirebilirim ve bir şekilde yalnızca bazı yanıtları seçici olarak sıkıştırabiliriz?

Teşekkürler!

Not: Şu anda XML tabanlı yapılandırmamız yok.



2
Ne yaptığınızı bilmiyorsanız HTTPS ile HTTP sıkıştırması kullanmayın
Neil McGuigan

Yanıtlar:


192

Bu cevapların geri kalanı güncel değil ve / veya basit bir IMO olması gereken bir şey için çok karmaşık (gzip şimdilik ne zamandır var? Java'dan daha uzun ...) Dokümanlar:

Application.properties 1.3+ içinde

# 🗜️🗜️🗜️
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 

Uygulama özellikleri 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'den eski:

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

Ayrıca, bunun YALNIZCA gömülü tomcat çalıştırıyorsanız çalışacağını unutmayın:

Gömülü olmayan bir tomcat'e dağıtmayı planlıyorsanız, bunu server.xml http://tomcat.apache.org/tomcat-9.0-doc/config/http.html#Standard_Implementation'da etkinleştirmeniz gerekecektir.

IRL Üretim Notu:

Ayrıca, tüm bunlardan kaçınmak için , Tomcat'in önünde nginx ve / veya haproxy veya benzeri bir proxy / yük dengeleyici kurulumu kullanmayı düşünün, çünkü statik varlıkları işleyecektir ve Java / Tomcat'in iş parçacığı modelinden ÇOK daha verimli ve kolay bir şekilde gzip'i gzip edecektir.

Kediyi banyoya atmak istemezsiniz çünkü istekleri yerine getirmek yerine bir şeyler sıkıştırmakla meşguldür (veya daha büyük olasılıkla AWS faturanızı çalıştırırken veritabanı GÇ'sinin oluşmasını beklerken etrafta oturup dolaşmakla meşguldür) Neden geleneksel Java / Tomcat ne yaptığınıza bağlı olarak başlamak için iyi bir fikir olmayabilir ama konuyu ele alıyorum ...)

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


1.2.2'den eski sürümler için yaklaşımınız, Spring Boot TomcatConnectorCustomizeruygulama bağlamında örnekleri aramadığından işe yaramaz ; programatik olarak kaydedilmeleri gerekirTomcatEmbeddedServletContainerFactory
Andy Wilkinson

Söylediğin için teşekkürler. Statik / dinamik / tomcat / vs önyükleme hala bir sorun olduğu için bundan vazgeçtim. Bu olması gerekenden çok daha zor ... Nginx ters proxy FTW!
John Culviner

3
SpringBoot'ta yeni özellikler server.compression.enabled = true ve server.compression.mime-types = XXX, YYY github.com/spring-projects/spring-boot/wiki/…
blacelle

2
Yaylı önyükleme için, tüm JSON yanıtlarını döndüren birden fazla dinlenme denetleyicimiz var. Zip'i bazı denetleyicilere seçici olarak uygulayabilir miyiz?

3
Sıkıştırma için minimum yanıt boyutunu da belirtmelisiniz (ör: 10KB), aksi takdirde sunucunun her isteği (ör. 0,5KB) sıkıştırması ek yük haline gelir. server.compression.min-response-size=10240
UsamaAmjad


12

Bu, temelde @ andy-wilkinson'ın sağladığı çözümle aynıdır, ancak Spring Boot 1.0'dan itibaren, özelleştir (...) yönteminin bir ConfigurableEmbeddedServletContainer parametresi vardır.

Kayda değer bir başka şey Tomcat sadece içerik türleri sıkıştırır olduğunu text/html, text/xmlve text/plainvarsayılan olarak. Aşağıda sıkıştırmayı da destekleyen bir örnek bulunmaktadır 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);
                        }
                    }
            );
        }
    };
}

Bunu Java Yapılandırmama eklemeyi denedim ve sıkıştırmanın hiç çalışmadığını fark ettim. Tümleşik kapsayıcı olarak Tomcat ile Spring Boot kullanıyorum ve bu yapılandırma dışında ayarlamam gereken başka şeyler olup olmadığını merak ettim.
Michael Coxon

2
Accept-Encoding: gzip,deflateCurl kullanıyorsanız , başlığı belirterek doğrulamayı deneyin :curl -i -H 'Accept-Encoding: gzip,deflate' http://url.to.your.server
matsev

9

Spring Boot 1.4 Bunu tüm sıkıştırmalar için Javascript HTML Json için kullanın.

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

Bu sıkıştırmayı nasıl doğrularız?
Bhargav

@Bhargav API yanıtınızın yanıt başlığına bakın. Başlığı içermelidir Content-Encoding::gzip
Sumit Jha


6

GZip'i Tomcat'te etkinleştirmek Spring Boot Projemde işe yaramadı. Burada bulunan CompressingFilter kullandım .

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

@ user1127860 tnx bu çalışıyor ama yine de bu Filtreyi daha fazla yapılandırmak için? Spring boot kullanıyorum ve web.xml'de kılavuzun dediği gibi init parametreleri ekleyemiyorum
Spring

5

GZIP sıkıştırmasını etkinleştirmek için, gömülü Tomcat örneğinin yapılandırmasını değiştirmeniz gerekir. Bunu yapmak için, EmbeddedServletContainerCustomizerJava yapılandırmanızda bir fasulye bildirirsiniz ve ardından TomcatConnectorCustomizeronunla bir tane kaydedersiniz .

Örneğin:

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

Mevcut çeşitli sıkıştırma yapılandırma seçenekleri hakkında daha fazla ayrıntı için Tomcat belgelerine bakın .

Seçmeli olarak sıkıştırmayı etkinleştirmek istediğinizi söylüyorsunuz. Seçim kriterlerinize bağlı olarak, yukarıdaki yaklaşım yeterli olabilir. Sıkıştırmayı isteğin kullanıcı aracısına, yanıtın boyutuna ve yanıtın mime türüne göre kontrol etmenizi sağlar.

Bu ihtiyaçlarınızı karşılamıyorsa, denetleyicinizde sıkıştırmayı yapmanız ve gzip içerik kodlama başlığıyla bir bayt [] yanıtı döndürmeniz gerektiğine inanıyorum.


1
Ayarı application.properties'e yerleştirme seçeneğine verdiğiniz yanıt arasındaki fark nedir? server.compression.enabled = true server.compression.mime-types = application / json, application / xml, text / html, text / xml, text / plain, application / javascript, text / css
lukass77

Bu cevap, özelliklere dayalı sıkıştırma yapılandırması mevcut olmadan önce yazılmıştır. Bunlar eşdeğerdir, ancak özelliklere dayalı yaklaşım daha kolaydır, bu yüzden onu kullanmanızı tavsiye ederim.
Andy Wilkinson

benim durumumda tomcat'in https alan bir yük dengeleyicinin arkasında olduğunu paylaşmak istiyorum ve application.properties çözümünü kullandığımda tomcat'e isteği http. https isteği ile gzip yanıtı LB
lukass77

application.properties çözümünü kullanmam ve 8081 ve 8082 bağlantı noktalarında daha fazla 2 bağlayıcı tanımlamam durumunda başka bir soru .. sıkıştırma tüm bağlayıcılara mı yoksa yalnızca 8080 bağlayıcısına mı uygulanabilir?
lukass77

Bunu doğruluyorum, derleme yalnızca 8080 numaralı bağlantı noktasında geçerlidir, daha fazla bağlayıcı açsanız bile .., bence hata bu konuda açık olmalı ?? .., bu nedenle benim için yalnızca çalışma çözümü her bağlayıcı için programlı yapılandırmaydı, not application.properties
lukass77

0

Aynı sorunu Spring Boot + Spring Data projemde bir @RepositoryRestResource.

Sorun, döndürülen MIME türüdür; hangisi application/hal+json. Bunu server.compression.mime-typesmülke eklemek bu sorunu benim için çözdü.

Umarım bu başka birine yardımcı olur!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.