我有一个在 Glassfish [GlassFish Server Open Source Edition 3.1.2.2 (build 5) 上运行的 JSF 应用程序;Mojarra 2.1.6(快照 20111206)]。我正在使用 PrimeFaces 3.5 和 OmniFaces 1.5 版。我正在使用基于表单的登录身份验证
<login-config>
<auth-method>FORM</auth-method>
<realm-name>reportingRealm</realm-name>
<form-login-config>
<form-login-page>/faces/login.xhtml</form-login-page>
<form-error-page>/loginError.xhtml</form-error-page>
</form-login-config>
</login-config>
在 web.xml 中定义了一个错误页面
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/faces/viewExpired.xhtml</location>
</error-page>
并具有以下用于 servlet 映射的 URL 模式(如果相关)
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
该应用程序最初没有使用 AJAX。具体来说,我有没有使用 AJAX 的 ap:commandButton。如果会话过期并单击此按钮,则异常处理如下:显示登录页面;在(重新)输入登录凭据并登录时,会显示会话过期页面。选择再次登录让您重新开始工作。我对此没有任何问题。(请注意,最初我认为我在错误页面中专门引用了 ViewExpiredException,而不是现在配置的 Throwable。我描述的行为在使用 Throwable 和使用 ViewExpiredException 时都会发生,但需要注意的是ViewExpiredException 的情况下,我添加了一个额外的异常类型来满足 OmniFaces 要求)。
单击 p:commandButton 时,我将应用程序更改为使用 AJAX。为了支持这一点,我将 OmniFaces(我强烈推荐的解决方案)添加到我的项目中,并将 form-login-page 从 '/login.xhtml' 更改为 '/faces/login.xhtml' (据我了解 OmniFaces文档,并且考虑到我的配置,这将是必要的;事实上,当 form-login-page 等于“/login.xhmtl”时,异常处理在使用非 AJAX 启用控件时继续像以前一样工作,但不会发生任何事情单击启用 AJAX 的控件时(显示的页面没有更改,也没有记录))。
当 p:commandButton 使用 AJAX、使用 OmniFaces 和 form-login-page 更改为“/faces/login.xhtml”时,当会话过期并且我单击启用 AJAX 的控件时,ViewExpiredException 处理工作完美(在事实上,我更喜欢在为非 AJAX 启用的控件处理 ViewExpiredException 时发生的序列:使用 OmniFaces 的序列是您被直接带到会话过期页面。选择再次登录并重新登录商业。)
但是,现在 - 如果会话已过期并且我单击未启用 AJAX 的控件 - 在我的浏览器窗口中显示以下内容(作为现在显示的页面上的唯一内容)
XML Parsing Error: no element found
Location: http://localhost:8080/Reporting-war/faces/protected/multiUser.xhtml
Line Number 1, Column 1;
记录以下内容:
WARNING: ApplicationDispatcher[/Reporting-war] PWC1231: Servlet.service() for servlet Faces Servlet threw exception
javax.faces.application.ViewExpiredException: viewId:/login.xhtml - View /login.xhtml could not be restored.
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:205)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
...
at java.lang.Thread.run(Thread.java:722)
WARNING: Unexpected error forwarding or redirecting to login page
javax.servlet.ServletException: viewId:/login.xhtml - View /login.xhtml could not be restored.
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:606)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
...
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.application.ViewExpiredException: viewId:/login.xhtml - View /login.xhtml could not be restored.
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:205)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
...
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
... 32 more
请注意,如果 form-login-page 的值为“/faces/login.xhtml”,则无论是否使用 OmniFaces,都会发生错误;我不认为这是一个 OmniFaces 问题。但是,我不明白 (a) 为什么会发生这种情况,或者 (b) 是否有一种方法可以维护我现有的配置(例如,保持我的 servlet 映射等)并让会话过期处理工作适用于启用 AJAX 和非启用 AJAX 的控件。
multiUser.xhtml 开头如下:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./mainTemplate.xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns="http://www.w3.org/1999/xhtml">
<ui:define name="top">
</ui:define>
<ui:define name="content">
...
login.xhtm 的完整内容是:
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Login</title>
</head>
<body>
<form method="POST" action="j_security_check">
Username
<input type="text" name="j_username"/>
Password
<input type="password" name="j_password"/>
<input type="submit" value="Login"/>
</form>
</body>
</html>
viewExpired.xhtml 的完整内容是:
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<title>Expired Session</title>
</head>
<body>
<div>
<p>
Your login session has expired.
</p>
<p>
<h:form>
<h:link value="Login Again" outcome="home"/>
</h:form>
</p>
</div>
</body>
</html>
任何人都可以提供任何帮助以了解为什么会发生这种情况,并了解解决该问题的选项是什么,我们将不胜感激。谢谢。