我该如何使用JSF 2 h:outputStylesheet实现“CSS版本控制”(以解决缓存问题)?

10

我开始使用JSF 2,所以想尝试使用h:outputStylesheet。它很好用,但是我试图应用添加查询字符串到请求的“模式”或技巧,该查询字符串会随着文件版本更改而变化,以强制浏览器获取更改内容。

类似于这里使用的方法

不幸的是,我无法实现它。实际上,使用该标签时,它并不生成简单的URL,而是生成一个已经有查询字符串的计算URL。我在规范和这里找到了一些关于JSF 2资源版本控制的信息,但它似乎涉及到多个版本的资源,而不是我需要的。

当然,我可以回到旧的使用方式。但我想在这里分享并讨论这个问题。

更新1- 一些示例:

我尝试的是像这样的代码:

<h:outputStylesheet library="css" name="estilo.css?v=1" target="head"/>

它的渲染效果为:

<link type="text/css" rel="stylesheet" href="RES_NOT_FOUND" />

相当具有描述性。;-)

我试图得到的是这样的内容:

<link rel="stylesheet" type="text/css" href="../css/estilo.css?v=1"/>

以前我会用 JSP 来实现这个功能,代码如下:

<link rel="stylesheet" type="text/css"
 href="<c:url value='/css/estilo.css?v=${initParam.version}'/>"/>

你能发一下你尝试过的例子吗? :) - Martijn Verburg
非常好奇这个。这个功能应该被捆绑在每个Web框架中。你已经为静态资源添加了过期的HTTP头吗?否则,为什么需要这样做(否则客户端将始终发出请求以检查文件是否已更改并在其更改时更新...不是吗)? - Tuukka Mustonen
@Tuuka:这是一种以动态内容开发Web应用程序的技巧。如果您在“estilo.css”中更改了某些内容并发布了新版本,则最近访问过您的用户可能不会立即下载新版本。对于JS来说,情况更糟,因为它可能会破坏功能。这个“技巧”利用了浏览器使用查询字符串来决定是否下载资源的事实。因此,查询字符串(可以是任何内容)实际上什么也没做。只需在内容更改时更改它即可。而且很容易更改URL,因为您已经生成了HTML。 - sargue
我非常同意这个观点。我本来想在Mojarra项目页面上报告一个增强请求,但由于它将来要迁移到另一个站点,目前已被禁用。我有一个修复的理论,但必须先自己尝试一下。 - BalusC
@Sergi @BalusC 是的,但浏览器不管如何都会创建一个请求,对吗?我不知道服务器或浏览器如何将缓存文件与浏览器请求的文件进行比较,但如果有任何更改(在文件大小、某些哈希等方面,我不知道),浏览器应该下载新文件。因此,我认为只有在设置了过期的HTTP标头并生效时,以及浏览器甚至不会执行通常所做的检查请求时,才需要这个功能。正确吗? - Tuukka Mustonen
1个回答

10
面对同样的挑战,我最终扩展了javax.faces.application.ResourceHandlerWrapper和javax.faces.application.ResourceWrapper,以在ResourceWrapper#getRequestString()的结果后附加"&v=x.y.z"。
我看到Primefaces和Openfaces也实现了这种解决方案。只需查看源代码即可。
org.primefaces.application.PrimeResourceHandler#createResource(String resourceName, String libraryName)

org.primefaces.application.PrimeResource#getRequestPath()

这里可供查看

别忘了将你的实现添加到 faces-config.xml 中:

<application>
  <resource-handler>your.package.YourResourceHandlerWrapper</resource-handler>
</application>

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