zoukankan      html  css  js  c++  java
  • spring/springboot/springmvc启用GZIP压缩

    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这里不拐弯抹角,直接就能看到,支持正则表达式

    本博客文章绝大多数为原创,少量为转载,代码经过测试验证,如果有疑问直接留言或者私信我。
    创作文章不容易,转载文章必须注明文章出处;如果这篇文章对您有帮助,点击右侧打赏,支持一下吧。
  • 相关阅读:
    [K/3Cloud] 首页增加一个自定义页签及页面内容
    [K/3Cloud]DBServiceHelper.ExecuteDataSet(this.Context, sql)) 返回数据问题
    [K/3Cloud] 表单python脚本使用QueryService的做法
    [K/3Cloud]有关单据显示行数限制和数据导出的建议
    [K/3Cloud]实现双击列表行后显示具体的某个单据明细。
    [K/3Cloud]K3Cloud的移动审批方面
    [K/3Cloud]K3Cloud的移动审批方面
    [K/3Cloud]关于数据库sa密码更改,管理中心登录不上的问题。
    游戏编程最前沿....
    marmalade android 5.0 JNI 调用失败的解决方案
  • 原文地址:https://www.cnblogs.com/passedbylove/p/14344277.html
Copyright © 2011-2022 走看看