有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用ContentVersionStrategy的java Spring引导缓存禁止使用gzip进行资源压缩

我们有一个带有Thymeleaf的Spring Boot web应用程序。 在HTML模板中,我们引用了一些静态资源,例如/src/main/resources/static/js/main.js通过<script defer th:src="@{/js/main.js}"></script>

为了允许浏览器缓存静态资源,以便多次访问我们的网站,我们启用了内容版本控制:

spring.resources:
    chain:
      strategy.content:
        enabled: true
        paths: /**
    cache.cachecontrol.max-age: 365d

这一切都很好,我们得到的资源将其MD5哈希附加到文件名(例如/main-d9f17fd70ee583fef4acf26dd331b8ab.js

为了进一步减少通信量,我们现在希望使用gzip启用资源压缩:

server:
  compression:
    enabled: true
    mime-types: application/javascript,and-some-others
    min-response-size: 1024

当请求头为Accept-Encoding='gzip'的(版本化)资源时,我们不会得到Content-Encoding='gzip'的响应。因此,资源压缩似乎不能与内容版本控制一起工作

如果我们禁用内容版本控制,资源压缩就可以正常工作:为(现在没有版本控制的)资源设置Content-Encoding='gzip'

因此,我们深入研究了Spring的内部,发现了以下内容:

  1. org.springframework.web.servlet.resource.VersionResourceResolver#getResponseHeaders始终设置(强)ETag头:
public HttpHeaders getResponseHeaders() {
    HttpHeaders headers = (this.original instanceof HttpResource ?
            ((HttpResource) this.original).getResponseHeaders() : new HttpHeaders());
    headers.setETag("\"" + this.version + "\"");
    return headers;
}
  1. org.apache.coyote.CompressionConfig#useCompression如果存在强ETag,则禁用压缩:
public boolean useCompression(Request request, Response response) {
    ...
    if (noCompressionStrongETag) {
        String eTag = responseHeaders.getHeader("ETag");
        if (eTag != null && !eTag.trim().startsWith("W/")) {
            // Has an ETag that doesn't start with "W/..." so it must be a
            // strong ETag
            return false;
        }
    }
    ...
}

您可以将noCompressionStrongETag设置为false,但这已被弃用,并将使用Tomcat 10删除

为了证明这个问题,我创建了一个example project in Github测试,其中有三个通过测试,一个失败测试,显示我们的期望没有得到满足

你有办法解决这个矛盾吗?我们做错什么了吗


共 (1) 个答案

  1. # 1 楼答案

    该问题现在在Spring's Github repository中跟踪。目前的想法是在Spring的VersionResourceResolver中从强etag切换到弱etag

    更新:该问题通过Spring 5.3附带的Spring Boot 2.4解决。包含修复

    一位贡献者在本期文章中强调,当前行为与Tomcat addressedhere中的修复程序相关联。在这里,我们得出结论,响应压缩违反了强ETag的含义,因此是一个bug。因此,Tomcat仅在不存在或仅存在弱ETag头的情况下应用压缩(这与我在SO问题中描述的观察结果一致)