在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 path = request.getRequestURI();
?? ??? ??? ?String [] ss = path.split("/");?? ??? ??? ?
?? ??? ??? ?String redirectKey = "session.timeout.redirect.url.general";
?? ??? ??? ?for(int i=0;i<ss.length;i++){
?? ??? ??? ??? ?if( ss[i].equals("security") || ss[i].equals("organManagementCenter") || ss[i].equals("webManageCenter")){
?? ??? ??? ??? ??? ?//管理模块
?? ??? ??? ??? ??? ?redirectKey = "session.timeout.redirect.url.management";
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?if( ss[i].equals("usercenter")){
?? ??? ??? ??? ??? ?//个人中心
?? ??? ??? ??? ??? ?redirectKey = "session.timeout.redirect.url.usercenter";
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?//目标页面
?? ??? ??? ?String url = context.getExternalContext().getRequestContextPath() + SystemProperty.getKeyValue(redirectKey);?? ?
?? ??? ??? ?response.sendRedirect(url);
?? ??? ?} catch (Exception e) {
?? ??? ??? ?System.out.println("url redirect wrong ");
?? ??? ?}
?? ?}
}
??? 这个类可以捕获ViewExpiredException引起的异常,将页面重定向到实现设定的url。com.ppedu.commons.SystemProperty是一个读配置文件的类,读者可以自己实现一个,配置文件设置了三个url,分别指向网站首页、用户中心登陆页和管理中心登录页,设置如下:
#============================================================================
# session过期后的默认页 ?
#============================================================================
session.timeout.redirect.url.general = /home.jsf
session.timeout.redirect.url.management = /security/managementLogin.jsf
session.timeout.redirect.url.usercenter = /usercenter/login.jsf
??? 然后,我们创建一个工厂类:
import com.sun.faces.lifecycle.LifecycleFactoryImpl;
public class TeleLifecycleFactoryImpl extends LifecycleFactoryImpl {
?? ?public final static String CUSTOM_LIFECYCLE = "TELEEPOCH";?? ?
??? /** Creates a new instance of TeleLifecycleFactoryImpl */
??? public TeleLifecycleFactoryImpl() {
??????? addLifecycle(CUSTOM_LIFECYCLE,new TeleLifecycleImpl());
??? }
}
??? 接着,在faces-config.xml中注册这个工厂类来监查生命周期:
<factory>
?? ??? ?<lifecycle-factory>com.ppedu.view.TeleLifecycleFactoryImpl</lifecycle-factory>
</factory>
??? OK,搞定收工,测试一下看看是否能获得预期效果。
详细解决方案
JSF中session过期后视图恢复的有关问题
热度:301 发布时间:2012-12-27 10:17:10.0
相关解决方案
- hibernate 连接 oracle session 有关问题
- Servlet Session 购物车,该怎么解决
- Servlet Session 购物车解决办法
- ssh多数据库配置 如何get session
- hibernate中Query query=session.createQuery的有关问题
- CAPTCHA 模块中 ajax form 导致CAPTCHA session reuse attack detected异常,解决方法
- session 覆盖的有关问题 求高手
- Could not deserialize session data解决方法
- response.write(session.getAttribute("BranchName")提示异常
- JSP上if(trim(session.getAttribute("grade"))== "0") 多谢!
- jsp session 过期提示有关问题
- session.invalidate()无效解决办法
- null id in com.bsw.gms.hibernate.pojo.Score entry (don't flush the Session after an exception occurs,该怎么解决
- struts2关于request,session,application传值与显示的有关问题
- java ssh session NullPointerException,该怎么处理
- spring2.0+hibernate3.2中,oracle中产生大量的inactive session,怎么解决
- session 登录有关问题
- Cannot create a session after the response has been committed,该怎么解决
- org.hibernate.HibernateException: No Session found for current thread解决办法
- Cannot create a session after the response has been committed解决办法
- Struts2 的 Action 类里如何创建 session request response out 对象
- eclipse+jboss开发一个十分简单的远程无状态 Session Bean 时遇到的有关问题
- spring aop关于获取 session 有关问题
- Session 什么时候结束会话,怎么判断非正常登录
- WEB session 有关问题
- 一个纠结的有关问题-session
- 使用 StateServer 保存 Session,哪位高手用过啊
- Session.Remove()为啥不起作用
- session 没法自动注销
- 小弟新手 - Session 与 Cookies 用法