web-dev-qa-db-fra.com

Utilisation de la compression GZIP avec Spring Boot/MVC/JavaConfig avec RESTful

Nous utilisons Spring Boot/MVC avec Java-config basé sur des annotations pour une série de services RESTful et nous souhaitons activer de manière sélective la compression de flux HTTP GZIP sur certaines réponses de l'API.

Je sais que je peux le faire manuellement dans mon contrôleur et avec un byte[] @ResponseBody. Cependant, nous préférerions nous appuyer sur l'infrastructure SpringMVC (filtres/etc.) et lui demander de faire automatiquement la conversion et la compression JSON (c'est-à-dire que la méthode retourne un POJO).

Comment puis-je activer la compression GZIP dans l'instance ResponseBody ou Tomcat intégrée et comment, de manière sélective, ne compresser que certaines réponses?

Merci!

PS: Nous n'avons actuellement aucune configuration basée sur XML.

79
user3182614

Le reste de ces réponses est obsolète et/ou excessivement compliqué pour une chose qui devrait être simple. OMI (depuis combien de temps gzip existe-t-il maintenant? Plus longtemps que Java ...) D'après les documents:

Dans 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

Dans 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

Plus vieux que 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");
  }
}

Notez également que cela fonctionnera UNIQUEMENT si vous utilisez Tomcat intégré:

Si vous envisagez de déployer sur un Tomcat non incorporé, vous devrez l'activer dans server.xml http://Tomcat.Apache.org/Tomcat-9.0-doc/config/http.html#Standard_Implementation

Note de production IRL:

Pour éviter tout cela, envisagez d'utiliser une configuration proxy/équilibreur de charge devant Tomcat avec nginx et/ou haproxy ou similaire, car elle gérera plus facilement et plus efficacement les actifs statiques et gzip MUCH par rapport à Java /. Modèle de threading de Tomcat.

Vous ne voulez pas jeter le chat dans le bain parce qu'il est occupé à compresser des choses au lieu de répondre aux demandes (ou plutôt à faire tourner des threads/à manger du CPU/du tas en attendant que la base de données IO se produise lors de l'exécution de votre La facture AWS, c’est la raison pour laquelle les versions traditionnelles de Java/Tomcat n’est peut-être pas une bonne idée de commencer en fonction de ce que vous faites, mais je m'éloigne du sujet ...)

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

163
John Culviner

C'est en gros la même solution que celle fournie par @ andy-wilkinson, mais à partir de Spring Boot 1.0, la méthode personnaliser (...) a un paramètre ConfigurableEmbeddedServletContainer

Une autre chose à noter est que Tomcat ne compresse que les types de contenu text/html, text/xml et text/plain par défaut. Vous trouverez ci-dessous un exemple prenant en charge la compression de 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);
                        }
                    }
            );
        }
    };
}
12
matsev

Sur les versions récentes de application.yml config:

---

spring:
  profiles: dev

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

---
11
M. Reza Nasirloo

Spring Boot 1.4 Utilisez ceci pour Javascript HTML avec toutes les compressions.

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

Pour activer la compression GZIP, vous devez modifier la configuration de l'instance intégrée Tomcat. Pour ce faire, vous déclarez un bean EmbeddedServletContainerCustomizer dans votre configuration Java, puis vous enregistrez une TomcatConnectorCustomizer avec celui-ci.

Par exemple:

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

Reportez-vous à la documentation Tomcat pour plus de détails sur les différentes options de configuration de la compression disponibles.

Vous dites que vous souhaitez activer la compression de manière sélective. En fonction de vos critères de sélection, l’approche ci-dessus peut alors suffire. Il vous permet de contrôler la compression par l'agent utilisateur de la demande, la taille de la réponse et le type mime de la réponse.

Si cela ne répond pas à vos besoins, je pense que vous devrez effectuer la compression dans votre contrôleur et renvoyer une réponse octet [] avec un en-tête gzip content-encoding.

4
Andy Wilkinson

J'ai ajouté pour cela: 

Compression du serveur

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

extrait de http://bisaga.com/blog/programming/web-compression-on-spring-boot-application/

4

L'activation de GZip dans Tomcat ne fonctionne pas dans mon projet de démarrage Spring. J'ai utilisé CompressingFilter trouvé ici .

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

J'avais le même problème dans mon projet Spring Boot + Spring Data lors de l'appel à un @RepositoryRestResource.

Le problème est le type MIME renvoyé. qui est application/hal+json. L'ajouter à la propriété server.compression.mime-types a résolu ce problème pour moi.

J'espère que cela aide quelqu'un d'autre!

0
Serginho