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

73

我有这样的结构:

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>

但我认为这并不算是“优雅”的。有什么想法吗?

2个回答

157
URL不是基于服务器端的文件结构解析的。URL是基于所需资源的真实公共Web地址解析的。即Web浏览器必须调用它们,而不是Web服务器。

有几种方法可以缓解痛苦:

JSF EL提供了一种缩写方式${pageContext.request},以#{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都相对于此基础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" />

3
非常感谢,我是你的忠实粉丝 =) 我希望能够像你一样成为一个出色的开发者,谢谢。 - Valter Silva
好的解决方案,不知道这是可能的!谢谢分享! - Robert M.
1
@balusC 是的,ui:param 方法在 MyFaces 中不起作用。 - Rajat Gupta
1
@Aklin:我修复了答案,谢谢你。我之前不知道这是Mojarra特有的问题,实际上我也从未看到过关于这个问题的Mojarra报告。 - BalusC
1
@Aklin:也许又是MyFaces的问题。尝试添加 scope="request" - BalusC
显示剩余8条评论

1
JSTL 1.2的变化,借鉴自BalusC的答案。
<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}" />

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