Java Spring MVC 处理会话已过期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24658203/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring MVC handling session expired
提问by Michel Foucault
I'm working with Jboss EAP 6.2
, Java EE 6
and Spring MVC 4.0.2
.
When the session expired I want to execute a page redirect.
我正在使用Jboss EAP 6.2
,Java EE 6
和Spring MVC 4.0.2
。当会话过期时,我想执行页面重定向。
I have developed a Spring Interceptor
我开发了一个Spring拦截器
@Component
public class SessionExpiredInterceptor extends HandlerInterceptorAdapter {
static final Logger logger = Logger.getLogger(SessionExpiredInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
final HttpSession session = request.getSession(false);
if ( session == null || session.isNew() ) {
ConfigurationProperties confProp = ConfigurationProperties.getInstance();
logger.info("Sessione scaduta, redirect home page");
request.getSession(true);
response.sendRedirect(request.getContextPath() + "/" +
confProp.getInstance().getProperty("session.expired.redirect"));
}
return true;
}
}
but I have the following exeception:
但我有以下例外:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.navigator': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: JBWEB000043: Cannot create a session after the response has been committed
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:353)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.getTarget(CglibAopProxy.java:676)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:627)
it.lispa.sire.finanziamentionline.web.mvc.model.Navigator$$EnhancerBySpringCGLIB$$b6b810e.addNavigationMessages(<generated>)
it.lispa.sire.finanziamentionline.web.mvc.UserSessionInterceptor.preHandle(UserSessionInterceptor.java:91)
org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:130)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
JBWEB000071: root cause
java.lang.IllegalStateException: JBWEB000043: Cannot create a session after the response has been committed
org.apache.catalina.connector.Request.doGetSession(Request.java:2627)
org.apache.catalina.connector.Request.getSession(Request.java:2361)
org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:790)
org.springframework.web.context.request.ServletRequestAttributes.getSession(ServletRequestAttributes.java:79)
org.springframework.web.context.request.ServletRequestAttributes.getSessionMutex(ServletRequestAttributes.java:212)
org.springframework.web.context.request.SessionScope.get(SessionScope.java:91)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:338)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.getTarget(CglibAopProxy.java:676)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:627)
it.lispa.sire.finanziamentionline.web.mvc.model.Navigator$$EnhancerBySpringCGLIB$$b6b810e.addNavigationMessages(<generated>)
it.lispa.sire.finanziamentionline.web.mvc.UserSessionInterceptor.preHandle(UserSessionInterceptor.java:91)
org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:130)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
The navigator bean is injected in some @Controller and other Interceptor.
navigator bean 被注入到一些@Controller 和其他Interceptor 中。
This is a Interceptor that use Navigator
bean:
这是一个使用Navigator
bean的拦截器:
@Component
public class UserSessionInterceptor extends HandlerInterceptorAdapter {
@Autowired
private Navigator navigator;
static final Logger logger = Logger.getLogger(UserSessionInterceptor.class.getName());
public static ConfigurationProperties getAuthenticationProps() throws IOException {
return ConfigurationProperties.getInstance();
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
...}
}
The following is the interceptor configuration in spring.xml
以下是拦截器中的配置 spring.xml
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**" />
<mvc:exclude-mapping path="/index.jsp" />
<mvc:exclude-mapping path="/logout" />
<mvc:exclude-mapping path="/ajax-logout" />
<bean class="it.lispa.sire.finanziamentionline.web.mvc.SessionExpiredInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/home"/>
<mvc:exclude-mapping path="/static/**" />
<mvc:exclude-mapping path="/logout" />
<mvc:exclude-mapping path="/ajax-logout" />
<bean class="it.lispa.sire.finanziamentionline.web.mvc.UserSessionInterceptor"/>
</mvc:interceptor>
Can you help me? Thanks.
你能帮助我吗?谢谢。
采纳答案by Sotirios Delimanolis
What happens here is that SessionExpiredInterceptor
acts before UserSessionInterceptor
. If it detects that the session is new, it performs a redirect
这里发生的事情是SessionExpiredInterceptor
之前的行为UserSessionInterceptor
。如果它检测到会话是新的,则执行重定向
response.sendRedirect(request.getContextPath() + "/" +
confProp.getInstance().getProperty("session.expired.redirect"));
Once you do a redirect, you've basically stated that you're finished processing the request and have sent a response (301 status code). But instead, in your code, you are returning true
from preHandle
which indicates to the DispatcherServlet
that it should continue handling the request, execute the other interceptors and eventually reach the @Controller
.
进行重定向后,您基本上已声明您已完成对请求的处理并已发送响应(301 状态代码)。但是,相反,在您的代码中,您true
从preHandle
which返回表明DispatcherServlet
它应该继续处理请求,执行其他拦截器并最终到达@Controller
.
You don't want this. In the if
block, return false
after the sendRedirect
.
你不想要这个。在if
块中,false
在 之后返回sendRedirect
。