有三个主要原因。
FacesServlet
没有被调用。
- XML 命名空间 URI 缺失或错误。
- 加载了多个 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源代码文件。在这种情况下,您可以在
web.xml
中
*.xhtml
的
<url-pattern>
上添加一个空的
<auth-constraint>
<security-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>
JSF 2.3是于2017年4月发布的,它已经通过在Web应用程序启动期间自动注册URL模式为*.xhtml
的FacesServlet
来解决了上述所有问题。因此,另一种选择就是升级到最新可用的JSF版本,应该是JSF 2.3或更高版本。但理想情况下,您仍应该明确地将FacesServlet
仅注册到一个URL模式*.xhtml
,因为对于完全相同的资源(例如/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实现,彼此冲突并损坏。例如,当你的Web应用程序的运行时类路径被多个不同版本的JSF库污染时,或者在特定的Mojarra 2.x + Tomcat 8.x组合中,当Web应用程序的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中捆绑依赖项。
另请参阅:
-
com.sun.faces.config.ConfigureListener的配置
-
如何通过Maven正确安装和配置JSF库?
确保以正确的方式学习JSF
对于不熟悉基本HTTP, HTML和Servlets的人来说,JSF的学习曲线非常陡峭。互联网上存在着许多低质量资源。请忽略那些由业余人员维护的代码片段爬取站点,他们主要关注广告收入而非教学,例如roseindia、tutorialspoint、javabeat、baeldung等等。它们很容易通过令人不快的广告链接/横幅进行识别。此外,请忽略与史前时代JSF 1.x有关的资源。他们使用JSP文件而不是XHTML文件,因此很容易辨别。自2009年起,JSP作为视图技术已经被JSF 2.0所取代。
为了以正确的方式开始,从我们的JSF维基页面开始,并订购权威书籍。
另请参阅:
FacesServlet
的url-pattern
从/faces/*
替换为*.jsf
。 - BalusC