0
点赞
收藏
分享

微信扫一扫

spring/springboot/springmvc启用GZIP压缩

千妈小语 2022-08-18 阅读 46

http压缩相关类Compression.java

package org.springframework.boot.web.server;

import org.springframework.util.unit.DataSize;

/**
* Simple server-independent abstraction for compression configuration.
*
* @author Ivan Sopov
* @author Andy Wilkinson
* @author Stephane Nicoll
* @since 2.0.0
*/
public class Compression {

private boolean enabled = false;

private String[] mimeTypes = new String[] { "text/html", "text/xml", "text/plain", "text/css", "text/javascript",
"application/javascript", "application/json", "application/xml" };

private String[] excludedUserAgents = null;

private DataSize minResponseSize = DataSize.ofKilobytes(2);

/**
* Return whether response compression is enabled.
* @return {@code true} if response compression is enabled
*/
public boolean getEnabled() {
return this.enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

/**
* Return the MIME types that should be compressed.
* @return the MIME types that should be compressed
*/
public String[] getMimeTypes() {
return this.mimeTypes;
}

public void setMimeTypes(String[] mimeTypes) {
this.mimeTypes = mimeTypes;
}

public String[] getExcludedUserAgents() {
return this.excludedUserAgents;
}

public void setExcludedUserAgents(String[] excludedUserAgents) {
this.excludedUserAgents = excludedUserAgents;
}

/**
* Return the minimum "Content-Length" value that is required for compression to be
* performed.
* @return the minimum content size in bytes that is required for compression
*/
public DataSize getMinResponseSize() {
return this.minResponseSize;
}

public void setMinResponseSize(DataSize minSize) {
this.minResponseSize = minSize;
}

}

通过以上代码了解

1、从Spring 2.x开始就支持http响应流压缩

2、默认不开启压缩

3、默认压缩阈值2K,当响应流字节达到2K才压缩

4、支持过滤特定类型的User-Agent

5、默认压缩文件类型

"text/html", "text/xml", "text/plain", "text/css", "text/javascript",
"application/javascript", "application/json", "application/xml"

 

解决方案

在application.properties或者application.yml配置相关属性

server.compression.enabled=true

server.compression.min-response-size=1024 #响应流达到1024字节再压缩

application.yml

server:
compression:
enabled: true
min-response-size: 1024

 

参考:https://frontbackend.com/spring/how-to-enable-gzip-compression-in-spring-boot

关于排除自定义的User-Agent

笔者追踪源代码,找到了相关代码片段

Tomcat

org.springframework.boot.web.embedded.tomcat.CompressionConnectorCustomizer

package org.springframework.boot.web.embedded.tomcat;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.UpgradeProtocol;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.apache.coyote.http2.Http2Protocol;

import org.springframework.boot.web.server.Compression;
import org.springframework.util.StringUtils;

/**
* {@link TomcatConnectorCustomizer} that configures compression support on the given
* Connector.
*
* @author Brian Clozel
*/
class CompressionConnectorCustomizer implements TomcatConnectorCustomizer {

private final Compression compression;

CompressionConnectorCustomizer(Compression compression) {
this.compression = compression;
}

@Override
public void customize(Connector connector) {
if (this.compression != null && this.compression.getEnabled()) {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractHttp11Protocol) {
customize((AbstractHttp11Protocol<?>) handler);
}
for (UpgradeProtocol upgradeProtocol : connector.findUpgradeProtocols()) {
if (upgradeProtocol instanceof Http2Protocol) {
customize((Http2Protocol) upgradeProtocol);
}
}
}
}

private void customize(Http2Protocol protocol) {
Compression compression = this.compression;
protocol.setCompression("on");
protocol.setCompressionMinSize(getMinResponseSize(compression));
protocol.setCompressibleMimeType(getMimeTypes(compression));
if (this.compression.getExcludedUserAgents() != null) {
protocol.setNoCompressionUserAgents(getExcludedUserAgents());
}
}

private void customize(AbstractHttp11Protocol<?> protocol) {
Compression compression = this.compression;
protocol.setCompression("on");
protocol.setCompressionMinSize(getMinResponseSize(compression));
protocol.setCompressibleMimeType(getMimeTypes(compression));
if (this.compression.getExcludedUserAgents() != null) {
protocol.setNoCompressionUserAgents(getExcludedUserAgents());
}
}

private int getMinResponseSize(Compression compression) {
return (int) compression.getMinResponseSize().toBytes();
}

private String getMimeTypes(Compression compression) {
return StringUtils.arrayToCommaDelimitedString(compression.getMimeTypes());
}

private String getExcludedUserAgents() {
return StringUtils.arrayToCommaDelimitedString(this.compression.getExcludedUserAgents());
}

}

tomcat的做法是拿到excludedUserAgent然后根据逗号进行分割数组,相关代码如下

/**
* Convert a {@code String} array into a comma delimited {@code String}
* (i.e., CSV).
* <p>Useful for {@code toString()} implementations.
* @param arr the array to display (potentially {@code null} or empty)
* @return the delimited {@code String}
*/
public static String arrayToCommaDelimitedString(@Nullable Object[] arr) {
return arrayToDelimitedString(arr, ",");
}

跟随代码一路往下看,找到(说明支持正则表达式匹配)

public void setNoCompressionUserAgents(String noCompressionUserAgents) {
if (noCompressionUserAgents == null || noCompressionUserAgents.length() == 0) {
this.noCompressionUserAgents = null;
} else {
this.noCompressionUserAgents =
Pattern.compile(noCompressionUserAgents);
}
}

undertow

笔者用的是undertow,相关代码

org.springframework.boot.web.embedded.undertow.CompressionHttpHandlerFactory
相关代码

private static Predicate[] getCompressionPredicates(Compression compression) {
List<Predicate> predicates = new ArrayList<>();
predicates.add(new MaxSizePredicate((int) compression.getMinResponseSize().toBytes()));
predicates.add(new CompressibleMimeTypePredicate(compression.getMimeTypes()));
if (compression.getExcludedUserAgents() != null) {
for (String agent : compression.getExcludedUserAgents()) {
RequestHeaderAttribute agentHeader = new RequestHeaderAttribute(new HttpString(HttpHeaders.USER_AGENT));
predicates.add(Predicates.not(Predicates.regex(agentHeader, agent)));
}
}
return predicates.toArray(new Predicate[0]);
}

undertow这里不拐弯抹角,直接就能看到,支持正则表达式

举报

相关推荐

0 条评论