This question already has an answer here:
这个问题在这里已有答案:
- javax.faces.application.ViewExpiredException: View could not be restored 10 answers
javax.faces.application.ViewExpiredException:无法恢复视图10个答案
This question is related to my other question "How to redirect to Login page when Session is expired in Java web application?". Below is what I'm trying to do:
这个问题与我的另一个问题“如何在Java Web应用程序中过期会话时重定向到登录页面?”有关。以下是我正在尝试做的事情:
- I've a JSF web application running on JBoss AS 5
- When the user is inactive for, say 15 minutes, I need to log out the user and redirect him to the login page, if he is trying to use the application after the session has expired.
- So, as suggested in 'JSF Logout and Redirect', I've implemented a filter which checks for the session expired condition and redirects the user to a session-timed-out.jsp page, if the session has expired.
- I've added SessionExpiryCheckFilter on top of all other filter definitions in web.xml, so that my session expiry check will get the first hit always.
我在JBoss AS 5上运行了一个JSF Web应用程序
当用户处于非活动状态时,例如15分钟,我需要注销用户并将其重定向到登录页面,如果他在会话过期后尝试使用该应用程序。
因此,正如'JSF Logout and Redirect'中所建议的那样,我已经实现了一个过滤器,它检查会话过期情况,并在会话过期时将用户重定向到session-timed-out.jsp页面。
我已经在web.xml中的所有其他过滤器定义之上添加了SessionExpiryCheckFilter,因此我的会话到期检查将始终获得第一次命中。
Now comes the challenge I'm facing. Since I'm using JBoss AS, when the session expired, JBoss automatically redirects me to the login page (note that the session expiry check filter is not invoked). So, after I log-in, my SessionExpiryCheckFilter intercepts the request, and it sees a session is available. But, it throws the exception javax.faces.application.ViewExpiredException: viewId:/mypage.faces - View /mypage.faces could not be restored.
现在面临着我所面临的挑战。由于我正在使用JBoss AS,当会话到期时,JBoss会自动将我重定向到登录页面(请注意,不会调用会话到期检查过滤器)。因此,在我登录后,我的SessionExpiryCheckFilter拦截了请求,并且它看到会话可用。但是,它抛出异常javax.faces.application.ViewExpiredException:viewId:/mypage.faces - 无法恢复视图/mypage.faces。
Have anyone faced this issue before? Any ideas to solve this issue?
以前有人遇到过这个问题吗?有什么想法可以解决这个问题?
5 个解决方案
#1
The following approach works for me. Note that you have to use the JSTL core taglib redirect and not the jsp redirect in order for this to work (as the jsp also expires).
以下方法适用于我。请注意,您必须使用JSTL核心taglib重定向而不是jsp重定向才能使其正常工作(因为jsp也会过期)。
In your FacesConfig.xml you put the following:
在FacesConfig.xml中,您输入以下内容:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/sessionExpired.jsf</location>
</error-page>
sessionExpired.jsp:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:redirect url="/login.jsf" />
You can also use this approach for other error types or exceptions. For example the element contains a mapping between an error code or exception type and the path of a resource in the web application.:
您还可以将此方法用于其他错误类型或异常。例如,元素包含错误代码或异常类型与Web应用程序中资源路径之间的映射:
<error-page>
<error-code>400</error-code>
<location>/400.html</location>
</error-page>
or element contains a fully qualified class name of a Java exception type.
或element包含Java异常类型的完全限定类名。
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/servlet/ErrorDisplay</location>
</error-page>
#2
If you are using Mojarra/Sun RI you might want to try to add this to your web.xml:
如果您使用的是Mojarra / Sun RI,可能需要尝试将其添加到web.xml:
<context-param>
<param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
<param-value>true</param-value>
</context-param>
However be aware that this isn't always the perfect solution. It hides the fact that the user has lost its session.
但请注意,这并不总是完美的解决方案。它隐藏了用户丢失会话的事实。
#3
Implement javax.faces.event.PhaseListener for Restore view
为Restore视图实现javax.faces.event.PhaseListener
@Override
public void afterPhase(PhaseEvent event) {
FacesContext facesContext = event.getFacesContext();
if(facesContext.getViewRoot()==null){
try{
facesContext.getExternalContext().redirect(HOME_PAGE);
facesContext.responseComplete();
} catch (IOException e){
e.printStackTrace();
}
}
}
@Override
public void beforePhase(PhaseEvent event) {}
@Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
register in faces-config.xml
在faces-config.xml中注册
#4
I would suggest writing a session listener in conjunction with the filter.
我建议结合过滤器编写会话监听器。
When the session expires you can create a new session object and set a timeout value on the new object.
会话到期时,您可以创建新的会话对象并在新对象上设置超时值。
Just check for the timeout value in the filter and redirect the browser.
只需检查过滤器中的超时值并重定向浏览器即可。
See http://www.java2s.com/Code/Java/Servlets/Servletsessionlistener.htm
#5
I tried to write a filter for it but some how it was not working for me, so I made an alternate for it.
我试着为它编写一个过滤器,但是有些它不适用于我,所以我为它做了一个替代。
I did it like this in every page that I don't want the user to access without Login:
我在每个页面都这样做,我不希望用户在没有登录的情况下访问:
<f:view>
<h:dataTable value="#{userHome.validuser()}"/>
// my code
<f:view/>
This will call the function validuser()
which is in my session managed bean.
这将调用我的会话管理bean中的函数validuser()。
Now this is my function. During login I already insert the user object into the session.
现在这是我的功能。在登录期间,我已经将用户对象插入到会话中。
public void validuser()
{
FacesContext context = FacesContext.getCurrentInstance();
UserLogin ul = (UserLogin) context.getExternalContext().getSessionMap().get("userbean");
if (ul == null)
try{
context.getExternalContext().redirect("/HIBJSF/faces/LoginPage.xhtml");
context.responseComplete();
}
catch (IOException e)
{
e.printStackTrace();
}
}
If there is a session but no one had logged in, then it will take you to a redirect page.
如果有会话但没有人登录,则会转到重定向页面。
#1
The following approach works for me. Note that you have to use the JSTL core taglib redirect and not the jsp redirect in order for this to work (as the jsp also expires).
以下方法适用于我。请注意,您必须使用JSTL核心taglib重定向而不是jsp重定向才能使其正常工作(因为jsp也会过期)。
In your FacesConfig.xml you put the following:
在FacesConfig.xml中,您输入以下内容:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/sessionExpired.jsf</location>
</error-page>
sessionExpired.jsp:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:redirect url="/login.jsf" />
You can also use this approach for other error types or exceptions. For example the element contains a mapping between an error code or exception type and the path of a resource in the web application.:
您还可以将此方法用于其他错误类型或异常。例如,元素包含错误代码或异常类型与Web应用程序中资源路径之间的映射:
<error-page>
<error-code>400</error-code>
<location>/400.html</location>
</error-page>
or element contains a fully qualified class name of a Java exception type.
或element包含Java异常类型的完全限定类名。
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/servlet/ErrorDisplay</location>
</error-page>
#2
If you are using Mojarra/Sun RI you might want to try to add this to your web.xml:
如果您使用的是Mojarra / Sun RI,可能需要尝试将其添加到web.xml:
<context-param>
<param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
<param-value>true</param-value>
</context-param>
However be aware that this isn't always the perfect solution. It hides the fact that the user has lost its session.
但请注意,这并不总是完美的解决方案。它隐藏了用户丢失会话的事实。
#3
Implement javax.faces.event.PhaseListener for Restore view
为Restore视图实现javax.faces.event.PhaseListener
@Override
public void afterPhase(PhaseEvent event) {
FacesContext facesContext = event.getFacesContext();
if(facesContext.getViewRoot()==null){
try{
facesContext.getExternalContext().redirect(HOME_PAGE);
facesContext.responseComplete();
} catch (IOException e){
e.printStackTrace();
}
}
}
@Override
public void beforePhase(PhaseEvent event) {}
@Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
register in faces-config.xml
在faces-config.xml中注册
#4
I would suggest writing a session listener in conjunction with the filter.
我建议结合过滤器编写会话监听器。
When the session expires you can create a new session object and set a timeout value on the new object.
会话到期时,您可以创建新的会话对象并在新对象上设置超时值。
Just check for the timeout value in the filter and redirect the browser.
只需检查过滤器中的超时值并重定向浏览器即可。
See http://www.java2s.com/Code/Java/Servlets/Servletsessionlistener.htm
#5
I tried to write a filter for it but some how it was not working for me, so I made an alternate for it.
我试着为它编写一个过滤器,但是有些它不适用于我,所以我为它做了一个替代。
I did it like this in every page that I don't want the user to access without Login:
我在每个页面都这样做,我不希望用户在没有登录的情况下访问:
<f:view>
<h:dataTable value="#{userHome.validuser()}"/>
// my code
<f:view/>
This will call the function validuser()
which is in my session managed bean.
这将调用我的会话管理bean中的函数validuser()。
Now this is my function. During login I already insert the user object into the session.
现在这是我的功能。在登录期间,我已经将用户对象插入到会话中。
public void validuser()
{
FacesContext context = FacesContext.getCurrentInstance();
UserLogin ul = (UserLogin) context.getExternalContext().getSessionMap().get("userbean");
if (ul == null)
try{
context.getExternalContext().redirect("/HIBJSF/faces/LoginPage.xhtml");
context.responseComplete();
}
catch (IOException e)
{
e.printStackTrace();
}
}
If there is a session but no one had logged in, then it will take you to a redirect page.
如果有会话但没有人登录,则会转到重定向页面。