日期:2014-05-16  浏览次数:20360 次

JSF中session过期后视图恢复的问题

在jsf中,一旦session过期,生命周期为session的Controller bean对象将会被销毁,因此除了一些静态页面,大多数情况的动态页面视图也就无法恢复。如果没有在web.xml设置error page,那么系统会直接在页面中抛出异常。当然关掉页面重新打开就不会有这个问题,但是普通浏览者这个时候往往会不知所措,以为网站挂掉了,这样可用性会很差。

??? 一般网上提供的解决方法是在web.xml中设置error page来捕获错误,重定向到一个指定的页面,例如:
<error-page>??? ?
<exception-type>javax.faces.application.ViewExpiredException</exception-type>??? ?
<location>/login.jsf</location>?
</error-page>


??? 但悲惨的是,在调试中发现javax.faces.application.ViewExpiredException这个异常并不会被捕获到,com.sun.faces.lifecycle.LifecycleImpl的execute方法抛出的实际上是FacesException。我怀疑可能是jsf的2.0版本修改了这一块,而网上的解决方法是针对老版本的。

??? 如此,我们只能通过从com.sun.faces.lifecycle.LifecycleImpl派生一个类来处理这个异常,代码如下:

import javax.faces.FacesException;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ppedu.commons.SystemProperty;
import com.sun.faces.lifecycle.LifecycleImpl;

public class TeleLifecycleImpl extends LifecycleImpl {

?? ?public TeleLifecycleImpl() {
?? ??? ?super();
?? ?}
?? ??
?? ?public void execute(FacesContext context) {
?? ??? ?try {
?? ??? ??? ?super.execute(context);
?? ??? ?}?
?? ??? ?catch (ViewExpiredException? vee) {
?? ??? ??? ?//似乎永远不会捕获,应该是异常在父类的同名方法中被包装成了FacesException
?? ??? ??? ?redirect(context);
?? ??? ?}
?? ??? ?catch (FacesException fe) {
?? ??? ??? ?//取得该异常的root cause
?? ??? ??? ?Object obj= fe.getCause();
?? ??? ??? ?//判断是否ViewExpiredException
?? ??? ??? ?if (obj instanceof? ViewExpiredException){?? ??? ??? ??? ?
?? ??? ??? ??? ?redirect(context);
?? ??? ??? ?}
?? ??? ??? ?else{
?? ??? ??? ??? ?throw fe;
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ??
?? ?private void redirect(FacesContext context) {
?? ??? ?try {
?? ??? ??? ?context.responseComplete();
?? ??? ??? ?context.renderResponse();
?? ??? ??? ?HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
?? ??? ??? ?
?? ??? ??? ?//根据原来的请求路径确定要重定向的路径
?? ??? ??? ?HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
?? ??? ??? ?String p