Tomcat9中如何管理session

技术Tomcat9中如何管理session这篇文章主要介绍Tomcat9中如何管理session,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!源码解析session相关共有两个类:Standard

这篇文章主要介绍Tomcat9中如何管理会话,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

源码解析

会话相关共有两个类:

标准会话:默认的会议的类,是对会议的系统抽象

标准管理器:默认的会议管理类,管理会议的创建、加载、持久化等

Tomcat9中如何管理session

org.apache.catalina.core.StandardContext.startInternal()

受保护的synchronizedvoidstarinternal()

.省略其他代码.

ManagercontextManager=null

managermanager=GetManager();

if(manager==null){ 0

if(log。isdebugenabled()){ 0

日志。调试(sm。GetString('标准上下文。集群。“经理”,

布尔型。((((GetCLuster()!=null)),

布尔值(可分配)));

}

if((((GetCLuster()!=n

ull) && distributable) {
                        try {
                            contextManager = getCluster().createManager(getName());
                        } catch (Exception ex) {
                            log.error(sm.getString("standardContext.cluster.managerError"), ex);
                            ok = false;
                        }
                    } else {
                        contextManager = new StandardManager();
                    }
                }
               // Configure default manager if none was specified
                if (contextManager != null) {
                    if (log.isDebugEnabled()) {
                        log.debug(sm.getString("standardContext.manager",
                                contextManager.getClass().getName()));
                    }
                    setManager(contextManager);
                }
...省略其他代码...
public void setManager(Manager manager) {
        Lock writeLock = managerLock.writeLock();
        writeLock.lock();
        Manager oldManager = null;
        try {
            // Change components if necessary
            oldManager = this.manager;
            if (oldManager == manager)
                return;
            this.manager = manager;
            // Stop the old component if necessary
            if (oldManager instanceof Lifecycle) {
                try {
                    ((Lifecycle) oldManager).stop();
                    ((Lifecycle) oldManager).destroy();
                } catch (LifecycleException e) {
                    log.error(sm.getString("standardContext.setManager.stop"), e);
                }
            }
            // Start the new component if necessary
            if (manager != null) {
                manager.setContext(this);
            }
            if (getState().isAvailable() && manager instanceof Lifecycle) {
                try {
                    ((Lifecycle) manager).start();
                } catch (LifecycleException e) {
                    log.error(sm.getString("standardContext.setManager.start"), e);
                }
            }
        } finally {
            writeLock.unlock();
        }
        // Report this property change to interested listeners
        support.firePropertyChange("manager", oldManager, manager);
    }
}

在StandardContext的start方法中,会对sessionManager进行实例化,这里是支持Tomcat的集群session,本文以单机session管理为例,即StandardManager,在setManager中会调用StandardManager.start

org.apache.catalina.session.StandardManager.start()
 protected synchronized void startInternal() throws LifecycleException {
        super.startInternal();
        // Load unloaded sessions, if any
        try {
            load();
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            log.error(sm.getString("standardManager.managerLoad"), t);
        }
        setState(LifecycleState.STARTING);
    }
protected String pathname = "SESSIONS.ser";
protected void doLoad() throws ClassNotFoundException, IOException {
        if (log.isDebugEnabled()) {
            log.debug("Start: Loading persisted sessions");
        }
        // Initialize our internal data structures
        sessions.clear();
        // Open an input stream to the specified pathname, if any
        File file = file();
        if (file == null) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("standardManager.loading", pathname));
        }
        Loader loader = null;
        ClassLoader classLoader = null;
        Log logger = null;
        try (FileInputStream fis = new FileInputStream(file.getAbsolutePath());
                BufferedInputStream bis = new BufferedInputStream(fis)) {
            Context c = getContext();
            loader = c.getLoader();
            logger = c.getLogger();
            if (loader != null) {
                classLoader = loader.getClassLoader();
            }
            if (classLoader == null) {
                classLoader = getClass().getClassLoader();
            }
            // Load the previously unloaded active sessions
            synchronized (sessions) {
                try (ObjectInputStream ois = new CustomObjectInputStream(bis, classLoader, logger,
                        getSessionAttributeValueClassNamePattern(),
                        getWarnOnSessionAttributeFilterFailure())) {
                    Integer count = (Integer) ois.readObject();
                    int n = count.intValue();
                    if (log.isDebugEnabled())
                        log.debug("Loading " + n + " persisted sessions");
                    for (int i = 0; i < n; i++) {
                        StandardSession session = getNewSession();
                        session.readObjectData(ois);
                        session.setManager(this);
                        sessions.put(session.getIdInternal(), session);
                        session.activate();
                        if (!session.isValidInternal()) {
                            // If session is already invalid,
                            // expire session to prevent memory leak.
                            session.setValid(true);
                            session.expire();
                        }
                        sessionCounter++;
                    }
                } finally {
                    // Delete the persistent storage file
                    if (file.exists()) {
                        if (!file.delete()) {
                            log.warn(sm.getString("standardManager.deletePersistedFileFail", file));
                        }
                    }
                }
            }
        } catch (FileNotFoundException e) {
            if (log.isDebugEnabled()) {
                log.debug("No persisted data file found");
            }
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug("Finish: Loading persisted sessions");
        }
    }
protected void doUnload() throws IOException {
        if (log.isDebugEnabled())
            log.debug(sm.getString("standardManager.unloading.debug"));
        if (sessions.isEmpty()) {
            log.debug(sm.getString("standardManager.unloading.nosessions"));
            return; // nothing to do
        }
        // Open an output stream to the specified pathname, if any
        File file = file();
        if (file == null) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("standardManager.unloading", pathname));
        }
        // Keep a note of sessions that are expired
        List<StandardSession> list = new ArrayList<>();
        try (FileOutputStream fos = new FileOutputStream(file.getAbsolutePath());
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                ObjectOutputStream oos = new ObjectOutputStream(bos)) {
            synchronized (sessions) {
                if (log.isDebugEnabled()) {
                    log.debug("Unloading " + sessions.size() + " sessions");
                }
                // Write the number of active sessions, followed by the details
                oos.writeObject(Integer.valueOf(sessions.size()));
                for (Session s : sessions.values()) {
                    StandardSession session = (StandardSession) s;
                    list.add(session);
                    session.passivate();
                    session.writeObjectData(oos);
                }
            }
        }
        // Expire all the sessions we just wrote
        if (log.isDebugEnabled()) {
            log.debug("Expiring " + list.size() + " persisted sessions");
        }
        for (StandardSession session : list) {
            try {
                session.expire(false);
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
            } finally {
                session.recycle();
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("Unloading complete");
        }
    }

在start方法中,会调用load方法,load方法最终调用doLoad方法,会读取文件名为SESSIONS.ser的文件,该文件存储了Tomcat关闭时session的内容,具体存储逻辑在doUnload方法中

Request.getSession()
public HttpSession getSession() {
        Session session = doGetSession(true);
        if (session == null) {
            return null;
        }
        return session.getSession();
    }
protected Session doGetSession(boolean create) {
        // There cannot be a session if no context has been assigned yet
        Context context = getContext();
        if (context == null) {
            return null;
        }
        // Return the current session if it exists and is valid
        if ((session != null) && !session.isValid()) {
            session = null;
        }
        if (session != null) {
            return session;
        }
        // Return the requested session if it exists and is valid
        Manager manager = context.getManager();
        if (manager == null) {
            return null;      // Sessions are not supported
        }
        if (requestedSessionId != null) {
            try {
                session = manager.findSession(requestedSessionId); //读取session
            } catch (IOException e) {
                session = null;
            }
            if ((session != null) && !session.isValid()) {
                session = null;
            }
            if (session != null) {
                session.access();
                return session;
            }
        }
        // Create a new session if requested and the response is not committed
        if (!create) {
            return null;
        }
        boolean trackModesIncludesCookie =
                context.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.COOKIE);
        if (trackModesIncludesCookie && response.getResponse().isCommitted()) {
            throw new IllegalStateException(sm.getString("coyoteRequest.sessionCreateCommitted"));
        }
        String sessionId = getRequestedSessionId();
        if (requestedSessionSSL) {
            // If the session ID has been obtained from the SSL handshake then
            // use it.
        } else if (("/".equals(context.getSessionCookiePath())
                && isRequestedSessionIdFromCookie())) {
            if (context.getValidateClientProvidedNewSessionId()) {
                boolean found = false;
                for (Container container : getHost().findChildren()) {
                    Manager m = ((Context) container).getManager();
                    if (m != null) {
                        try {
                            if (m.findSession(sessionId) != null) {
                                found = true;
                                break;
                            }
                        } catch (IOException e) {
                            // Ignore. Problems with this manager will be
                            // handled elsewhere.
                        }
                    }
                }
                if (!found) {
                    sessionId = null;
                }
            }
        } else {
            sessionId = null;
        }
        session = manager.createSession(sessionId); //创建新的session
        // Creating a new session cookie based on that session
        if (session != null && trackModesIncludesCookie) {
            Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie(
                    context, session.getIdInternal(), isSecure());
            response.addSessionCookieInternal(cookie);
        }
        if (session == null) {
            return null;
        }
        session.access();
        return session;
    }

在getSession方法中,会先根据sessionId在调用manager.findSession查找,如果查找不存在则会调用manager.createSession创建

findSession() & createSession()
public Session findSession(String id) throws IOException {
        if (id == null) {
            return null;
        }
        return sessions.get(id);
    }
public Session createSession(String sessionId) {
        if ((maxActiveSessions >= 0) &&
                (getActiveSessions() >= maxActiveSessions)) {
            rejectedSessions++;
            throw new TooManyActiveSessionsException(
                    sm.getString("managerBase.createSession.ise"),
                    maxActiveSessions);
        }
        // Recycle or create a Session instance
        Session session = createEmptySession();
        // Initialize the properties of the new session and return it
        session.setNew(true);
        session.setValid(true);
        session.setCreationTime(System.currentTimeMillis());
        session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60);
        String id = sessionId;
        if (id == null) {
            id = generateSessionId();
        }
        session.setId(id);
        sessionCounter++;
        SessionTiming timing = new SessionTiming(session.getCreationTime(), 0);
        synchronized (sessionCreationTiming) {
            sessionCreationTiming.add(timing);
            sessionCreationTiming.poll();
        }
        return session;
    }

所有的session为维护在一个HashMap中,在创建时会想Map中维护,读取是从Map中查找。

以上是“Tomcat9中如何管理session”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/138374.html

(0)

相关推荐

  • 银氨溶液化学式,氨与氨气的化学式是什么

    技术银氨溶液化学式,氨与氨气的化学式是什么氨就是氨气…… 化学式 NH3 1银氨溶液化学式、物理性质 相对分子质量 17.031 氨气在标准状况下的密度为0.7081g/L 氨气极易溶于水,溶解度1:700 2、化学性质

    生活 2021年10月30日
  • 数据库语句能通过脚本运行吗(数据库脚本版本管理)

    技术数据库日常维护常用的脚本语句是什么小编给大家分享一下数据库日常维护常用的脚本语句是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!  1

    攻略 2021年12月20日
  • Java正则表达式相关知识点有哪些

    技术Java正则表达式相关知识点有哪些这篇文章主要介绍“Java正则表达式相关知识点有哪些”,在日常操作中,相信很多人在Java正则表达式相关知识点有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望

    攻略 2021年11月20日
  • jquery中怎么显示和隐藏元素

    技术jquery中怎么显示和隐藏元素本篇内容介绍了“jquery中怎么显示和隐藏元素”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够

    攻略 2021年11月16日
  • java中如何实现WebSocket客户端断线重连

    技术java中如何实现WebSocket客户端断线重连这篇文章给大家分享的是有关java中如何实现WebSocket客户端断线重连的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Maven依赖<

    攻略 2021年10月31日
  • 小草怎么画,怎样画简笔画“冬虫夏草”

    技术小草怎么画,怎样画简笔画“冬虫夏草”方法小草怎么画:1、在白纸上用曲线画出冬虫夏草的轮廓。
    2、再用一条弯曲的曲线画出虫子的形态,这是一种冬天的形状。
    3、用曲线画出它的尾巴部分,这其实就像根须一样。
    4、再用小线条

    生活 2021年10月31日