Tomcat8.x Servlet应用 Session的机制(初始化、读取、序列化)

来源:互联网 发布:php报名系统源码 编辑:程序博客网 时间:2024/05/04 16:08


// 《Tomcat8.x Servlet应用 Session的机制 》// ----------------------------------// 创建Session管理器,Session的初始化 -------------1// ----------------------------------class org.apache.catalina.core.StandardContext{protected synchronized void startInternal() throws LifecycleException {// Acquire clustered manager            Manager contextManager = null;            Manager manager = getManager();            if (manager == null) {                if ( (getCluster() != null) && distributable) { // 如果有配置集群/并且启动了分布式                    try {                        contextManager = getCluster().createManager(getName());                    } catch (Exception ex) {                        log.error("standardContext.clusterFail", ex);                        ok = false;                    }                } else {                    contextManager = new StandardManager(); // 上下文管理器,Session管理器                }            }            // Configure default manager if none was specified            if (contextManager != null) {                setManager(contextManager); // 设置上下文管理器,Session管理器            }                        // Start manager                Manager manager = getManager();                if (manager instanceof Lifecycle) {                // org.apache.catalina.session.StandardManager                    ((Lifecycle) manager).start(); // 启动上下文管理器,即启动Session管理器,加载服务器上的Session文件                }}}// Session管理器class org.apache.catalina.session.StandardManager{protected synchronized void startInternal() throws LifecycleException {        super.startInternal();        // Load unloaded sessions, if any                    load(); // 加载服务器上的Session文件        setState(LifecycleState.STARTING);    }// 加载服务器上的Session文件public void load() throws ClassNotFoundException, IOException {            doLoad(); // 加载服务器上的Session文件    }// 加载服务器上的Session文件protected void doLoad() throws ClassNotFoundException, IOException {        // Initialize our internal data structures        sessions.clear();        // Open an input stream to the specified pathname, if any        File file = file();//!!! 在临时目录中读取Session信息        if (file == null) {            return;        }        Loader loader = null;        ClassLoader classLoader = null;        Log logger = null;        try (FileInputStream fis = new FileInputStream(file.getAbsolutePath());                BufferedInputStream bis = new BufferedInputStream(fis)) {        // org.apache.catalina.core.StandardContext            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) { // 解析Session文件内容                try (ObjectInputStream ois = new CustomObjectInputStream(bis, classLoader, logger,                        getSessionAttributeValueClassNamePattern(),                        getWarnOnSessionAttributeFilterFailure())) { // 读取d:/a/b/tomcat8.x/work/Catalina/localhost/test/SESSIONS.ser                    Integer count = (Integer) ois.readObject(); // 读取Session对象                    int n = count.intValue();                    for (int i = 0; i < n; i++) { // org.apache.catalina.session.StandardSession                        StandardSession session = getNewSession(); // 创建StandardSession                        session.readObjectData(ois); // 解析Session文件                        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()) {                        file.delete();                    }                }            }        }    }// 查找Session文件protected File file() {        if (pathname == null || pathname.length() == 0) {            return null;        }        File file = new File(pathname);// SESSIONS.ser        if (!file.isAbsolute()) {        // context === org.apache.catalina.core.StandardContext            Context context = getContext();            ServletContext servletContext = context.getServletContext();            File tempdir = (File) servletContext.getAttribute(ServletContext.TEMPDIR);            if (tempdir != null) {                file = new File(tempdir, pathname); // 从临时目录中加载Session文件            }        }        return file;    }}// ----------------------------------// Session 的调用 -------------2// ----------------------------------HttpSession httpSession = req.getSession();httpSession.setAttribute("userInfo", "userInfo_Value");httpSession.getAttribute("userInfo");class org.apache.catalina.connector.RequestFacade{public HttpSession getSession() {        return getSession(true);    }public HttpSession getSession(boolean create) {            return request.getSession(create);    }}class org.apache.catalina.connector.Request{public HttpSession getSession(boolean create) {        Session session = doGetSession(create);//!!!        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(); // org.apache.catalina.core.StandardContext        if (context == null) {            return (null);        }        // Return the current session if it exists and is valid        if ((session != null) && !session.isValid()) { // 如果Session已经过期,从session管理中删除本对象,就返回空            session = null;        }        if (session != null) {            return (session);        }        // Return the requested session if it exists and is valid        // org.apache.catalina.session.StandardManager        Manager manager = context.getManager();        if (manager == null) {            return (null);      // Sessions are not supported        }        if (requestedSessionId != null) {            try {            // manager === org.apache.catalina.session.StandardManager            //查找SessionID是否已经存在                session = manager.findSession(requestedSessionId);            } catch (IOException e) {                session = null;            }            if ((session != null) && !session.isValid()) { // 如果Session已经过期,从session管理中删除本对象,就返回空                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);        }        if (response != null                && context.getServletContext()                        .getEffectiveSessionTrackingModes()                        .contains(SessionTrackingMode.COOKIE)                && response.getResponse().isCommitted()) {  // 如果在cookie发送之前已经发送了其他响应内容了,就报错            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;        }        // manager == org.apache.catalina.session.StandardManager        session = manager.createSession(sessionId);//!!!! 创建Session对象        // Creating a new session cookie based on that session        if (session != null                && context.getServletContext()                        .getEffectiveSessionTrackingModes()                        .contains(SessionTrackingMode.COOKIE)) {        // 创建Session的Cookie            Cookie cookie =                ApplicationSessionCookieConfig.createSessionCookie(                        context, session.getIdInternal(), isSecure());            // 添加响应Cookie            response.addSessionCookieInternal(cookie);        }        if (session == null) {            return null;        }        session.access();//!!! // 访问次数+1        return session;    }}// ----------------------------------// Session 的调用 -------------的保存(序列化)// ----------------------------------class org.apache.catalina.core.StandardContext{protected synchronized void stopInternal() throws LifecycleException {// 保存Session信息// manager == org.apache.catalina.session.StandardManager            Manager manager = getManager();            if (manager instanceof Lifecycle && ((Lifecycle) manager).getState().isAvailable()) {                ((Lifecycle) manager).stop();            }}}class org.apache.catalina.session.StandardManager{protected synchronized void stopInternal() throws LifecycleException {        setState(LifecycleState.STOPPING);        // Write out sessions        try {            unload(); // 保存Session数据到文件中        } catch (Throwable t) {        }        // Expire all active sessions  让活动中的Session全部失效        Session sessions[] = findSessions();        for (int i = 0; i < sessions.length; i++) {            Session session = sessions[i];                if (session.isValid()) {                     session.expire(); //                 }        }        // Require a new random number generator if we are restarted        super.stopInternal();    }// 保存Session数据到文件中public void unload() throws IOException {            doUnload();    }protected void doUnload() throws IOException {        // Open an output stream to the specified pathname, if any        File file = file();        if (file == null) {            return;        }        // Keep a note of sessions that are expired        ArrayList<StandardSession> list = new ArrayList<>();        try (FileOutputStream fos = new FileOutputStream(file.getAbsolutePath());                BufferedOutputStream bos = new BufferedOutputStream(fos);                ObjectOutputStream oos = new ObjectOutputStream(bos)) { // 写入d:/a/b/tomcat8.x/work/Catalina/localhost/test/SESSIONS.ser            synchronized (sessions) {                // Write the number of active sessions, followed by the details                oos.writeObject(Integer.valueOf(sessions.size()));                Iterator<Session> elements = sessions.values().iterator();                while (elements.hasNext()) {                    StandardSession session =                        (StandardSession) elements.next();                    list.add(session);                    session.passivate();                    session.writeObjectData(oos);  // 写入Session的数据                }            }        }        // Expire all the sessions we just wrote        Iterator<StandardSession> expires = list.iterator();        while (expires.hasNext()) {        // org.apache.catalina.session.StandardSession            StandardSession session = expires.next();            try {                session.expire(false);            } catch (Throwable t) {                ExceptionUtils.handleThrowable(t);            } finally {                session.recycle();            }        }    }protected File file() {        if (pathname == null || pathname.length() == 0) {            return null;        }        File file = new File(pathname);// SESSIONS.ser        if (!file.isAbsolute()) {        // context === org.apache.catalina.core.StandardContext            Context context = getContext();            ServletContext servletContext = context.getServletContext();            File tempdir = (File) servletContext.getAttribute(ServletContext.TEMPDIR);            if (tempdir != null) {                file = new File(tempdir, pathname); // 从临时目录中加载Session文件            }        }        return file;    }}




0 0