【问题标题】:External facelets template - does it get cached?外部 facelets 模板 - 它是否被缓存?
【发布时间】:2013-03-31 23:17:30
【问题描述】:

由于显示来自外部源的标头的给定要求,我们提出了以下设置(在 Tomcat 7 上使用 JEE6):

我们的页面经常使用模板:

...
<ui:composition ... template="/WEB-INF/templates/template.xhtml">
...

这个模板除了布局页面结构外,还包括另一个 XHTML 文件:

...
<h:body>
  <ui:include src="./header.xhtml" />
...

然后包含的文件再次使用模板,但这次指向外部资源,该资源返回包含要使用的标头的&lt;div&gt; 元素:

...
<ui:composition ... template="http://someserver/somefile">
...

我知道这个设置有点奇怪,但是为了包含外部生成的&lt;div&gt; 元素,我们必须在页面中包含该元素。 (如果有人可以为给定问题提供更智能的解决方案,我会很高兴。)

到目前为止,这工作正常,但似乎是这种情况,这个包含的文件被我们的 Tomcat 缓存,导致在更改后不显示当前标题。如果 Tomcat 重新启动,则会显示新的标头。

谁能告诉我这一切是如何在幕后工作的,以及它是否与 Facelets、Tomcat 或我的特定设置有关?

【问题讨论】:

  • 哪个 JSF 实现/版本?哪个JSF项目阶段?例如。 MyFaces 在非开发阶段通常会积极缓存,如果您不耐烦,则确实需要重新启动。
  • @BalusC 我们在 2.1.3-b02 版本中使用对 com.sun.faces.jsf-impl 的依赖。我们没有明确设置 javax.faces.PROJECT_STAGE,但我们有 facelets.DEVELOPMENT 为 true,也许这与此有关。那个时候可以禁用缓存吗?客户的要求是,他希望尽快在应用程序中看到对标头的更改(当然,如果可能的话,无需重新启动)。

标签: jsf-2 tomcat7 java-ee-6 facelets


【解决方案1】:

您可以使用不同级别的多种解决方案: 您可以只实现 ResourceResolver 并包含来自已定义 URL 的模板(具有已定义的 URL,如 external-resource/header.xhtml)。此 ResourceResolver 可能配置有外部引用。

下一个可能性是有一个 ServletFilter 来处理你的 HTML 并在定义的位置添加标题。

最后,您可以实现一个简单的自定义组件,使用 jQuery 等在服务器或客户端加载标头。

您通常不希望在 facelets 上禁用缓存,因为它会降低性能。

【讨论】:

  • 这听起来像是解决问题的好选择,所以即使我还没有测试它,我也会奖励它。
【解决方案2】:

在 JSF 2(即 Facelets 中)中,模板是一段静态内容,其中可以包含动态内容。

如果你想使用不同的模板,首先你必须用不同的URL路径指向不同的页面,然后不同的页面可以使用不同的模板:

<ui:include src="./header{$HeaderTemplateSuffix}.xhtml" />

那么headerABC.xml可以有:

...
<ui:composition ... template="http://someserver/somefileABC">
...

和 headerDEF.xml 可以有

...
<ui:composition ... template="http://someserver/somefileDEF">
...

或者,您可以放弃对标头使用模板,并动态生成所有标头内容(甚至包括静态部分)。

注意:将 html 标头模板合并回主模板并不是解决此问题的方法,因为它没有解决标头模板是动态的核心挑战。

希望对您有所帮助!干杯:^)


注意:可以在web.xml中设置如下:

<!-- Time in seconds that facelets should be checked for changes since last request. A value of -1 disables refresh checking. -->
<context-param>
    <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
    <param-value>0</param-value>
</context-param>

<!-- Set the project stage to "Development", "UnitTest", "SystemTest", or "Production". -->
<!-- An optional parameter that makes troubleshooting errors much easier. -->
<!-- You should remove this context parameter before deploying to production! -->
<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

但是,这旨在服务于一个完全不同的目的:允许开发人员即时更改任何静态资源,JSF 容器将动态检查更改并在开发期间加载它。您无意使用它来模拟动态模板,并且设置上述属性将对您的生产环境中的性能和安全行为产生负面影响。

【讨论】:

  • 感谢您的 cmets。你提到,我可以指向不同的外部页面,但在我们的例子中,标题总是来自给定的 URL,它为我们提供了我们必须使用的当前标题。所以 URL 总是相同的,但它的内容会随着时间而改变。你提到放弃对标题使用模板并动态生成内容,但是如何?同样,内容不在我们手中,它来自为我们提供静态 html div 块的外部源。
  • 这可能行得通。只要您在每种情况下都有不同的包含文件 headerXXX.html,您可能可以指向相同的模板 URL (template="someserver/somefile"),但您必须确保它返回不同的在每种情况下都有适当的标头模板。我不确定您如何在始终重用相同的 URL 的同时实现适当的模板??如果仍然有问题,可以轻松解决:只需在服务器上引入额外的标头模板 URL - 如果需要,它们可以通过 web.xml 映射到相同的资源(servlet/JSP)。
  • 也许我还不够清楚 - 在我们的应用程序中只有一个标题模板,它永远不会改变,所有页面都使用相同的标题 XHTML,从来没有其他东西。但是,指向外部 URL 的此标头的 content 可能会发生变化。因此,某些 CMS 人员可能决定将标题设置为绿色而不是白色,并且它应该在我们的应用程序中显示为绿色,因为我们所做的只是包含一个外部 HTML DIV,我们对此一无所知,只是将其显示在标题应该出现的位置在我们的页面中。
猜你喜欢
  • 2011-02-28
  • 2011-04-09
  • 1970-01-01
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
相关资源
最近更新 更多