Как получить базовый URL-адрес через контекстный путь в JSF?

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

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>

Но я считаю, что это совсем не «элегантно». Любые идеи?


person Valter Silva    schedule 29.07.2011    source источник


Ответы (2)


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>

При необходимости вы можете использовать _4 _, чтобы сделать его еще короче. Поместите его где-нибудь в мастер-шаблон, он будет доступен для всех страниц:

<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"> относительно себя! См. Также Рекомендуется ли использовать базу ‹ ›Тег html? В JSF его можно решить как <a href="#{request.requestURI}#top">top</a> или <h:link value="top" fragment="top" />.

person BalusC    schedule 29.07.2011
comment
Большое вам спасибо, я ваш большой поклонник =) Надеюсь, что стану отличным разработчиком, как и вы, товарищ, спасибо. - person Valter Silva; 30.07.2011
comment
Хорошее решение, не знал, что это возможно! Спасибо, что поделился! - person Robert M.; 30.07.2011
comment
Спасибо, у меня есть дополнительный вопрос: правильный путь для ссылки будет /appname/faces/page.xhtml, но с # {request.contextPath} я получаю только / appname. есть ли способ получить / лиц / тоже? где это вообще определяется? - person styx; 25.04.2012
comment
@styx: используйте #{request.servletPath} или <h:link>. - person BalusC; 25.04.2012
comment
@BalusC, спасибо, как обычно, очень полезно :) Мне нужен был первый, так как я использую путь внутри тега ‹meta http-Equiv = refresh›. еще раз спасибо! - person styx; 26.04.2012
comment
@BalusC: Я попробовал ваш ui:param подход, и он работает с Mojarra, но не с Myfaces 2.1.8. Я создал проблему, думая, что это ошибка, но оттуда узнал, что <ui:param> должно быть направьте дочерний элемент <ui:include> или <ui:define> на работу. См. Обсуждение этого вопроса. - person Aklin; 23.08.2012
comment
@balusC да, подход ui: param не работает с myfaces. - person Rajat Gupta; 26.08.2012
comment
@Aklin: Я исправил ответ, спасибо, я не знал, что это относится к Mojarra, я на самом деле никогда не видел отчета о проблеме Mojarra по этому поводу. - person BalusC; 27.08.2012
comment
<c:set var="root" value="#{request.contextPath}/" />, похоже, не заставляет #{root} работать для всех включенных страниц. Я работаю только тогда, когда #{root} используется только на определенной странице .. - person Aklin; 30.08.2012
comment
@Aklin: Возможно, это снова что-то еще от MyFaces. Попробуйте добавить scope="request". - person BalusC; 30.08.2012
comment
Спасибо, после добавления scope="request" теперь работает! Однако мне было интересно, что я должен использовать application область видимости для этого конкретного случая, так как путь останется таким же для всех запросов и всех пользователей в масштабе всего приложения !? - person Aklin; 30.08.2012
comment
Обратите внимание, что попытка установить базу, как показано выше, не будет работать должным образом в прокси-среде (пример: apache с mod_proxy, перенаправление somedomain / app на somedomain: 8080 / app; вышеупомянутая попытка вместо этого установит base на somedomain: 8080 / app of -somehow- ожидаемый somedomain / app. - person Markus Schulte; 21.03.2013
comment
Я работаю над устаревшим приложением с JSF1.0. value="#{facesContext.externalContext.requestContextPath}/ работал у меня, а value="#{request.contextPath}/" не работал. - person vinS; 07.12.2018

Вариант 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}" />
person JET    schedule 17.06.2015