简体   繁体   English

Spring MVC和Thymeleaf资源版本控制

[英]Spring MVC and Thymeleaf Resource Versioning

资源层次结构我的项目

I am trying resource versioning with Spring Mvc 4.I use thymeleaf template engine.But doesnt work with the following code.When load the page I cant see new version Url when i view the page source.So what's the problem in my code? 我正在尝试使用Spring Mvc 4进行资源版本控制。我使用thymeleaf模板引擎。但是不适用于以下代码。加载页面时,当我查看页面源代码时无法看到新版本的网址。那么我的代码有什么问题? what am i miss? 我想念什么?

@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();
}

I am using with expression in script tag. 我正在脚本标记中使用表达式。 th:src="@{/resources/static/js/companyList.js}" th:src =“ @ {/ resources / static / js / companyList.js}”

I managed it with no code, only config in application.properties: 我没有代码,只有application.properties中的config来管理它:

# 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=/**

I didn't need to add any other code to get the hash version in the URLs for CSS and JS. 我不需要添加任何其他代码即可在CSS和JS的URL中获取哈希版本。

Here is the my solution.I debug source code of Spring.ServletContextResource class create a relativeRelative.Then check whether resource is exists. 这是我的解决方案。我调试Spring.ServletContextResource类的源代码创建一个relativeRelative。然后检查资源是否存在。

Resource location : /resources/static/ 资源位置:/ resources / static /

Path : /static/css/login.css 路径:/static/css/login.css

pathToUse : /resources/static/static/css/login.css --> this resource url not exists so return null. pathToUse:/resources/static/static/css/login.css->此资源网址不存在,因此返回null。

ServletContextResource class ServletContextResource类

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

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

Path : /css/login.css 路径:/css/login.css

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

Now I include this format.Remove /resources from path. 现在我包括这种格式。从路径中删除/ resources。

th:src="@{/css/login.css}" 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/**");
            }

1. Create Thymeleaf LinkBuilder that uses Spring's ResourceUrlProvider to create versioned links: 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. Use thymeleaf tags th:href and th:src 2.使用百里香标签th:hrefth:src

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

It will be converted to: 它将转换为:

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

3. (Optional) It is also recommended to add browser cache headers. 3. (可选)还建议添加浏览器缓存头。 Add to your application.properties : 添加到您的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

Or if you use application.yml : 或者,如果您使用application.yml

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

The usage of ResourceUrlEncodingFilter filters all urls in the page, which is not desirable and causes performance issues. 使用ResourceUrlEncodingFilter可以过滤页面中的所有URL,这是不希望的,并会导致性能问题。 My solution is the following: 我的解决方案如下:

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("/**"));

and inside the page using the below function to lookup the static resource 并在页面内部使用以下功能查找静态资源

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

The following worked for me: 以下为我工作:

application.yml application.yml

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

index.html index.html

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

Result 结果

This renders something like this: 这呈现出如下内容:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM