JSF возвращает пустую/непроверенную страницу с открытым/исходным источником XHTML/XML/EL вместо вывода HTML-вывода

У меня есть несколько файлов Facelets, как показано ниже.

WebContent
 |-- index.xhtml
 |-- register.xhtml
 |-- templates
 |    |--userForm.xhtml
 |    '--banner.xhtml
 :

На обеих страницах используются шаблоны из каталога /templates. Мой /index.xhtml нормально открывается в браузере. Я получаю сгенерированный вывод HTML. У меня есть ссылка в файле /index.xhtml на файл /register.xhtml.

Однако мой /register.xhtml не анализируется и возвращается как обычный XHTML/raw XML вместо сгенерированного HTML-вывода. Все выражения EL в форме #{...} отображаются как есть, а не их результаты печатаются. Когда я щелкаю правой кнопкой мыши страницу в браузере и выполняю просмотр исходного кода страницы, я все равно вижу исходный код XHTML вместо сгенерированного вывода HTML. Например, <h:body> не стал <body>. Похоже, что шаблон не выполняется.

Однако когда я открываю /register.xhtml, как /faces/register.xhtml в адресной строке браузера, он отображается правильно. Как это вызвано и как я могу решить это?

Ответ 1

Есть три основные причины.

  1. FacesServlet не вызывается.
  2. URI пространства имен XML отсутствуют или неверны.
  3. Было загружено несколько реализаций JSF.

1. Убедитесь, что URL соответствует сопоставлению FacesServlet

URL-адрес ссылки (URL-адрес, который вы видите в адресной строке браузера) должен соответствовать <url-pattern> FacesServlet, как определено в web.xml, чтобы запустить все работы JSF. FacesServlet отвечает за синтаксический анализ файла XHTML, сбор отправленных значений форм, выполнение преобразования/проверки, обновление моделей, запуск действий и генерацию вывода HTML. Если вы не вызываете FacesServlet по URL-адресу, то все, что вы получите (и увидите правый клик, "Просмотр исходного кода в браузере"), - это действительно необработанный исходный код XHTML.

Если <url-pattern> является, например, *.jsf, то ссылка должна указывать на /register.jsf, а не на /register.xhtml. Если это, например, /faces/*, как у вас, то ссылка должна указывать на /faces/register.xhtml, а не на /register.xhtml. Один из способов избежать этой путаницы - просто изменить <url-pattern> с /faces/* на *.xhtml. Таким образом, ниже приведено идеальное отображение:

<servlet>
    <servlet-name>facesServlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>facesServlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

Если по какой-то причине вы не можете изменить <url-pattern> на *.xhtml, вы, вероятно, также хотели бы запретить конечным пользователям прямой доступ к файлам исходного кода XHTML по URL-адресу. В этом случае вы можете добавить <security-constraint> в <url-pattern> из *.xhtml с пустым <auth-constraint> в web.xml, что предотвращает это:

<security-constraint>
    <display-name>Restrict direct access to XHTML files</display-name>
    <web-resource-collection>
        <web-resource-name>XHTML files</web-resource-name>
        <url-pattern>*.xhtml</url-pattern>
    </web-resource-collection>
    <auth-constraint />
</security-constraint> 

Предстоящий JSF 2.3 решит все вышеперечисленное путем автоматической регистрации FacesServlet в шаблоне URL-адреса *.xhtml во время запуска веб-приложения.

Смотрите также:


2. Убедитесь, что пространства имен XML соответствуют версии JSF

С момента появления JSF 2.2 еще одной вероятной причиной является то, что пространства имен XML не соответствуют версии JSF. xmlns.jcp.org, как показано ниже, является новым с JSF 2.2 и не работает в более старых версиях JSF. Симптомы почти такие же, как если бы FacesServlet не вызывался.

<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">

Если вы не можете перейти на JSF 2.2, вам нужно вместо этого использовать старые пространства имен XML java.sun.com:

<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">

Смотрите также:


3. Несколько реализаций JSF были загружены

Еще одна вероятная причина заключается в том, что ваше веб-приложение загружает несколько реализаций JSF, конфликтующих и портящих друг друга. Например, когда ваш путь к классам во время выполнения веб-приложения загрязнен несколькими различными версиями библиотек JSF или в определенной комбинации Mojarra 2.x + Tomcat 8.x, когда в веб-приложении web.xml есть ненужная запись ConfigureListener, вызывающая его загрузку дважды.

<!-- You MUST remove this one from web.xml! -->
<!-- This is actually a workaround for buggy GlassFish3 and Jetty servers. -->
<!-- When leaving this in and you're targeting Tomcat, you'll run into trouble. -->
<listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

При использовании Maven убедитесь, что вы правильно объявляете зависимости и понимаете области действия зависимостей. Важно отметить, что не связывайте зависимости в веб-приложении, если они уже предоставлены целевым сервером.

Смотрите также:


Убедитесь, что вы изучаете JSF правильно

У JSF очень крутой курс обучения для тех, кто не знаком с базовыми HTTP, HTML и сервлетами. В Интернете много некачественных ресурсов. Не обращайте внимания на сайты с фрагментами кода, поддерживаемые любителями, уделяющими основное внимание доходам от рекламы, а не обучению, таким как roseindia, tutorialspoint, javabeat и т.д. Их легко узнать по нарушающим рекламные ссылки/баннеры. Также, пожалуйста, не обращайте внимания на ресурсы, связанные с юрским JSF 1.x. Их легко узнать, используя файлы JSP вместо файлов XHTML. JSP как технология представления уже устарела с версии JSF 2.0 в 2009 году.

Чтобы начать правильно, начните с нашей вики-страницы JSF и закажите авторитетную книгу.

Смотрите также: