JSF 使用普通/原始 XHTML/XML/EL 源而不是呈现的 HTML 输出返回空白/未解析页面 [英] JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output

查看:19
本文介绍了JSF 使用普通/原始 XHTML/XML/EL 源而不是呈现的 HTML 输出返回空白/未解析页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些如下所示的 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 时,它会正确显示.这是怎么引起的,我该如何解决?

解决方案

主要有三个原因.

  1. FacesServlet 未被调用.
  2. XML 命名空间 URI 丢失或错误.
  3. 已加载多个 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 不利.

另见:


2.确保 XML 命名空间与 JSF 版本匹配

自从引入 JSF 2.2 以来,另一个可能的原因是 XML 名称空间与 JSF 版本不匹配.如下所示的 xmlns.jcp.org 是自 JSF 2.2 以来的新内容,并且在较旧的 JSF 版本中不起作用.症状与未调用 FacesServlet 时几乎相同.

如果您无法升级到 JSF 2.2 或更高版本,则需要使用旧的 java.sun.com XML 命名空间:

但理想情况下,您应该始终使用可用的最新版本.

另见:


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, HTMLServlets.互联网上有很多低质量的资源.请忽略由业余爱好者维护的主要关注广告收入而不是教学的代码片段抓取网站,例如 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.

  1. FacesServlet is not invoked.
  2. XML namespace URIs are missing or wrong.
  3. 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:


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:


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:


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:

这篇关于JSF 使用普通/原始 XHTML/XML/EL 源而不是呈现的 HTML 输出返回空白/未解析页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆