在我的应用程序JSF 2中,我发生了许多ViewExpiredException。甚至在身份验证页面上。如果在身份验证期间发生,我们应该重新输入登录名/密码才能正常运行。在其他页面上,我们需要刷新(F5)浏览器。在IE11上几乎是系统的。我认为我有缓存问题,因为它经常显示旧页面。
JSF配置:
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>OMB</display-name>
<description>OMB</description>
<!-- Without this param upload does not work at 1st time with IceFaces 3.3.0 -->
<context-param>
<param-name>org.icefaces.mandatoryResourceConfiguration</param-name>
<param-value>all</param-value>
</context-param>
<context-param>
<param-name>facelets.FACELETS_LIBRARIES</param-name>
<param-value>/pages/templates/tags.taglib.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/appCtx/**/*applicationContext*.xml
</param-value>
</context-param>
<!-- Facelet Config -->
<!-- <context-param> <param-name>javax.faces.application.CONFIG_FILES</param-name>
<param-value> /WEB-INF/faces-config-application-beans.xml, /WEB-INF/faces-config-navigation.xml
</param-value> </context-param> -->
<!-- <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value> </context-param> -->
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>-1</param-value>
</context-param>
<context-param>
<param-name>com.icesoft.faces.standardRequestScope</param-name>
<param-value>false</param-value>
</context-param>
<!-- Specifies to the ICEfaces framework whether to support multiple views
of a single application from the same browser. When running in a Portlet
environment, this parameter must be set to true. -->
<context-param>
<param-name>com.icesoft.faces.concurrentDOMViews</param-name>
<param-value>false</param-value>
</context-param>
<!-- Specifies to the ICEfaces framework that synchronous update mode is
to be used. By default, ICEfaces uses asynchronous update mode to support
server-initiated updates (AJAX push). Setting to true will enable synchronous
update mode and disable AJAX push features. -->
<context-param>
<param-name>com.icesoft.faces.synchronousUpdate</param-name>
<param-value>true</param-value>
</context-param>
<!-- Specifies to the ICEfaces framework whether to compress the server-side
DOM representation after each response. This saves a considerable amount
of of memory per client. However, since this is decompressed/compressed for
every update, it may not bring significant memory savings to applications
that make frequent use of AJAX push. -->
<context-param>
<param-name>com.icesoft.faces.compressDOM</param-name>
<param-value>true</param-value>
</context-param>
<!-- Specifies the amount of time in milliseconds that the bridge will wait
for a response from the server for a user-initiated request before declaring
the connection lost. Un-comment and change the default value, if necessary. -->
<context-param>
<param-name>com.icesoft.faces.connectionTimeout</param-name>
<param-value>300000</param-value>
</context-param>
<!-- Specifies the amount of time in milliseconds that an idle asynchronous
blocking connection should be held open before being released. Normally,
the blocking connection is closed and re-opened with every communication
to the browser, such as user interaction or a heartbeat ping. The purpose
of this setting is to remove the possibility of threads being held blocked
for a long duration on a dead or completely inactive client connection. This
value should be longer than the heartbeat interval to avoid unnecessary network
traffic. Un-comment and change the default value, if necessary. -->
<context-param>
<param-name>
com.icesoft.faces.blockingConnectionTimeout
</param-name>
<param-value>90000</param-value>
</context-param>
<!-- Specifies the amount of time in milliseconds between heartbeat messages.
Un-comment and change the default value, if necessary. -->
<context-param>
<param-name>com.icesoft.faces.heartbeatInterval</param-name>
<param-value>50000</param-value>
</context-param>
<!-- Specifies how many consecutive heartbeat connection attempts may fail
before the connection is considered lost. Un-comment and change the default
value, if necessary. -->
<context-param>
<param-name>com.icesoft.faces.heartbeatRetries</param-name>
<param-value>2</param-value>
</context-param>
<!-- Specifies the number of milliseconds that a heartbeat request waits
for a successful response before it is considered timed out. Un-comment and
change the default value, if necessary. -->
<context-param>
<param-name>com.icesoft.faces.heartbeatTimeout</param-name>
<param-value>60000</param-value>
</context-param>
<!-- Specifies a page URI to redirect the client to when an asynchronous
connection is lost. The parameter value must be surrounded by single quotes.
Un-comment and change the default value, if necessary. -->
<context-param>
<param-name>
com.icesoft.faces.connectionLostRedirectURI
</param-name>
<param-value>login.xhtml</param-value>
</context-param>
<context-param>
<param-name>
com.icesoft.faces.sessionExpiredRedirectURI
</param-name>
<param-value>login.xhtml</param-value>
</context-param>
<context-param>
<param-name>com.icesoft.faces.blockUIOnSubmit</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.icefaces.ace.fileEntry.requireJavascript</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jExposeWebAppRoot</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>springFilter</filter-name>
<filter-class>
org.springframework.web.filter.RequestContextFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>springFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>HttpHeadersFilter</filter-name>
<filter-class>com.omb.filters.HttpHeadersFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>X-UA-Compatible</param-name>
<param-value>IE=9</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeadersFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- SPRING -->
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.util.IntrospectorCleanupListener
</listener-class>
</listener>
<!-- Listener d'initialisation de l'application -->
<listener>
<listener-class>com.omb.listeners.OMBServletContextListener</listener-class>
</listener>
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Resource Servlet</servlet-name>
<servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/icefaces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Resource Servlet</servlet-name>
<url-pattern>/xmlhttp/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<mime-mapping>
<extension>com</extension>
<mime-type>application/octet-stream</mime-type>
</mime-mapping>
<mime-mapping>
<extension>com</extension>
<mime-type>text/plain</mime-type>
</mime-mapping>
<mime-mapping>
<extension>pdf</extension>
<mime-type>application/pdf</mime-type>
</mime-mapping>
<!-- Welcome files -->
<welcome-file-list>
<welcome-file>login.xhtml</welcome-file>
</welcome-file-list>
<error-page>
<error-code>500</error-code>
<location>/pages/error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>
<location>/pages/error.jsp</location>
</error-page>
</web-app>
ExceptionHandler:
package com.omb.view.exception;
import java.util.Iterator;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.icefaces.application.SessionExpiredException;
import org.springframework.beans.factory.annotation.Autowired;
import com.omb.UserContext;
import com.omb.exception.FunctionnalException;
import com.omb.service.translation.TranslationService;
import com.omb.view.util.FacesUtils;
public class CustomExceptionHandler extends ExceptionHandlerWrapper {
private static final Log logger = LogFactory.getLog(CustomExceptionHandler.class);
private ExceptionHandler wrapped;
@Autowired
private TranslationService translationService;
@Autowired
private UserContext userContext;
CustomExceptionHandler(ExceptionHandler exception) {
this.wrapped = exception;
}
/**
* @see javax.faces.context.ExceptionHandlerWrapper#getWrapped()
*/
@Override
public ExceptionHandler getWrapped() {
return wrapped;
}
@Override
public void handle() throws FacesException {
final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();
while (i.hasNext()) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext context =
(ExceptionQueuedEventContext) event.getSource();
// get the exception from context
Throwable throwable = context.getException();
final FacesContext fc = FacesContext.getCurrentInstance();
final Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
final NavigationHandler nav = fc.getApplication().getNavigationHandler();
// here you do what ever you want with exception
try {
if (throwable instanceof ViewExpiredException) {
logger.info("the session is expired");
FacesUtils.addInfoMessage("Session expired !");
nav.handleNavigation(fc, null, "sessionExpired");
} else if (throwable instanceof SessionExpiredException) {
nav.handleNavigation(fc, null, "sessionExpired");
} else if (throwable instanceof FunctionnalException) {
logger.warn(throwable.getMessage());
FacesUtils.addInfoMessage(throwable.getMessage());
nav.handleNavigation(fc, null, null);
} else {
logger.error(throwable.getMessage(), throwable);
requestMap.put("exceptionMessage", throwable.getMessage());
nav.handleNavigation(fc, null, "error");
}
fc.renderResponse();
} finally {
// remove it from queue
i.remove();
}
}
// parent hanle
getWrapped().handle();
}
}