Usando compresión GZIP con Spring Boot / MVC / JavaConfig con RESTful

Utilizamos Spring Boot / MVC con java-config basado en anotaciones para una serie de servicios RESTful y queremos habilitar selectivamente la compresión de flujo HTTP GZIP en algunas respuestas API.

Sé que puedo hacer esto manualmente en mi controlador y un byte[] @ResponseBody , sin embargo, preferiríamos confiar en la infraestructura de SpringMVC (filtros / etc) y hacer que automáticamente haga la conversión y compresión JSON (es decir, el método devuelve un POJO).

¿Cómo puedo habilitar la compresión GZIP en ResponseBody o en la instancia incorporada de Tomcat, y de una manera que podamos comprimir selectivamente solo algunas respuestas?

¡Gracias!

PD .: actualmente no tenemos ninguna configuración basada en XML.

El rest de estas respuestas están desactualizadas y / o son complicadas para algo que debería ser simple IMO (¿por cuánto tiempo ha estado gzip por ahora? Más tiempo que Java …) De los documentos:

En 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 

En 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 

Más viejo 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"); } } 

También tenga en cuenta que esto SÓLO funcionará si está ejecutando tomcat integrado:

Si planea implementar un tomcat no incrustado, deberá habilitarlo server.xml http://tomcat.apache.org/tomcat-9.0-doc/config/http.html#Standard_Implementation

IRL Production Note:

También para evitar todo esto, considere usar una configuración de proxy / equilibrador de carga en frente de Tomcat con nginx y / o haproxy o similar, ya que manejará los activos estáticos y gzip MUCHO más eficiente y fácilmente que el modelo de subprocesamiento de Java / Tomcat.

No querrás tirar ‘gato en el baño porque está ocupado comprimiendo cosas en lugar de atender peticiones (o más probablemente haciendo girar hilos / comiendo CPU / montón esperando que ocurra IO de la base de datos mientras ejecutas tu factura de AWS que es ¿Por qué Java / Tomcat tradicional podría no ser una buena idea para empezar, dependiendo de lo que estás haciendo, pero estoy divagando …)

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

Esta es básicamente la misma solución que se proporciona con @andy-wilkinson, pero a partir de Spring Boot 1.0, el método customize (…) tiene un parámetro ConfigurableEmbeddedServletContainer .

Otra cosa que vale la pena mencionar es que Tomcat solo comprime los tipos de contenido text/html , text/xml y text/plain de forma predeterminada. A continuación se muestra un ejemplo que también admite la compresión 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); } } ); } }; } 

En versiones recientes en application.yml config:

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

Spring Boot 1.4 Use esto para Javascript HTML Json todas las compresiones.

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

Para habilitar la compresión GZIP, debe modificar la configuración de la instancia incorporada de Tomcat. Para hacerlo, declara un bean EmbeddedServletContainerCustomizer en su configuración de Java y luego registra un TomcatConnectorCustomizer con él.

Por ejemplo:

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

Consulte la documentación de Tomcat para obtener más detalles sobre las diversas opciones de configuración de compresión que están disponibles.

Usted dice que quiere activar selectivamente la compresión. Dependiendo de sus criterios de selección, entonces el enfoque anterior puede ser suficiente. Le permite controlar la compresión por parte del agente de usuario de la solicitud, el tamaño de la respuesta y el tipo de mime de la respuesta.

Si esto no satisface sus necesidades, entonces creo que tendrá que realizar la compresión en su controlador y devolver una respuesta de byte [] con un encabezado de encoding de contenido gzip.

Enabeling GZip en Tomcat no funcionó en mi Spring Boot Project. Utilicé CompressingFilter que se encuentra aquí .

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

He añadido para esto:

Compresión del servidor

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

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

Tuve el mismo problema en mi proyecto Spring Boot + Spring Data al invocar a @RepositoryRestResource .

El problema es el tipo MIME devuelto; que es application/hal+json . Agregarlo a la propiedad server.compression.mime-types resolvió este problema para mí.

Espero que esto ayude a otra persona!