Tomcat中session详解(源码阅读)

Tomcat中的session是通过一个manager来管理的,其中Session接口默认实现类有StandardSession,管理器的默认实现是StandardManager。

我们平时在servlet中使用的session也就是HashMap中的一个session对象,同时session除了在内存存储,同时还提供了持久化方法,tomcat中持久化有两种,一种是保存为文件,另一种则是保存到数据库。

这一节首先来看一下默认的StandardSession和StandardManager。


public interface Session {

    // ----------------------------------------------------- Manifest Constants

    public static final String SESSION_CREATED_EVENT = "createSession";

    public static final String SESSION_DESTROYED_EVENT = "destroySession";

    // ------------------------------------------------------------- Properties

    public String getAuthType();

    public void setAuthType(String authType);

    public long getCreationTime();

    public void setCreationTime(long time);

    public String getId();

    public void setId(String id);

    public String getInfo();

    public long getLastAccessedTime();

    public Manager getManager();

    public void setManager(Manager manager);

    public int getMaxInactiveInterval();

    public void setMaxInactiveInterval(int interval);

    public void setNew(boolean isNew);

    public Principal getPrincipal();

    public void setPrincipal(Principal principal);

    public HttpSession getSession();

    public void setValid(boolean isValid);

    public boolean isValid();

    // --------------------------------------------------------- Public Methods

    public void access();

    public void addSessionListener(SessionListener listener);

    public void expire();

    public Object getNote(String name);

    public Iterator getNoteNames();

    public void recycle();

    public void removeNote(String name);

    public void removeSessionListener(SessionListener listener);

    public void setNote(String name, Object value);

}

1.StandardManager中整个启动过程


 public void start() throws LifecycleException {

        if (debug >= 1)
            log("Starting");

        // Validate and update our current component state
        if (started)
            throw new LifecycleException
                (sm.getString("standardManager.alreadyStarted"));
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // Force initialization of the random number generator
        if (debug >= 1)
            log("Force random number initialization starting");
        String dummy = generateSessionId();
        if (debug >= 1)
            log("Force random number initialization completed");

        // Load unloaded sessions, if any
        try {
            //用于加载持久化的session,加载以后放入sessions(hashMap)中
            load();
        } catch (Throwable t) {
            log(sm.getString("standardManager.managerLoad"), t);
        }

        // Start the background reaper thread
        threadStart();

    }
//启动一个管理器线程,用于实现自动重新加载
 private void threadStart() {

        if (thread != null)
            return;

        threadDone = false;
        threadName = "StandardManager[" + container.getName() + "]";
        thread = new Thread(this, threadName);
        thread.setDaemon(true);
        thread.setContextClassLoader(container.getLoader().getClassLoader());
        thread.start();

    }

    /**
     * The background thread that checks for session timeouts and shutdown.
     */
    public void run() {

        // Loop until the termination semaphore is set
        while (!threadDone) {
            threadSleep();
            processExpires();
        }

    }

 private void threadSleep() {

        try {
            Thread.sleep(checkInterval * 1000L);
        } catch (InterruptedException e) {
            ;
        }

    }

 /**
     * Invalidate all sessions that have expired.
     */
    //管理StandardSession中session,去除无效的session
    private void processExpires() {

        long timeNow = System.currentTimeMillis();
        //获取存活的sessions
        Session sessions[] = findSessions();

        for (int i = 0; i < sessions.length; i++) {
            StandardSession session = (StandardSession) sessions[i];
            //有效,则不移除
            if (!session.isValid())
                continue;
            int maxInactiveInterval = session.getMaxInactiveInterval();
            //如果设置最大存活时间是-1,则不终止
            if (maxInactiveInterval < 0)
                continue;
            int timeIdle = // Truncate, do not round up
                (int) ((timeNow - session.getLastAccessedTime()) / 1000L);
            if (timeIdle >= maxInactiveInterval) {
                try {
                    session.expire();
                } catch (Throwable t) {
                    log(sm.getString("standardManager.expireException"), t);
                }
            }
        }

    }



2.StandardManager中整个停止过程

   public void stop() throws LifecycleException {

        if (debug >= 1)
            log("Stopping");

        // Validate and update our current component state
        if (!started)
            throw new LifecycleException
                (sm.getString("standardManager.notStarted"));
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;

        // Stop the background reaper thread
        threadStop();

        // Write out sessions
        try {
            //将存活的session持久化
            unload();
        } catch (IOException e) {
            log(sm.getString("standardManager.managerUnload"), e);
        }

        // Expire all active sessions
        Session sessions[] = findSessions();
        for (int i = 0; i < sessions.length; i++) {
            StandardSession session = (StandardSession) sessions[i];
            if (!session.isValid())
                continue;
            try {
            //终止所有的session
                session.expire();
            } catch (Throwable t) {
                ;
            }
        }

        // Require a new random number generator if we are restarted
        this.random = null;

 private void threadStop() {

        if (thread == null)
            return;

        threadDone = true;
        //将当前线程设置为中断状态
        thread.interrupt();
        try {
            //当前线程被挂起,直达thread线程结束才运行改线程
            thread.join();
        } catch (InterruptedException e) {
            ;
        }

        thread = null;

    }

1.StandardManager中创建一个session

 public Session createSession() {

        if ((maxActiveSessions >= 0) &&
          (sessions.size() >= maxActiveSessions))
            throw new IllegalStateException
                (sm.getString("standardManager.createSession.ise"));
//实际调用的是ManagerBase中的creatSession()方法
        return (super.createSession());

    }
 //ManagerBase类中creatSession方法
    public Session createSession() {

        // Recycle or create a Session instance
        Session session = null;
        synchronized (recycled) {
            int size = recycled.size();
            if (size > 0) {
                session = (Session) recycled.get(size - 1);
                recycled.remove(size - 1);
            }
        }
        if (session != null)
            session.setManager(this);
        else
            session = new StandardSession(this);

        // Initialize the properties of the new session and return it
        session.setNew(true);
        session.setValid(true);
        session.setCreationTime(System.currentTimeMillis());
        session.setMaxInactiveInterval(this.maxInactiveInterval);
        String sessionId = generateSessionId();
        String jvmRoute = getJvmRoute();
        // @todo Move appending of jvmRoute generateSessionId()???
        if (jvmRoute != null) {
            sessionId += ‘.‘ + jvmRoute;
            session.setId(sessionId);
        }
        /*
        synchronized (sessions) {
            while (sessions.get(sessionId) != null)        // Guarantee uniqueness
                sessionId = generateSessionId();
        }
        */
        session.setId(sessionId);

        return (session);

    }
时间: 2024-10-14 05:17:51

Tomcat中session详解(源码阅读)的相关文章

Java开源生鲜电商平台-Java后端生成Token架构与设计详解(源码可下载)

Java开源生鲜电商平台-Java后端生成Token架构与设计详解(源码可下载) 目的:Java开源生鲜电商平台-Java后端生成Token目的是为了用于校验客户端,防止重复提交. 技术选型:用开源的JWT架构. 1.概述:在web项目中,服务端和前端经常需要交互数据,有的时候由于网络相应慢,客户端在提交某些敏感数据(比如按照正常的业务逻辑,此份数据只能保存一份)时,如果前端多次点击提交按钮会导致提交多份数据,这种情况我们是要防止发生的. 2.解决方法: ①前端处理:在提交之后通过js立即将按钮

Shiro的Filter机制详解---源码分析

Shiro的Filter机制详解 首先从spring-shiro.xml的filter配置说起,先回答两个问题: 1, 为什么相同url规则,后面定义的会覆盖前面定义的(执行的时候只执行最后一个). 2, 为什么两个url规则都可以匹配同一个url,只执行第一个呢. 下面分别从这两个问题入手,最终阅读源码得到解答. 问题一解答 相同url但定义在不同的行,后面覆盖前面 如 /usr/login.do=test3 /usr/login.do=test1,test2 不会执行test3的filter

Python-Flask框架之——图书管理系统 , 附详解源码和效果图 !

该图书管理系统要实现的功能: 1. 可以通过添加窗口添加书籍或作者, 如果要添加的作者和书籍已存在于书架上, 则给出相应的提示. 2. 如果要添加的作者存在, 而要添加的书籍书架上没有, 则将该书籍添加到该作者栏. 3. 如果要添加的作者和书籍都不存在于书架上 , 则将书籍和作者一起添加. 4. 每个书籍和作者旁边都有一个删除按钮 , 点击删除书籍的按钮可以将该书籍删除 , 若某作者栏的书籍全部删除完毕则显示"无". 5. 若直接点击删除作者按钮, 则可以将该作者和其书籍一起全部删掉.

美容预约系统开发详解源码模式设计

美容预约系统开发(李想.185.6504.8478)美容一词可以从两个角度来理解.首选是"容"这个字,其次是"美"."容"包括脸.仪态.和修饰三层意思."美"则具有形容词和动词的两层含义.形容词表明的是美容的结果和目的是美丽的好看的:动词则表明的是美容的过程,即美化和改变的意思.预约系统是一种通过微信公众号或者app平台来实现一键预约服务的系统,常见的有游泳馆一键预约,美容一键预约,健身一键预约,按摩一键预约,诊所一键预约,试

RecyclerView实现瀑布流效果(图文详解+源码奉送)

最近有时间研究了一下RecyclerView,果然功能强大啊,能实现的效果还是比较多的,那么今天给大家介绍一个用RecyclerView实现的瀑布流效果. 先来一张效果图: 看看怎么实现吧: 整体工程目录结构: 这里要特别强调一点,有人可能不知道去哪里找android-support-v7-recyclerview.jar这个文件,其实它就在你下载的sdk目录下,我的是在D:\Program Files\Android\android-sdk\extras\android\support\v7\

Java7、8中HashMap和ConcurrentHashMap源码阅读

首先来看下HashMap的类继承结构: public class HashMap extends AbstractMap<K,V> impement Map<K,V>,Coloneable,Serializable{ } 可以看出HashMap实现了Map接口.其里面的方法都是非线程安全的,且不支持并发操作.对于HashMap主要看的是get/put方法实现,其在jdk1.7,及1.8在解决哈希冲突的上有所不同.一.Java7 HashMap 从上面的结构图中,可以大致看出,Has

凌煜云商城系统开发详解源码设计

凌煜云商城系统开发(李想.185.6504.8478)互联网是全球性的.这就意味着这个网络不管是谁发明了它,是属于全人类的.互联网的结构是按照"包交换"的方式连接的分布式网络.因此,在技术的层面上,互联网绝对不存在中央控制的问题.也就是说,不可能存在某一个国家或者某一个利益集团通过某种技术手段来控制互联网的问题.反过来,也无法把互联网封闭在一个国家之内-除非建立的不是互联网.然而,与此同时,这样一个全球性的网络,必须要有某种方式来确定联入其中的每一台主机.在互联网上绝对不能出现类似两个

Tomcat记录-tomcat常用配置详解和优化方法

常用配置详解 1 目录结构 /bin:脚本文件目录. /common/lib:存放所有web项目都可以访问的公共jar包(使用Common类加载器加载). /conf:存放配置文件,最重要的是server.xml. /logs:存放日志文件. /server/webapps:来管理Tomcat-web服务用的.仅对TOMCAT可见,对所有的WEB APP都不可见(使用Catalina类加载器加载). /shared/lib:仅对所有WEB APP可见,对TOMCAT不可见(使用Shared类加载

tomcat常用配置详解 及优化

常用配置详解 1 目录结构 /bin:脚本文件目录. /common/lib:存放所有web项目都可以访问的公共jar包(使用Common类加载器加载). /conf:存放配置文件,最重要的是server.xml. /logs:存放日志文件. /server/webapps:来管理Tomcat-web服务用的.仅对TOMCAT可见,对所有的WEB APP都不可见(使用Catalina类加载器加载). /shared/lib:仅对所有WEB APP可见,对TOMCAT不可见(使用Shared类加载