使用 JBoss 对静态内容进行自动版本控制

Posted

技术标签:

【中文标题】使用 JBoss 对静态内容进行自动版本控制【英文标题】:Auto-versioning of static content with JBoss 【发布时间】:2011-02-07 12:32:01 【问题描述】:

根据 Q&A here,我想为在 JBoss 5 中运行的 Web 应用程序实现一个类似的自动版本控制系统。是否已经有任何东西可以做这种事情,或者我需要自己写点什么?明确一点:我没有使用 PHP。

php 了解不多,我不确定 PHP 的 .htaccess 等的 Tomcat/JBoss 类似物是什么。如果我必须编写自己的自动版本控制,我该从哪里开始?原理对我来说很清楚 - 使用文件的时间戳重写 URL,但我不太了解使用 JBoss/Tomcat 重写 URL。


更新:

结合Pascal 和novice 推荐的方法,我得到了以下结果:

1.自定义<my:script/><my:style/>标签,这样我就不必到处看到<c:url/>标签了。

<%@ tag body-content="empty" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ attribute name="src" required="true" rtexprvalue="true" %>
<script src="<c:url value="$src" />"></script>

2. 非常接近新手的步骤,但在 web.xml 中将 UrlRewriteFilter 映射到 /*

<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3. 将 CACHE_BUST 变量注入每个新会话(或多或少...),应用程序部署 timestamp:

// On application deploy:
long CACHE_BUST = System.currentTimeMillis() / 1000;

// later...
session.setAttribute("cacheBust", CACHE_BUST);

4. ...以便我可以在urlrewrite.xml 中使用这些规则:

<outbound-rule>
    <from>^/static/(css|js|images)/(.*)$</from>
    <to>%context-path/static/%session-attribute:cacheBust/$1/$2</to>
</outbound-rule>

<rule>
    <from>^/static/\d10/(css|js|images)/(.*)$</from>
    <to>/static/$1/$2</to>
</rule>

非常感谢 Pascal 和 novice 的帮助。

【问题讨论】:

【参考方案1】:

以下解决方案更适合生产环境,因为您将增加每个版本的版本号。

方法:

将产品发布号(版本号)附加到jsp文件中的js/css/images/static内容url 浏览器会缓存 (js/css/static) 带有版本号的 url 文件 当新版本发布时,jsp文件中会有新版本号的js/css/static文件的url,所以浏览器会因为找不到新url的内容而进行调用李>

步骤:

在类路径中包含urlrewritefilter.jar(从http://www.tuckey.org/urlrewrite/获取)

使用 url 模式更新 web.xml,例如,

<filter>
    <filter-name>urlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>urlRewriteFilter</filter-name>
  <url-pattern>/v/*</url-pattern>
</filter-mapping>

更新 jsp 文件中的“abc.js”,例如,

<html>
    <head>
        <script type="text/javascript" src="<c:url value="/v/js/abc.js"/>"></script>
    </head>
</html>

编写 urlrewritefilter.xml,例如,

<outbound-rule>
    <from>^/v/(css|js|static)/(.*)$</from>
    <to>%context-path/v/updateVersionNumberHere/$1/$2</to>
</outbound-rule>

<rule>
    <from>^/v/updateVersionNumberHere/(css|js|static|images)/(.*)$</from>
    <to>/$1/$2</to>
</rule>

说明:

jsp 提供给客户端时

jsp中提到的url: /v/js/abc.js 应用出站规则后: /contextPath/v/3.4.5/js/abc.js

当浏览器调用 js/css/static 文件时

传入网址: /contextPath/v/3.4.5/js/abc.js 应用规则后: /js/abc.js

积分:

浏览器会捕获带有 url /contextPath/v/3.4.5/js/abc.js 的 js 文件,接下来你部署一个新版本的 jsp 文件,它们可能有 url /contextPath/v/4.5.6/js /abc.js,所以浏览器会调用 js 文件而不是使用缓存的 js 文件。 如果您使用 maven 或类似的构建工具,版本更新可以自动进行

【讨论】:

这看起来很有希望。将尽快测试。可能与@Pascal 的服务器启动时间建议结合使用。 写得很漂亮。谢谢!【参考方案2】:

如果您不想在应用程序前面使用 Apache HTTPD,那么您可以使用自定义 servlet 过滤器或重用现有的 Url Rewrite Filter。这个过滤器基于 Apache 的mod_rewrite 并提供类似的功能。换句话说,它将允许实现与 PHP 相同的解决方案之一。


我以前见过 URL 重写过滤器。您能否详细说明我将如何使用它?我真的不清楚如何对这个问题应用过滤器,因为我不会完全调用包装在每个包含的 JS/CSS 文件周围的 JSP/JSTL 函数,而且我不知道如何获取从 WAR 中的文件修改的日期。

嗯,这个想法是模仿你链接到的答案的“PHP解决方案”(我们称之为选项1):

    设置 URL 重写过滤器以将任何请求将 /css/my.123456.css 重写为 /css/my.css 实现一个Servlet,它将为WAR内的给定资源获取File对象,并将File#lastModified()插入到该资源的返回路径中。 从 JSP 中为 CSS 调用 Servlet

另一种方法(选项 2)是将唯一的查询字符串附加到静态内容的 URL,例如服务器启动时间:

    将服务器启动时间从ServletContextListener 放在应用程序范围内(比如在键"key" 下)。

    在你的 JSP 中

    <link rel="stylesheet" type="text/css" href="/css/my.css?$key.startupTime">
    

Pro:不再需要重写 url。缺点:不太理想(内容将在重新启动时请求)但可以接受。


在网上搜索一些有助于实现选项 1 的步骤 #2 的代码时,我发现 Spring 的 o.s.w.s.ResourceServlet 正在做类似的事情,您可以查看它的源代码。但是,在更仔细地阅读它的 javadoc 时,我意识到这个 servlet 实际上正是您正在寻找的。像这样映射它:

<servlet>
  <servlet-name>Resource Servlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.ResourceServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>Resource Servlet</servlet-name>
  <url-pattern>/static/*</url-pattern>
</servlet-mapping>

并将其applyLastModified 属性设置为true。我对 javadoc 的理解是它应该可以解决问题。这是选项 3,如果添加对此 servlet 的依赖不是问题,这是 IMO 的最佳选择。

【讨论】:

我以前见过 URL 重写过滤器。您能否详细说明我将如何使用它?我真的不清楚如何对这个问题应用过滤器,因为我不会完全调用包装在每个包含的 JS/CSS 文件周围的 JSP/JSTL 函数,而且我不知道如何获取从 WAR 中的文件修改的日期。【参考方案3】:

我们在网络应用中执行以下操作:

    构建过程检索 Subversion 存储库编号并将其存储在 Web 应用程序的属性中。 构建过程还会为 WAR 中的静态资产创建一个目录结构,其中包含此修订号:/assets/1234/styles/... 过滤器/拦截器将资产路径(包括修订号)作为属性放入所有请求中 Jsp 模板使用此资产路径属性来构造资产的 URL

【讨论】:

这没什么用。就像我说的,我明白了原则;我正在寻找实现细节。 我不知道有什么“内置”专门处理这个问题。我上面描述的正是我们的实现,对我们来说已经足够好了。

以上是关于使用 JBoss 对静态内容进行自动版本控制的主要内容,如果未能解决你的问题,请参考以下文章

版本控制工具GIT使用指南

nginx 中的自动版本控制 CSS/JS

使用 Git 进行版本控制

使用 S3 和 Cloudfront 的静态 Web 应用程序版本控制

进行 CDN 版本控制的最佳方法

Version Control