繁体   English   中英

JSF 返回带有普通/原始 XHTML/XML/EL 源而不是呈现的 HTML 输出的空白/未解析页面

[英]JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output

我有一些如下所示的 Facelets 文件。

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

两个页面都使用/templates目录中的/templates 我的/index.xhtml在浏览器中打开正常。 我得到生成的 HTML 输出。 我在/index.xhtml文件中有一个指向/register.xhtml文件的链接。

但是,我的/register.xhtml没有被解析并返回为纯 XHTML/原始 XML,而不是其生成的 HTML 输出。 #{...}形式的所有 EL 表达式都按原样显示,而不是打印它们的结果。 当我在浏览器中右键单击页面并执行View page source 时,我仍然看到原始的 XHTML 源代码而不是生成的 HTML 输出。 例如, <h:body>没有变成<body> 看起来模板没有被执行。

但是,当我在浏览器的地址栏中打开像/faces/register.xhtml这样的/register.xhtml时,它会正确显示。 这是怎么引起的,我该如何解决?

主要有以下三个原因。

  1. FacesServlet没有被调用。
  2. XML 命名空间 URI 丢失或错误。
  3. 已加载多个 JSF 实现。

1. 确保 URL 匹配FacesServlet映射

链接的 URL(您在浏览器地址栏中看到的 URL)必须与web.xml中定义的FacesServlet<url-pattern>匹配,以便让所有 JSF 工作运行。 FacesServlet负责解析 XHTML 文件、收集提交的表单值、执行转换/验证、更新模型、调用操作和生成 HTML 输出。 如果您不通过 URL 调用FacesServlet ,那么您将获得的(通过右键单击查看,在浏览器中查看源代码)确实是原始 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 ,那么您可能还想阻止最终用户通过 URL 直接访问 XHTML 源代码文件。 在这种情况下,您可以在*.xhtml<url-pattern> <security-constraint>上添加一个<security-constraint>并在web.xml添加一个空的<auth-constraint>以防止:

<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> 

2017 年 4 月推出的 JSF 2.3 通过在 webapp 启动期间自动在*.xhtml的 URL 模式上注册FacesServlet已经解决了上述所有问题。 因此,替代方法是简单地升级到最新的可用 JSF 版本,该版本应该是 JSF 2.3 或更高版本。 但理想情况下,您仍然应该仅在*.xhtml一种 URL 模式上显式注册FacesServlet ,因为对于完全相同的资源(如/register.xhtml/register.jsf/register.faces/faces/register.xhtml有多个可能的 URL对 SEO 不利。

也可以看看:


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 或更高版本,则需要改用旧的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">

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

也可以看看:


3. 加载了多个 JSF 实现

另一个可能的原因是您的 web 应用程序加载了多个 JSF 实现,相互冲突和损坏。 例如,当您的 webapp 的运行时类路径被多个不同版本的 JSF 库污染时,或者在特定的 Mojarra 2.x + Tomcat 8.x 组合中,当 webapp 的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

对于那些不熟悉基本HTTPHTMLServlets 的人来说,JSF 的学习曲线非常陡峭。 互联网上有很多低质量的资源。 请忽略由业余爱好者维护的主要关注广告收入而不是教学的代码片段抓取网站,例如 roseindia、tutorialspoint、javabeat、baeldung 等。它们很容易通过干扰广告链接/横幅识别。 另外请忽略处理侏罗纪 JSF 1.x 的资源。 通过使用 JSP 文件而不是 XHTML 文件,它们很容易识别。 自 2009 年的 JSF 2.0 以来,JSP 作为视图技术已被弃用。

要以正确的方式开始,请从我们的 JSF wiki 页面开始并订购一本权威书籍

也可以看看:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM