您当前的位置: 首页 >  tomcat

恐龙弟旺仔

暂无认证

  • 0浏览

    0关注

    282博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

tomcat session过期时间的设置

恐龙弟旺仔 发布时间:2021-11-07 23:09:44 ,浏览量:0

前言:

笔者在工作中,碰到一个需求,需要根据不同的用户来设置不同的session过期时间。

搜索了半天之后,主要都是在web.xml中通过设置session-timeout参数来设置过期时间,如下所示:


      15

但是这样设置的,所有的session过期时间都是一样的。

如何设置不同的呢?网上也有答案,代码如下:

session.setMaxInactiveInterval(30*60);//以秒为单位

但是大家对这个参数的设置想法都不统一,有的说是全量的session,有的说是单独设置每个session的,也没有人能从源码角度来说明下,所以,笔者干脆自己下了tomcat的源码,源码在手,答案我有。

特意把这个过程整理为本文。

1.tomcat8.5源码下载导入

笔者公司使用的是tomcat8,所以特地下载了8.5的代码,笔者不需要编译,只需要把项目所需要的jar包引入下来即可。

由于其使用的是ant编译,笔者不太熟悉,所以就使用maven的方式引入包了。

1.1 创建pom.xml

我们主动在%tomcat_home%包路径下创建一个pom.xml,内容如下:




    4.0.0
    org.apache.tomcat
    Tomcat8.5
    Tomcat8.5
    8.5

    
        Tomcat8.5
        java
        
        
            
                java
            
        
        
            
                
            
        
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.1
                
                    UTF-8
                    1.8
                    1.8
                
            
        
    

    
        
            junit
            junit
            4.12
            test
        
        
            org.easymock
            easymock
            3.4
        
        
            ant
            ant
            1.7.0
        
        
            wsdl4j
            wsdl4j
            1.6.2
        
        
            javax.xml
            jaxrpc
            1.1
        
        
            org.eclipse.jdt.core.compiler
            ecj
            4.5.1
        
    
1.2 导入源码

导入就比较简单了,笔者使用idea导入,直接使用File -> Open 当前项目即可

pom.xml文件也通过Add Maven Project的方式引入进来,再点击Reimport即可,所需要的包都引入了下来。如下图所示:

 

2.HttpSession

tomcat中有关Session的接口是HttpSession,找到其实现类,默认为StandardSession。

2.1 StandardSession
public class StandardSession implements HttpSession, Session, Serializable {
 
    // session的相关属性集合
    protected ConcurrentMap attributes = new ConcurrentHashMap();
    // session创建时间
    protected long creationTime = 0L;
    // session是否过期
    protected transient volatile boolean expiring = false;
    // 唯一标识 id
    protected String id = null;
    // 这个参数比较重要,表示当前session最后一个被访问的时间,默认为创建时间
    protected volatile long lastAccessedTime = creationTime;
    
    // 这个就是我们要寻找的参数,后续介绍
    protected volatile int maxInactiveInterval = -1;
    
    // 当前访问时间 TODO
    protected volatile long thisAccessedTime = creationTime;
    
}
2.2 session过期判断
public class StandardSession implements HttpSession, Session, Serializable {
    // 判断当前session是否有效
	public boolean isValid() {
        if (!this.isValid) {
            return false;
        }
        if (this.expiring) {
            return true;
        }

        if (ACTIVITY_CHECK && accessCount.get() > 0) {
            return true;
        }

        // 主要在这里
        // 如果用户设置了maxInactiveInterval参数,则需要判断
        // 如果设置maxInactiveInterval=-1,说明永不过期
        if (maxInactiveInterval > 0) {
            // 获取session空闲时间
            int timeIdle = (int) (getIdleTimeInternal() / 1000L);
            // 如果距离最后一个访问时间已经超过了maxInactiveInterval,则将session置为过期
            if (timeIdle >= maxInactiveInterval) {
                expire(true);
            }
        }

        return this.isValid;
    }
    
    public long getIdleTimeInternal() {
        // 主要就是拿当前时间与最后一次访问时间做比较lastAccessedTime
        long timeNow = System.currentTimeMillis();
        long timeIdle;
        if (LAST_ACCESS_AT_START) {
            timeIdle = timeNow - lastAccessedTime;
        } else {
            timeIdle = timeNow - thisAccessedTime;
        }
        return timeIdle;
    }
}

所以通过源码可以知道,session是否过期的判断,主要是当前时间与session最后一次被访问时间之间的差值是否大于设置的maxInactiveInterval。

那么通过对不同的session设置不同的maxInactiveInterval是可以定制化session的过期时间的。

2.2 request与session

在request.getSession()获取session的时候,session的访问时间就已经被修改了。

public class Request implements HttpServletRequest {
	public HttpSession getSession() {
        Session session = doGetSession(true);
        if (session == null) {
            return null;
        }

        return session.getSession();
    }
    
    protected Session doGetSession(boolean create) {
		...
        Manager manager = context.getManager();
        if (manager == null) {
            return null;      // Sessions are not supported
        }
        if (requestedSessionId != null) {
            try {
                session = manager.findSession(requestedSessionId);
            } catch (IOException e) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("request.session.failed", requestedSessionId, e.getMessage()), e);
                } else {
                    log.info(sm.getString("request.session.failed", requestedSessionId, e.getMessage()));
                }
                session = null;
            }
            if ((session != null) && !session.isValid()) {
                session = null;
            }
            if (session != null) {
                // 设置session 访问时间,具体见2.2.1
                session.access();
                return session;
            }
        }
        ...
    }
}

2.2.1 StandardSession.access()

public class StandardSession implements HttpSession, Session, Serializable {
	public void access() {
        // 将当前session访问时间重置为当前时间
        this.thisAccessedTime = System.currentTimeMillis();
        if (ACTIVITY_CHECK) {
            accessCount.incrementAndGet();
        }
    }
}

访问结束后,会调用StandardSession.endAccess()方法,如下所示:

public class StandardSession implements HttpSession, Session, Serializable {
	public void endAccess() {
        isNew = false;
        // 重置lastAccessedTime和thisAccessedTime
        if (LAST_ACCESS_AT_START) {
            this.lastAccessedTime = this.thisAccessedTime;
            this.thisAccessedTime = System.currentTimeMillis();
        } else {
            this.thisAccessedTime = System.currentTimeMillis();
            this.lastAccessedTime = this.thisAccessedTime;
        }

        if (ACTIVITY_CHECK) {
            accessCount.decrementAndGet();
        }
    }
}

总结:

通过调用Session.setMaxInactiveInterval()方法可以自定义不同session的过期时间,且只对当前session有效。

关注
打赏
1655041699
查看更多评论
立即登录/注册

微信扫码登录

0.0383s