千家信息网

Tomcat9中如何管理session

发表于:2025-01-26 作者:千家信息网编辑
千家信息网最后更新 2025年01月26日,这篇文章主要介绍Tomcat9中如何管理session,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!源码解析session相关共有两个类:StandardSession:默认的
千家信息网最后更新 2025年01月26日Tomcat9中如何管理session

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

源码解析

session相关共有两个类:

  • StandardSession:默认的session的类,是对session的系统抽象

  • StandardManager:默认的session管理类,管理session的创建、加载、持久化等

    org.apache.catalina.core.StandardContext.startInternal()
protected synchronized void startInternal() throws LifecycleException {...省略其他代码...                Manager contextManager = null;                Manager manager = getManager();                if (manager == null) {                    if (log.isDebugEnabled()) {                        log.debug(sm.getString("standardContext.cluster.noManager",                                Boolean.valueOf((getCluster() != null)),                                Boolean.valueOf(distributable)));                    }                    if ((getCluster() != null) && 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 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"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

方法 管理 内容 文件 代码 篇文章 存储 两个 价值 兴趣 单机 实例 小伙 小伙伴 更多 源码 知识 系统 行业 资讯 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 济宁软件开发联系方式 e-r模型是反映数据库应用 景区售票系统软件开发 厦门共享按摩椅软件开发公司 阿里云服务器怎么安装手机游戏 北京时间校准服务器虚拟主机 网络安全记我心 新华电脑学校软件开发学费表 图数据库 种类 网络安全最新进展 数据库查询的顺序 收到信用中国数据库的信息 特嘉互联网科技有限公司 项目软件开发进度计划 西安比亚迪软件开发工程师工资 服务器设备管理器命令 塔科夫服务器还需要排队吗 怎么去分析电商数据库 arcgis加载数据库文件 服务器iis日志 城管局国家网络安全宣传周 芜湖安卓应用软件开发收费多少 数据库故障恢复的基本单元是 网络安全口号标语视频 建立wsus服务器的作用 金融业网络安全征文稿 金铲铲服务器绿色的进不去 国家网络安全保护宣传月活动 网络安全为什么要保证 网络安全审查制度有哪些业务
0