Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring HttpSessionListener.sessionDestroyed()方法在会话超时期间被调用两次_Spring_Servlets_Tomcat8 - Fatal编程技术网

Spring HttpSessionListener.sessionDestroyed()方法在会话超时期间被调用两次

Spring HttpSessionListener.sessionDestroyed()方法在会话超时期间被调用两次,spring,servlets,tomcat8,Spring,Servlets,Tomcat8,每当HTTP会话被破坏时,我都试图记录一条消息。 我在这个web应用程序中使用了Spring引导、Spring安全和Tomcat 8(嵌入式) @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (applicationContext instanceof WebApplicationContext) {

每当HTTP会话被破坏时,我都试图记录一条消息。 我在这个web应用程序中使用了Spring引导、Spring安全和Tomcat 8(嵌入式)

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    if (applicationContext instanceof WebApplicationContext) {
        ((WebApplicationContext) applicationContext).getServletContext().addListener(this);
    } else {
        //Either throw an exception or fail gracefully, up to you
        throw new RuntimeException("Must be inside a web application context");
    }
}
在会话超时期间,sessionDestroyed()方法被调用了两次,因此我的消息被记录了两次

我检查了会话ID,在两次调用期间,会话ID相同

这就是我的代码的样子

import org.springframework.security.core.session.SessionRegistry;

下面是sessionDestroyed()

@Override
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();

        SecurityContextImpl springSecurityContext = (SecurityContextImpl)session.getAttribute("SPRING_SECURITY_CONTEXT");
        if(springSecurityContext!=null){
            Authentication authentication = springSecurityContext.getAuthentication();
            LdapUserDetails userDetails = (LdapUserDetailsImpl)authentication.getPrincipal();

            WebAuthenticationDetails WebAuthenticationDetails = (WebAuthenticationDetails)authentication.getDetails();
            String userIp = WebAuthenticationDetails.getRemoteAddress();

            Log.info(userDetails.getUsername(),userIp,timestamp,"timeout or logout","session destroyed");

        }

       sessionRegistry.removeSessionInformation(se.getSession().getId());
        logger.info("Due to timeout/logout Session is Destroyed : Session ID is..." + session.getId());

    }
任何帮助都将不胜感激

注意:我注意到这个问题是Tomcat5中的一个缺陷,我不认为这个缺陷在Tomcat8中还没有修复


参考资料:

这不是Tomcat的错误。这是我的应用程序特有的错误

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    if (applicationContext instanceof WebApplicationContext) {
        ((WebApplicationContext) applicationContext).getServletContext().addListener(this);
    } else {
        //Either throw an exception or fail gracefully, up to you
        throw new RuntimeException("Must be inside a web application context");
    }
}
我在我的应用程序中发现以下代码

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    if (applicationContext instanceof WebApplicationContext) {
        ((WebApplicationContext) applicationContext).getServletContext().addListener(this);
    } else {
        //Either throw an exception or fail gracefully, up to you
        throw new RuntimeException("Must be inside a web application context");
    }
}
下一行将当前侦听器添加到Servlet上下文中

getServletContext().addListener(this);
由于Spring已经将这个监听器(MySessionListener)添加到Servlet上下文中,第二次添加监听器导致Tomcat的org.apache.catalina.session.StandardSession类调用第二个sessionDestroyed()方法

Tomcat的源代码仅供参考

package org.apache.catalina.session;

public class StandardSession implements HttpSession, Session, Serializable {

....

public void expire(boolean notify) {

.....

.....

 Object listeners[] = context.getApplicationLifecycleListeners();
                    if (listeners != null && listeners.length > 0) {
                        HttpSessionEvent event =
                            new HttpSessionEvent(getSession());
                        for (int i = 0; i < listeners.length; i++) {
                            int j = (listeners.length - 1) - i;
                            if (!(listeners[j] instanceof HttpSessionListener))
                                continue;
                            HttpSessionListener listener =
                                (HttpSessionListener) listeners[j];
                            try {
                                context.fireContainerEvent("beforeSessionDestroyed",
                                        listener);
                                listener.sessionDestroyed(event);
                                context.fireContainerEvent("afterSessionDestroyed",
                                        listener);
                            }

....
....