Как получить базовый URL?

У меня есть эта структура:

WebContent
    resources
        components
            top.xhtml

    company
        about_us.xhtml

    index.xhtml

top.xhtml - это компонент, который также используется в index.xthml и about_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>

Но я думаю, что это не "элегантный". Любые идеи?

Ответ 1

URL-адреса не разрешаются на основе структуры файла на стороне сервера. URL-адреса разрешаются на основе реальных общедоступных веб-адресов соответствующих ресурсов. Это именно веб-браузер, которому приходится ссылаться на них, а не на веб-сервер.

Есть несколько способов смягчить боль:

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, и он автоматически добавит отображение контекста и 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 tag? В JSF вы можете решить его как <a href="#{request.requestURI}#top">top</a> или <h:link value="top" fragment="top" />.

Ответ 2

Изменение 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}" />