JSF 使用普通/原始 XHTML/XML/EL 源而不是呈现的 HTML 输出返回空白/未解析页面 [英] JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output
问题描述
我有一些如下所示的 Facelets 文件.
<前>网页内容|-- index.xhtml|-- 注册.xhtml|-- 模板||--userForm.xhtml|`--banner.xhtml:两个页面都使用来自 /templates
目录的模板.我的 /index.xhtml
在浏览器中打开正常.我得到生成的 HTML 输出.我在 /index.xhtml
文件中有一个链接到 /register.xhtml
文件.
但是,我的 /register.xhtml
没有被解析并返回为纯 XHTML/原始 XML,而不是其生成的 HTML 输出.#{...}
形式的所有 EL 表达式都按原样显示,而不是打印它们的结果.当我在浏览器中右键单击页面并执行 View page source 时,我仍然看到原始的 XHTML 源代码而不是生成的 HTML 输出.例如,
没有变成 .看起来模板没有被执行.
但是,当我在浏览器的地址栏中打开 /register.xhtml
像 /faces/register.xhtml
时,它会正确显示.这是怎么引起的,我该如何解决?
主要有三个原因.
FacesServlet
未被调用.- XML 命名空间 URI 丢失或错误.
- 已加载多个 JSF 实现.
1.确保 URL 匹配 FacesServlet
映射
链接的 URL(您在浏览器地址栏中看到的 URL)必须与 FacesServlet
的
匹配,如web.xml
以便让所有 JSF 工作运行.FacesServlet
负责解析 XHTML 文件、收集提交的表单值、执行转换/验证、更新模型、调用操作和生成 HTML 输出.如果您不通过 URL 调用 FacesServlet
,那么您将获得的(通过右键单击查看,在浏览器中查看源代码)确实是原始 XHTML 源代码.
如果
是例如 *.jsf
,那么链接应该指向 /register.jsf
和不是 /register.xhtml
.如果它是例如 /faces/*
,就像你一样,那么链接应该指向 /faces/register.xhtml
而不是 /register.xhtml代码>.避免这种混淆的一种方法是将
从 /faces/*
更改为 *.xhtml
.因此,以下是理想的映射:
<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.在这种情况下,您可以在 *.xhtml
的
上添加一个
并带有一个空 <web.xml
中的 code>
<display-name>限制对 XHTML 文件的直接访问</display-name><web-resource-collection><web-resource-name>XHTML 文件</web-resource-name><url-pattern>*.xhtml</url-pattern></web-resource-collection><认证约束/></安全约束>
JSF 2.3 于 2017 年 4 月推出,通过在 webapp 启动期间自动在 *.xhtml
的 URL 模式上注册 FacesServlet
已经解决了上述所有问题.因此,替代方法是简单地升级到最新的可用 JSF 版本,该版本应该是 JSF 2.3 或更高版本.但理想情况下,您仍然应该仅在 *.xhtml
的一种 URL 模式上显式注册 FacesServlet
,因为对于像 /register.xhtml 这样完全相同的资源有多个可能的 URL
、/register.jsf
、/register.faces
和 /faces/register.xhtml
对 SEO 不利.
另见:
- 通过<welcome-file>设置默认主页在 JSF 项目中
- 打开 XML 页面显示此 XML 文件似乎没有任何与之关联的样式信息."
- 有时我看到JSF URL 是 *.jsf,有时是 *.xhtml,有时是/faces/*.为什么?
- JavaServer Faces 2.2和 HTML5 支持,为什么 XHTML 还在使用
- 哪个XHTML 文件是否需要放在/WEB-INF 中,哪些不需要?
- 我们的 servlet wiki - 了解有关 servlet 的强制性基础知识
2.确保 XML 命名空间与 JSF 版本匹配
自从引入 JSF 2.2 以来,另一个可能的原因是 XML 名称空间与 JSF 版本不匹配.如下所示的 xmlns.jcp.org
是自 JSF 2.2 以来的新内容,并且在较旧的 JSF 版本中不起作用.症状与未调用 FacesServlet
时几乎相同.
如果您无法升级到 JSF 2.2 或更高版本,则需要使用旧的 java.sun.com
XML 命名空间:
但理想情况下,您应该始终使用可用的最新版本.
另见:
- 与 JSF 2.2 及更高版本一起使用的 XML 命名空间
- JSF 标签未执行
- 警告:此页面要求使用前缀 XXX 声明的 XML 命名空间 http://xmlns.jcp.org/jsf/XXX 但该命名空间不存在标签库
3.已加载多个 JSF 实现
另一个可能的原因是您的 web 应用程序加载了多个 JSF 实现,相互冲突和损坏.例如,当您的 webapp 的运行时类路径被多个不同版本的 JSF 库污染时,或者在特定的 Mojarra 2.x + Tomcat 8.x 组合中,当 webapp 的 中有一个不必要的
导致它被加载两次.ConfigureListener
条目时web.xml
<!-- 你必须从 web.xml 中删除这个!--><!-- 这实际上是有问题的 GlassFish3 和 Jetty 服务器的解决方法.--><!-- 当你把它留在里面并且你的目标是 Tomcat 时,你会遇到麻烦.--><听众><listener-class>com.sun.faces.config.ConfigureListener</listener-class></监听器>
使用 Maven 时,请务必确保以正确的方式声明依赖项并了解依赖项范围.重要的是,当目标服务器已经提供这些依赖项时,不要在 webapp 中捆绑这些依赖项.
另见:
确保您以正确的方式学习 JSF
JSF 对于那些不熟悉基本 HTTP, HTML 和 Servlets.互联网上有很多低质量的资源.请忽略由业余爱好者维护的主要关注广告收入而不是教学的代码片段抓取网站,例如 roseindia、tutorialspoint、javabeat、baeldung 等.它们很容易通过干扰广告链接/横幅识别.另外请忽略处理侏罗纪 JSF 1.x 的资源.通过使用 JSP 文件而不是 XHTML 文件,它们很容易识别.从 2009 年的 JSF 2.0 开始,JSP 作为视图技术已被弃用.
要以正确的方式开始,请从我们的 JSF wiki 页面开始订购权威书籍.
另见:
I have some Facelets files like below.
WebContent |-- index.xhtml |-- register.xhtml |-- templates | |--userForm.xhtml | `--banner.xhtml :
Both pages are using templates from /templates
directory. My /index.xhtml
opens fine in browser. I get the generated HTML output. I have a link in /index.xhtml
file to /register.xhtml
file.
However, my /register.xhtml
is not getting parsed and returns as plain XHTML / raw XML instead of its generated HTML output. All EL expressions in form of #{...}
are displayed as-is instead of that their results are being printed. When I rightclick page in browser and do View page source, then I still see the original XHTML source code instead of the generated HTML output. For example, the <h:body>
did not become a <body>
. It looks like that the template is not being executed.
However, when I open the /register.xhtml
like /faces/register.xhtml
in browser's address bar, then it displays correctly. How is this caused and how can I solve it?
There are three main causes.
FacesServlet
is not invoked.- XML namespace URIs are missing or wrong.
- Multiple JSF implemenations have been loaded.
1. Make sure that URL matches FacesServlet
mapping
The URL of the link (the URL as you see in browser's address bar) has to match the <url-pattern>
of the FacesServlet
as definied in web.xml
in order to get all the JSF works to run. The FacesServlet
is the one responsible for parsing the XHTML file, collecting submitted form values, performing conversion/validation, updating models, invoking actions and generating HTML output. If you don't invoke the FacesServlet
by URL, then all you would get (and see via rightclick, View Source in browser) is indeed the raw XHTML source code.
If the <url-pattern>
is for example *.jsf
, then the link should point to /register.jsf
and not /register.xhtml
. If it's for example /faces/*
, like you have, then the link should point to /faces/register.xhtml
and not /register.xhtml
. One way to avoid this confusion is to just change the <url-pattern>
from /faces/*
to *.xhtml
. The below is thus the ideal mapping:
<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>
If you can't change the <url-pattern>
to *.xhtml
for some reason, then you probably would also like to prevent endusers from directly accessing XHTML source code files by URL. In that case you can add a <security-constraint>
on the <url-pattern>
of *.xhtml
with an empty <auth-constraint>
in web.xml
which prevents that:
<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 which was introduced April 2017 has already solved all of above by automatically registering the FacesServlet
on an URL pattern of *.xhtml
during webapp's startup. The alternative is thus to simply upgrade to latest available JSF version which should be JSF 2.3 or higher. But ideally you should still explicitly register the FacesServlet
on only one URL pattern of *.xhtml
because having multiple possible URLs for exactly the same resource like /register.xhtml
, /register.jsf
, /register.faces
and /faces/register.xhtml
is bad for SEO.
See also:
- Set default home page via <welcome-file> in JSF project
- Opening XML page shows "This XML file does not appear to have any style information associated with it."
- Sometimes I see JSF URL is *.jsf, sometimes *.xhtml and sometimes /faces/*. Why?
- JavaServer Faces 2.2 and HTML5 support, why is XHTML still being used
- Which XHTML files do I need to put in /WEB-INF and which not?
- Our servlets wiki - to learn the mandatory basics about servlets
2. Make sure that XML namespaces match JSF version
Since introduction of JSF 2.2, another probable cause is that XML namespaces don't match the JSF version. The xmlns.jcp.org
like below is new since JSF 2.2 and does not work in older JSF versions. The symptoms are almost the same as if the FacesServlet
is not invoked.
<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">
If you can't upgrade to JSF 2.2 or higher, then you need to use the old java.sun.com
XML namespaces instead:
<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">
But ideally you should always use the latest version where available.
See also:
- Which XML namespace to use with JSF 2.2 and up
- JSF tags not executed
- Warning: This page calls for XML namespace http://xmlns.jcp.org/jsf/XXX declared with prefix XXX but no taglibrary exists for that namespace
3. Multiple JSF implementations have been loaded
One more probable cause is that multiple JSF implementations have been loaded by your webapp, conflicting and corrupting each other. For example, when your webapp's runtime classpath is polluted with multiple different versioned JSF libraries, or in the specific Mojarra 2.x + Tomcat 8.x combination, when there's an unnecessary ConfigureListener
entry in webapp's web.xml
causing it to be loaded twice.
<!-- 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>
When using Maven, make absolutely sure that you declare the dependencies the right way and that you understand dependency scopes. Importantingly, do not bundle dependencies in webapp when those are already provided by the target server.
See also:
- Configuration of com.sun.faces.config.ConfigureListener
- How to properly install and configure JSF libraries via Maven?
Make sure that you learn JSF the right way
JSF has a very steep learning curve for those unfamiliar with basic HTTP, HTML and Servlets. There are a lot of low quality resources on the Internet. Please ignore code snippet scraping sites maintained by amateurs with primary focus on advertisement income instead of on teaching, such as roseindia, tutorialspoint, javabeat, baeldung, etc. They are easily recognizable by disturbing advertising links/banners. Also please ignore resources dealing with jurassic JSF 1.x. They are easily recognizable by using JSP files instead of XHTML files. JSP as view technology was deprecated since JSF 2.0 at 2009 already.
To get started the right way, start at our JSF wiki page and order an authoritative book.
See also:
- Java / Jakarta EE web development, where do I start and what skills do I need?
- What is the need of JSF, when UI can be achieved with JavaScript libraries such as jQuery and AngularJS
这篇关于JSF 使用普通/原始 XHTML/XML/EL 源而不是呈现的 HTML 输出返回空白/未解析页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!