【问题标题】:Spring MVC and Thymeleaf Resource VersioningSpring MVC 和 Thymeleaf 资源版本控制
【发布时间】:2018-07-21 19:42:47
【问题描述】:

我正在尝试使用 Spring Mvc 4 进行资源版本控制。我使用 thymeleaf 模板引擎。但不适用于以下代码。加载页面时,当我查看页面源时看不到新版本的 Url。那么我的问题是什么代码?我想念什么?

@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/static/theme*//**").addResourceLocations("/resources/static/theme/")
            .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
            .resourceChain(false)
            .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
            .addTransformer(new CssLinkResourceTransformer());
    registry.addResourceHandler("/static*//**").addResourceLocations("/resources/static/")
            .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
            .resourceChain(false)
            .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
            .addTransformer(new CssLinkResourceTransformer());
    registry.addResourceHandler("/static/js*//**").addResourceLocations("/resources/static/js/")
            .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
            .resourceChain(false)
            .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
            .addTransformer(new CssLinkResourceTransformer());
}

@Bean
public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
    return new ResourceUrlEncodingFilter();
}

我在脚本标签中使用 with 表达式。 th:src="@{/resources/static/js/companyList.js}"

【问题讨论】:

  • 我有非常相似的非工作代码;对我来说,它没有设置缓存控制标头,表明它没有使用处理程序。您的版本是否将标头设置为 365 天?
  • 我的问题是相关的资源路径。错误创建的 url 导致了问题。当你查看页面的源代码时你能看到带有 md5 的版本控制 url 吗?如果你看到问题仍然存在?我的问题解决了,现在我可以看到 365 天的缓存头了。

标签: javascript java spring-mvc caching thymeleaf


【解决方案1】:

我没有代码管理它,只在 application.properties 中配置:

# Enable HTML5 application cache manifest rewriting.
spring.resources.chain.html-application-cache=true

# Enable the Spring Resource Handling chain. Disabled by default unless at least one strategy has been enabled.
spring.resources.chain.enabled=true
# Enable the content Version Strategy.
spring.resources.chain.strategy.content.enabled=true
# Comma-separated list of patterns to apply to the Version Strategy.
spring.resources.chain.strategy.content.paths=/**

我不需要添加任何其他代码来获取 CSS 和 JS 的 URL 中的哈希版本。

【讨论】:

【解决方案2】:

1. 创建 Thymeleaf LinkBuilder,使用 Spring 的 ResourceUrlProvider 创建版本化链接:

@Configuration
public class TemplateEngineConfig {
    @Autowired
    public void configureTemplateEngine(SpringTemplateEngine engine,
                                        ResourceUrlProvider urlProvider) {
        engine.setLinkBuilder(new VersioningLinkBuilder(urlProvider));
    }
}

class VersioningLinkBuilder extends StandardLinkBuilder {
    private final ResourceUrlProvider urlProvider;

    VersioningLinkBuilder(ResourceUrlProvider urlProvider) {
        this.urlProvider = urlProvider;
    }

    @Override
    public String processLink(IExpressionContext context, String link) {
        String lookedUpLink = urlProvider.getForLookupPath(link);
        if (lookedUpLink != null) {
            return super.processLink(context, lookedUpLink);
        } else {
            return super.processLink(context, link);
        }
    }
}

2.使用百里香标签th:hrefth:src

<link th:href="@{/main.css}" rel="stylesheet" type="text/css"/>
<script th:src="@{/js/main.js}" type="text/javascript"></script>

它将被转换为:

<link href="/main-0c362e5c8643b75ddf64940262b219f7.css" rel="stylesheet" type="text/css"/>
<script src="/js/main-c13acb86fa1012e27bbb01a7c4a9bf7f.js" type="text/javascript"></script>

3.(可选)还建议添加浏览器缓存头。添加到您的application.properties

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
spring.resources.cache.cachecontrol.max-age=365d
spring.resources.cache.cachecontrol.no-cache=false
spring.resources.cache.cachecontrol.no-store=false
spring.resources.cache.cachecontrol.cache-public=true

或者如果你使用application.yml:

spring:
  resources:
    chain:
      strategy:
        content:
          enabled: true
          paths: /**
    cache:
      cachecontrol:
        max-age: 365d
        no-cache: false
        no-store: false
        cache-public: true

【讨论】:

  • 我在上下文中部署了我的应用程序,因此在链接处理期间,我不得不删除并最近附加了上下文路径。思路如下: if (linkToProcess.startsWith(servletContext.getContextPath()){...} ... return super.processLink(context, servletContext.getContextPath() + linkToProcess);
  • 这在 Spring Boot 2.4 上对我有用,感谢您的撰写!
【解决方案3】:

以下内容对我有用:

application.yml

...
resources:
  chain:
    strategy:
      content:
        enabled: true
        paths: /js/**,/css/**
...

index.html

...
<script th:src=@{/js/home.js}></script>
...

结果

这会呈现如下内容:

...
<script src=/js/home-440273f30b71d3cf4184b48ce5e10b94.js></script>
...

【讨论】:

    【解决方案4】:

    这是我的解决方案。我调试Spring.ServletContextResource类的源代码创建一个relativeRelative。然后检查资源是否存在。

    资源位置:/resources/static/

    路径:/static/css/login.css

    pathToUse : /resources/static/static/css/login.css --> 这个资源url不存在所以返回null。

    ServletContextResource 类

    @Override
    public Resource createRelative(String relativePath) {
        String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);
        return new ServletContextResource(this.servletContext, pathToUse);
    }
    

    解决方案: 资源位置:/resources/static/

    路径:/css/login.css

    pathToUse : /resources/static/css/login.css

    现在我包含这种格式。从路径中删除 /resources。

    th:src="@{/css/login.css}"

               @Override
               public void addResourceHandlers(final ResourceHandlerRegistry registry) 
               {
    
                    registry.addResourceHandler("/theme*//**").addResourceLocations("/resources/static/")
                            .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
                            .resourceChain(false)
                            .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
                            .addTransformer(new CssLinkResourceTransformer());
                    registry.addResourceHandler("/css*//**").addResourceLocations("/resources/static/")
                            .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
                            .resourceChain(false)
                            .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
                            .addTransformer(new CssLinkResourceTransformer());
                    registry.addResourceHandler("/js*//**").addResourceLocations("/resources/static/")
                            .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
                            .resourceChain(false)
                            .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
                            .addTransformer(new CssLinkResourceTransformer());
    
             @Override
             public void configure(final WebSecurity web) throws Exception {
     web.ignoring().antMatchers("/theme/**").antMatchers("/js/**").antMatchers("/css/**");
                }
    

    【讨论】:

      【解决方案5】:

      ResourceUrlEncodingFilter 的使用过滤了页面中的所有 url,这是不可取的并且会导致性能问题。我的解决方案如下:

      registry.addResourceHandler("/javascript/*.js", "/css/*.css", "/img/*")
                          .addResourceLocations("classpath:/static/javascript/", "classpath:/static/css/", "classpath:/static/img/")
                          .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
                          .resourceChain(true)
                          .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
      

      并在页面内部使用以下函数查找静态资源

      <script th:src="${@mvcResourceUrlProvider.getForLookupPath('/javascript/app.js')}"></script>
      

      【讨论】:

        猜你喜欢
        • 2019-05-16
        • 2013-08-25
        • 2017-09-21
        • 2012-04-13
        • 1970-01-01
        • 2020-10-27
        • 2017-04-07
        • 2016-04-19
        • 2014-12-01
        相关资源
        最近更新 更多