如何通过 JSF 中的上下文路径获取基 URL?

我有这样的结构:

WebContent
resources
components
top.xhtml


company
about_us.xhtml


index.xhtml

top.xhtml是一个组件,也用于 index.xthmlabout_us.xhtml

top.xhtml

<ul>
<li><a href="index.xhtml">Home</a></li>
<li><a href="company/about_us.xhtml">About us</a></li>
...
</ul>

所以我的问题是,当当前页面是 index.xhtml时,组件正确地生成 URL,但是当当前页面是 about_us.xhtml时,它生成错误的 URL。我不能使用相对路径,因为它也会生成错误的 URL。我认为这是因为组件基于 *.xhtml页面的当前路径。

我能找到的唯一解决办法就是:

<ul>
<li><a href="${pageContext.request.contextPath}/webname/index.xhtml">Home</a></li>
<li><a href="${pageContext.request.contextPath}/webname/about_us.xhtml">About us</a></li>
...
</ul>

但我觉得一点也不“优雅”。有什么想法吗?

123388 次浏览

URL 不会根据服务器端的文件结构进行解析。URL 是根据相关资源的真实公共网址来解析的。也就是说,需要调用它们的是网络浏览器,而不是网络服务器。

有几种方法可以减轻痛苦:

JSF EL 提供了 #{request}风格的 ${pageContext.request}的简写:

<li><a href="#{request.contextPath}/index.xhtml">Home</a></li>
<li><a href="#{request.contextPath}/about_us.xhtml">About us</a></li>

如果有必要,可以使用 <c:set>标签使其更短。把它放在主模板的某个地方,所有页面都可以看到:

<c:set var="root" value="#{request.contextPath}/" />
...
<li><a href="#{root}index.xhtml">Home</a></li>
<li><a href="#{root}about_us.xhtml">About us</a></li>

JSF 2.x 提供了 <h:link>,它可以获取相对于 outcome中上下文根的视图 ID,并且它会自动附加上下文路径和 FacesServlet映射:

<li><h:link value="Home" outcome="index" /></li>
<li><h:link value="About us" outcome="about_us" /></li>

HTML 提供了 <base>标记,使得文档中的所有相对 URL 都相对于这个基址。你可以利用它。放进 <h:head>

<base href="#{request.requestURL.substring(0, request.requestURL.length() - request.requestURI.length())}#{request.contextPath}/" />
...
<li><a href="index.xhtml">Home</a></li>
<li><a href="about_us.xhtml">About us</a></li>

(注意: 这需要 EL 2.2,否则最好使用 JSTL fn:substring(),另见 这个答案)

这应该在生成的 HTML 中结束,类似于

<base href="http://example.com/webname/" />

请注意,<base>标签有一个警告: 它使所有跳转锚在页面像 <a href="#top">相对于它以及!另请参阅 是否建议使用 < base > html 标记?在 JSF 中您可以像 <a href="#{request.requestURI}#top">top</a><h:link value="top" fragment="top" />那样解决它。

从 BalusC 应答中利用的 JSTL 1.2变体

<c:set var="baseURL" value="${pageContext.request.requestURL.substring(0, pageContext.request.requestURL.length() - pageContext.request.requestURI.length())}${pageContext.request.contextPath}/" />


<head>
<base href="${baseURL}" />