【问题标题】:VersionResourceResolver breaks CSS relative URLsVersionResourceResolver 破坏 CSS 相对 URL
【发布时间】:2015-03-05 10:27:29
【问题描述】:

我在 Spring Boot 1.2.2 中使用 VersionResourceResolver 进行缓存清除。不幸的是,它认为操纵 CSS 文件中指定的 URI 很聪明。

以 Twitters Bootstrap 为例。它会在 CSS 文件所在目录上方的目录中查找字体。

@font-face {
  font-family: 'Glyphicons Halflings';

  src: url('../fonts/glyphicons-halflings-regular.eot');
  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
}

如果没有 VersionResourceResolver,它会像预期的那样工作:

GET http://example.com/res/css/bootstrap.min.css
GET http://example.com/res/fonts/glyphicons-halflings-regular.woff

现在我添加 VersionResourceResolver:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/res/**")
            .addResourceLocations("/resources/")
            .setCachePeriod(CACHE_SECONDS)
            .resourceChain(true)
                .addResolver(new VersionResourceResolver()                      
                .addFixedVersionStrategy(buildVersion, "/**/"))
                .addResolver(new PathResourceResolver());       
}

现在发生了:

GET http://example.com/res/085a8/css/bootstrap.min.css
GET http://example.com/res/085a8/css/fonts/glyphicons-halflings-regular.woff

那么,为什么会这样呢?因为有人篡改了 CSS 文件中的 URI:

@font-face {
  font-family: 'Glyphicons Halflings';

  src: url('085a8/../fonts/glyphicons-halflings-regular.eot');
  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('085a8/../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('085a8/../fonts/glyphicons-halflings-regular.woff') format('woff'), url('085a8/../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
}

Bootstrap 只是一个例子。这发生在 CSS 资源中指定的几乎所有(奇怪的是不是所有的)URI 上。使用 Spring 的 CssLinkResourceTransformer 没有帮助。那么,我如何告诉 Spring 不要操作 CSS 文件呢?

编辑:我发现,Spring 调用了 CssLinkResourceTransformer。但我没有在任何地方指定。可能 Spring Boot 会在某个地方自动配置它。

03-05 16:12:47.711 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Transforming resource: ServletContext resource [/resources/css/bootstrap.min.css]
2015-03-05 16:12:47.716 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link modified: 77a6e2aa77283c05d58f4ab52102f55684b6fb04/../fonts/glyphicons-halflings-regular.eot (original: ../fonts/glyphicons-halflings-regular.eot)
2015-03-05 16:12:47.716 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link not modified: ../fonts/glyphicons-halflings-regular.eot?#iefix
2015-03-05 16:12:47.717 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link modified: 77a6e2aa77283c05d58f4ab52102f55684b6fb04/../fonts/glyphicons-halflings-regular.woff2 (original: ../fonts/glyphicons-halflings-regular.woff2)
2015-03-05 16:12:47.718 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link modified: 77a6e2aa77283c05d58f4ab52102f55684b6fb04/../fonts/glyphicons-halflings-regular.woff (original: ../fonts/glyphicons-halflings-regular.woff)
2015-03-05 16:12:47.719 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link modified: 77a6e2aa77283c05d58f4ab52102f55684b6fb04/../fonts/glyphicons-halflings-regular.ttf (original: ../fonts/glyphicons-halflings-regular.ttf)
2015-03-05 16:12:47.719 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link not modified: ../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular

Edit2:如果你注册了 RessourceChain -.-,Spring 会自动创建一个 CssLinkResourceTransformer。见https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceChainRegistration.java#L112

【问题讨论】:

    标签: css spring-mvc spring-boot


    【解决方案1】:

    Spring 4.1+ 中的资源处理

    您使用的 VersionStrategy FixedVersionStrategy 是为处理文件名以加载 JavaScript 模块的 JavaScript 模块加载器量身定制的。

    由于您使用的是 JavaScript 模块加载器 (require.js),因此对 CSS/图像使用 ContentVersionStrategy 并为 JS 使用 FixedVersionStrategy 更适合您的应用程序。因此,将您的配置更改为此应该可以解决它:

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
        VersionResourceResolver versionResolver = new VersionResourceResolver()
                .addFixedVersionStrategy(version, "/**/*.js")
                .addContentVersionStrategy(version, "/**/*.css", "/**/*.png");
    
        registry.addResourceHandler("/res/**")
                .addResourceLocations("/resources/")
                .setCachePeriod(CACHE_SECONDS)
                .resourceChain(true)
                    .addResolver(versionResolver);
    }
    

    请注意,您不需要注册 PathResourceResolverCssLinkResourceTransformer,因为它是通过检查您的配置为您完成的(您已经通过阅读源代码了解了这一点)。

    现在,为了更好地了解该功能,我建议您阅读this blog post 并查看this example application

    SPR-12669 JIRA 问题

    实际上,此问题与您的用例无关,本身也不是错误。 Guillaume 创建了WUIC project,我们正在讨论如何更好地将这个资产管道集成到 Spring 项目中。因此,作为一名框架开发人员,他正在为 WUIC 用户寻找更多的灵活性——资源处理功能本身可以正常工作。

    您所描述的解决方法并非旨在用于应用程序,因为您没有充分理由手动进行大量管道检查,而不是依赖 Spring 的默认设置。

    另外,请注意,我们在这里讨论的默认值是由 Spring Framework 设置的,而不是由 Spring Boot 设置的。 Spring Boot 是“唯一的”autoconfiguring well-known locations to serve static resources

    【讨论】:

    • 感谢您的回答。我正在使用 RequireJS 加载我的 JavaScript 模块,因此我需要使用 VersionResourceResolver。这个解析器从最新的 git 提交中获取哈希并以这种方式操作我的 URI:/res/js/require.js 到 /res/{gitHash}/js/require.js。在 RequireJS 的配置中,我将 baseUrl 设置为“/res/{gitHash}/js/”。完美运行。问题在于 CSS 文件中 URL 的处理。见原帖。
    • 我已经更新了我的 anwser。您可以使用多种版本策略来满足您的需求。
    • 非常感谢!这工作得很好:-)我昨天花了几个小时让它工作......:D
    • 虽然避免 FixedVersionStrategy 是解决此问题的一种方法,但我仍然认为 CssLinkResourceTransformer 在使用 FixedVersionStrategy 时不应破坏 CSS URL 中的相对路径。为什么 FixedVersionStrategy 不适合 CSS 文件?
    • 我为 FixedVersionStrategy + CssLinkResourceTransformer 的这种行为写了一个问题:jira.spring.io/browse/SPR-13727
    【解决方案2】:

    这种行为的原因是,如果你创建了一个 ResourceChain,Spring 会自动创建一个 CssLinkResourceTransformer。您可以在他们的sourcecode 中看到它。这是他们框架中的默认配置。

    不幸的是,它破坏了 CSS 文件中的相对路径。为了避免CssLinkResourceTransformer的默认配置,需要自己做ResourceHandling。例如这个way(不推荐!)。

    【讨论】:

    • Daniel,请看一下我的回答——您可能想要更新那个答案,因为它向 Spring 开发人员发送了错误消息。另外,你能用你正在使用的 Spring Framework 版本更新你的问题吗?我不确定 FixedVersionStrategy 是否应该尝试更新相对路径(这可能是一个错误)
    • Brian,我用我正在使用的 Spring Boot 版本更新了我的原始帖子。我使用 Spring Boot “自动”提供的 Spring Framework 版本。将更新我的上述答案,以澄清这不是“错误”。
    • 它“破坏”了 CSS 文件的路径,因为您还将 FixedVersionStrategy 映射到 CSS 文件......
    猜你喜欢
    • 2019-05-16
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 2013-08-19
    • 2012-04-01
    相关资源
    最近更新 更多