У меня есть некоторые файлы Facelets как ниже.
WebContent |-- index.xhtml |-- register.xhtml |-- templates | |--userForm.xhtml | `--banner.xhtml :
Обе страницы используют шаблоны от /templates
каталог. Мой /index.xhtml
открывается прекрасный в браузере. Я получаю сгенерированный вывод HTML. У меня есть ссылка в /index.xhtml
файл к /register.xhtml
файл.
Однако мой /register.xhtml
не становится проанализированным и возвращается как простой XHTML / необработанный XML вместо его сгенерированного вывода HTML. Все выражения EL в форме #{...}
отображены как есть вместо этого, их результаты печатаются. Когда я щелкаю правой кнопкой по странице в браузере и делаю источник страницы View, затем я все еще вижу исходный исходный код XHTML вместо сгенерированного вывода HTML. Например, <h:body>
не стал a <body>
. Похоже, что шаблон не выполняется.
Однако, когда я открываюсь /register.xhtml
как /faces/register.xhtml
в строке поиска браузера затем это отображается правильно. Как это вызывается и как я могу решить его?
Есть три основные причины.
FacesServlet
не вызывается. FacesServlet
отображениюURL ссылки (URL, который вы видите в адресной строке браузера) должен соответствовать FacesServlet
, как определено в web.xml
, чтобы все работы JSF были запущены. FacesServlet
отвечает за разбор XHTML-файла, сбор значений отправленных форм, выполнение преобразования/оценки, обновление моделей, вызов действий и генерацию HTML-вывода. Если вы не вызовете FacesServlet
по URL, то все, что вы получите (и увидите через правый клик, View Source в браузере) - это действительно необработанный исходный код XHTML.
Если
- это, например, *.jsf
, то ссылка должна указывать на /register.jsf
, а не на /register.xhtml
. Если это, например, /faces/*
, как у вас, то ссылка должна указывать на /faces/register.xhtml
, а не на /register.xhtml
. Один из способов избежать этой путаницы - просто изменить
с /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>
Если вы по какой-то причине не можете изменить
на *.xhtml
, то, вероятно, вы также хотели бы предотвратить прямой доступ конечных пользователей к файлам исходного кода XHTML по URL. В этом случае вы можете добавить
на
из *.xhtml
с пустым
в 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, который был представлен в апреле 2017 года, уже решил все вышеперечисленные проблемы, автоматически регистрируя FacesServlet
на шаблоне URL *.xhtml
во время запуска webapp. Таким образом, альтернативой является простое обновление до последней доступной версии JSF, которая должна быть JSF 2.3 или выше. Но в идеале вы все равно должны явно зарегистрировать FacesServlet
только на одном шаблоне URL *.xhtml
, потому что наличие нескольких возможных URL для одного и того же ресурса, например /register. xhtml
, /register.jsf
, /register.faces
и /faces/register.xhtml
плохо для SEO.
С момента появления 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 или выше, тогда вам нужно использовать старые java.sun.com
XML пространства имен вместо этого:
<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">
Но в идеале вы всегда должны использовать последнюю версию, если она доступна.
Более вероятной причиной является то, что несколько реализаций JSF были загружены вашим веб-приложением, конфликтуя и повреждая друг друга. Например, если путь класса выполнения веб-приложения загрязнен несколькими различными версиями библиотек JSF, или в конкретной комбинации Mojarra 2.x + Tomcat 8.x, когда в ConfigureListener
в 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 убедитесь, что вы правильно объявляете зависимости и понимаете области зависимости. Важно отметить, что не связывайте зависимости в webapp, если они уже предоставляются целевым сервером.
JSF имеет очень крутую кривую обучения для тех, кто не знаком с базовыми HTTP, HTML и Servlets. В Интернете существует множество низкокачественных ресурсов. Пожалуйста, не обращайте внимания на сайты, содержащие фрагменты кода, которые поддерживаются любителями, ориентированными в первую очередь на доход от рекламы, а не на обучение, такие как roseindia, tutorialspoint, javabeat и др. Они легко узнаваемы по мешающим рекламным ссылкам/баннерам. Также, пожалуйста, игнорируйте ресурсы, посвященные юрскому JSF 1.x. Их легко узнать по использованию JSP файлов вместо XHTML файлов. JSP как технология представления была устаревшей с JSF 2.0 уже в 2009 году.
Чтобы начать правильно, начните с нашей вики-страницы JSF и закажите авторитетную книгу.