Spring MVC handling session expired

只愿长相守 提交于 2019-12-10 20:57:32

问题


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.

I have developed a Spring Interceptor

@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.

This is a Interceptor that use 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

<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.


回答1:


What happens here is that SessionExpiredInterceptor acts before UserSessionInterceptor. If it detects that the session is new, it performs a redirect

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.

You don't want this. In the if block, return false after the sendRedirect.



来源:https://stackoverflow.com/questions/24658203/spring-mvc-handling-session-expired

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!