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


// 《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;
		    }
		}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值