用于链接/导航到其他 JSF 页面的 URL

Posted

技术标签:

【中文标题】用于链接/导航到其他 JSF 页面的 URL【英文标题】:What URL to use to link / navigate to other JSF pages 【发布时间】:2015-08-21 09:51:26 【问题描述】:

当一些文件位于子文件夹中时,我对如何在 Java Server Faces 项目中的文件之间进行链接感到困惑。 (我打算附上屏幕截图,以便您可以看到 Nebeans 项目视图和我正在尝试的示例的文件视图......但我还不允许添加图像)。

在我的示例项目中,我有名为“index.xhtml”和“calculate/calculate.xhtml”的文件。我还有一个名为“template.xhtml”的文件,两者都使用。问题是在模板中使用哪种 url 格式适用于这两个文件。

在直接的 html 中,我将使用类似以下的内容来提供返回主页的链接,该链接可在任何位置工作:

<a href="/index.html">Home</a>

但我不知道什么是 JSF 应用程序的根文件夹,以及是使用“项目视图”文件夹结构还是“文件列表”文件夹结构。

【问题讨论】:

模板文件仅通过&lt;ui:include src="..."&gt;&lt;ui:insert name="..."&gt; 的方式包含在服务器端。客户端可以请求与该 URL 关联的资源的目标 URL 没有区别。迁移到 JSF 后,您观察到什么不同? 在我的模板中,如果我使用以下行: 在我的模板中,如果我使用&lt;a href="/index.xhtml" ..,那么 glassfish 服务器会认为它是http://localhost:8080/index.xhtml。但是,如果我使用&lt;a href="index.xhtml" ..,那么索引文件应该与 xhtml 文件位于同一文件夹中......所以我很困惑该怎么做 【参考方案1】:

首先,JSF 是一个 HTML 代码生成器。所以它在 J​​SF 中与在“普通”HTML 中没有什么不同。在 HTML 中创建链接时,您不应该只查看 webapp 项目中的文件系统结构。您应该查看这些资源的公共 URL 结构。即必须调用和下载这些资源的是网络浏览器,而不是网络服务器。网络浏览器对网络服务器中的文件系统结构一无所知。这并不特定于 JSF 项目。这适用于所有网络项目。

相对 URL 与其在 webapp 项目的文件系统结构中的位置无关。它们与当前打开的 HTML 文档的请求 URL 相关,正是您在浏览器地址栏中看到的那个。需要注意的是,当 HTML 文档中存在 &lt;base&gt; 元素时,HTML 文档中所有不以 / 开头的相对 URL 都将变为相对于它。

给定一个配置了FacesServlet映射URL模式*.xhtml的webapp,并以/context的上下文路径部署到localhost:8080,项目Web根目录中/index.xhtml文件的URL将如下:

http://localhost:8080/context/index.xhtml
----   -------------- ------- -----------
  |           |          |         `-- resource
  |           |          `-- path (can be multiple folders)
  |           `-- domain (and port)
  `-- scheme

如果您当前位于http://localhost:8080/context/index.xhtml,并且想要创建指向http://localhost:8080/context/calculate/calculate.xhtml 的链接,那么以下所有方式最终都会指向完全相同的绝对 URL。

// 开头的相对 URL 是相对于当前方案的。

<a href="//localhost:8080/context/calculate/calculate.xhtml">link</a>

/ 开头的相对 URL 是相对于域的。

<a href="/context/calculate/calculate.xhtml">link</a>

/ 开头的相对URL是相对于路径的。

<a href="calculate/calculate.xhtml">link</a>

当你目前在 http://localhost:8080/context/calculate/calculate.xhtml,并且你想链接到http://localhost:8080/context/index.xhtml,那么同样的规则适用:

// 开头的相对 URL 是相对于当前方案的。

<a href="//localhost:8080/context/index.xhtml">link</a>

/ 开头的相对 URL 是相对于域的。

<a href="/context/index.xhtml">link</a>

/ 开头的相对URL是相对于路径的。

<a href="../index.xhtml">link</a>

您现在可能已经意识到,以/ 开头的相对 URL依赖于当前路径和域。因此,这就是您真正希望在 Web 应用程序中随处使用的 URL,而不必担心在更改域或在服务器中移动文件时出现维护问题。唯一剩下的就是上下文路径的动态性。您可能已经知道这个值在 webapp 内部是无法控制的。您真的很想避免对其进行硬编码。但是,您可以在 EL 的帮助下轻松地让 JSF 以编程方式打印它。它仅由 HttpServletRequest#getContextPath() 提供,HttpServletRequest 在 EL 中可用作隐式对象 #request

<a href="#request.contextPath/index.xhtml">link</a>
<a href="#request.contextPath/calculate/calculate.xhtml">link</a>

每次重复此操作只会变得乏味。幸运的是,JSF 提供了&lt;h:link&gt; 组件,其目的就是为了生成一个HTML &lt;a&gt; 元素,并自动内联当前上下文路径。

<h:link value="link" outcome="index.xhtml" />
<h:link value="link" outcome="calculate/calculate.xhtml" />

注意outcome 必须代表一个JSF 视图ID,它不一定与URL 路径相同(当您将FacesServlet 映射到*.xhtml 时会这样)。您甚至可以在此处省略文件扩展名,JSF 会自动将其检测为“隐式导航”机制的一部分。

<h:link value="link" outcome="index" />
<h:link value="link" outcome="calculate/calculate" />

另见:

Is it recommended to use the <base> html tag? What are those URL's that are starting with // - that you can see within Google+ html source? JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why? Implicit objects in EL How to navigate in JSF? How to make URL reflect current page (and not previous one)

【讨论】:

很好的答案,谢谢!我在任何地方都找不到对这一切的体面描述。如果我缺少简明的文档资源,请告诉我。我正在研究Java EE 7 教程:第 1 卷:基本概念(Java 系列),但他们还没有涵盖这一点,而且他们的示例都没有在子文件夹中包含 xhtml 文件。我确实尝试过 href="#request.contextPath/index.xhtml" 之前并没有真正理解它在做什么,我猜当时还有其他问题。无论如何它现在正在工作,谢谢。 不客气。它不完全是 JSF。它只是 HTTP 和 HTML。了解 HTTP 和 HTML 确实是深入 JSF 之前的先决条件。在这种特定情况下,学习 JSF 需要了解 &lt;h:link&gt;#request.contextPath 的用途(尽管后者比 JSF 更特定于 Servlet+EL)。

以上是关于用于链接/导航到其他 JSF 页面的 URL的主要内容,如果未能解决你的问题,请参考以下文章

在 JSF 中使用 POST 请求导航到其他页面

链接中的 URL 片段和 JSF 中的 ajax 重定向

我可以在 JSF 导航规则中使用通配符 * 吗?

是否有用于实现面包屑导航的 JSF 组件?

JSF ViewParam 必需 +AJAX 中断页面

JSF 页面导航:意外的 RuntimeException