使用URL指纹技术在Java/Maven中管理激进缓存

5

我正在寻找最佳解决方案来管理浏览器缓存,以便在Java/Maven项目中重新加载修改后的JavaScript/CSS资源。 最广泛使用的解决方案似乎是使用Maven过滤器,在构建时向资源URL添加时间戳。例如:

<script type="text/javascript" src="resource.js?v=${maven.build.timestamp}"></script>

然而,最有效的方法是添加文件的校验和/哈希值(也称为指纹),而不是构建日期,这样资源在每次部署后不会重新加载,只有在必要时才会重新加载。

我急需使用Java或Maven插件来实现此模型的正确/通用实现,您有任何想法吗?

谢谢。

2个回答

3
你应该使用指纹技术而不是查询参数。查询参数方法并不总是有效,大多数代理服务器也无法缓存它。更改URL或实际文件名效果更好。
以下是我在Maven、Git、Tomcat和Dojo项目中处理此问题的方法。我使用http://mojo.codehaus.org/buildnumber-maven-plugin/来获取我的Git版本,并在构建WAR时使用过滤器将该值注入到我的JSP中。

pom.xml

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>buildnumber-maven-plugin</artifactId>
        <version>1.1</version>
        <executions>
            <execution>
                <phase>validate</phase>
                <goals>
                    <goal>create</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <doCheck>false</doCheck>
            <doUpdate>false</doUpdate>
            <shortRevisionLength>8</shortRevisionLength>
            <revisionOnScmFailure></revisionOnScmFailure>
        </configuration>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.3</version>
        <configuration>
            <warName>${project.name}-${project.version}-${buildNumber}</warName>
            <webResources>
                <resource>
                    <directory>src/main/webapp/WEB-INF/views/includes</directory>
                    <targetPath>WEB-INF/views/includes</targetPath>
                    <filtering>true</filtering>
                </resource>
            </webResources>                  
            ......
        </configuration>
    </plugin>

在我的主JSP包含文件中,我有:
<script src="${pageContext.request.contextPath}/${buildNumber}/static/js/ckeditor/ckeditor.js"></script>
<script src="${pageContext.request.contextPath}/${buildNumber}/static/js/build/dojo/dojo.js"  data-dojo-config="parseOnLoad: true"></script>

我将使用http://tuckey.org/urlrewrite/来进行重写。我只有一个简单的规则。
我的第一个过滤器条目在web.xml中。
<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    <init-param>
        <param-name>logLevel</param-name>
        <param-value>WARN</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

urlrewrite.xml

<rule match-type="regex">
    <from>^/[0-9A-Za-z_.\-]+/static/(.*)$</from>
    <to>/static/$1</to>
</rule>

1
感谢提供有用的URL重写部分。但是构建编号的行为与${maven.build.timestamp}几乎相同。即使它们没有改变,每个新版本都会重新下载您的资产。 - benweet
也许我误解了你的问题。你是想强制只部署更改过的文件吗? - denov
我将所有的JS代码编译和压缩到几个文件中,这样我就不用担心哪些文件发生了变化。用户只需要在每次更新时下载JS文件即可。 - denov

1

我还没有使用过它,但maven-fingerprint-plugin看起来不错。

只需要进行少量的maven配置,然后它就会自动重新构建文件中的所有url为指纹版本。

无需手动保留${buildNumber}${hashVersion}或其他资源URL中的指纹选项。

来自存储库:

<pluginRepositories>
    <pluginRepository>
        <id>fprint-repo</id>
        <url>https://raw.github.com/dernasherbrezon/maven-fingerprint-plugin/master/maven-fingerprint-plugin/mvn-repo</url>
    </pluginRepository>
</pluginRepositories>

那么

<executions>
    <execution>
        <phase>package</phase>
        <goals>
            <goal>generate</goal>
        </goals>
    </execution>
</executions>
<configuration>
    <excludeResources>
        <excludeResource>://</excludeResource>
        <excludeResource>//</excludeResource>
    </excludeResources>
    <!-- ${basedir}/src/main/webapp by default -->
    <sourceDirectory>${basedir}/target/webcombined</sourceDirectory>
    <!-- ${project.build.directory}/fingered-web by default -->
    <outputDirectory>${basedir}/target/fingered</outputDirectory>
    <!-- Remove unnecessary spaces between tags. Make single line page.
    Takes into consideration <pre> tags -->
    <trimTagExtensions>
        <trimTagExtension>html</trimTagExtension>
    </trimTagExtensions>
    <extensionsToFilter>
        <extensionToFilter>html</extensionToFilter>
        <extensionToFilter>jsp</extensionToFilter>
        <extensionToFilter>tag</extensionToFilter>
        <extensionToFilter>css</extensionToFilter>
        <extensionToFilter>js</extensionToFilter>
    </extensionsToFilter>
    <!-- cdn host. Not required. For example using
    "//accountname.r.worldssl.net": /css/bootstrap.css =>
    //accountname.r.worldssl.net/css/<md5>bootstrap.css -->
    <cdn>${cdn}</cdn>
</configuration>

就是这样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接