Detailed implementation of session under tomcat 7

Session is an object that records the server session. It can track a series of actions of the user from logging in to closing the browser. The specific creation code

 

public void addSession(HttpServletRequest request,String key,String value){
		HttpSession session = request.getSession();
		session.setAttribute(key, value);
	}

 

 

Obtain the session object through the HttpServletRequest object, corresponding to the getSession() method of org.apache.catalina.connector.RequestFacade under tomcat 

 

@Override
    public HttpSession getSession() {

        if (request == null) {
            throw new IllegalStateException(
                            sm.getString("requestFacade.nullRequest"));
        }

        return getSession(true);
    }

     Call the getSession(create) method

 

 

   @Override
    //create parameter is whether to create a session. If false, there is no corresponding session in the server, then return null
    public HttpSession getSession(boolean create) {

        if (request == null) {
            throw new IllegalStateException(
                            sm.getString("requestFacade.nullRequest"));
        }

        if (SecurityUtil.isPackageProtectionEnabled()){
            return AccessController.
                doPrivileged(new GetSessionPrivilegedAction(create));
        } else {
            return request.getSession(create);
        }
    }

   Transfer the acquired session to the org.apache.catalina.connector.Request class for processing. RequestFacade is a facade class of the Request class. It wraps the method call of the Request and is open to the outside world, hiding the implementation details of the Request.

 

The getSession(create) method of the Request class is called

 

@Override
      
	public HttpSession getSession(boolean create) {
               / / Process to get the session
		Session session = doGetSession(create);
		if (session == null) {
			return null;
		}

		return session.getSession();
	}

 

 

    Session session = doGetSession(create); This session is the session interface of tomcat, not under java.javax.

 

protected Session doGetSession(boolean create) {

		// There cannot be a session if no context has been assigned yet
		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 = null;
		if (context != null) {
			manager = context.getManager();
		}
		if (manager == null) {
			return (null); // Sessions are not supported
		}
               //If the jsessionId in the cookie, or the URL paramaters is not empty,
                 // Find the session through the manager manager

 

		if (requestedSessionId != null) {
			try {
				session = manager.findSession(requestedSessionId);
			} 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);
		}
		if ((context != null)
				&& (response != null)
				&& context.getServletContext()
						.getEffectiveSessionTrackingModes()
						.contains(SessionTrackingMode.COOKIE)
				&& response.getResponse().isCommitted()) {
			throw new IllegalStateException(
				sm.getString("coyoteRequest.sessionCreateCommitted"));
		}

		// Attempt to reuse session id if one was submitted in a cookie
		// Do not reuse the session id if it is from a URL, to prevent possible
		// phishing attacks
		// Use the SSL session ID if one is present.
		if (("/".equals(context.getSessionCookiePath()) && isRequestedSessionIdFromCookie())
				|| requestedSessionSSL) {
			session = manager.createSession(getRequestedSessionId());
		} else {
			session = manager.createSession(null);
		}

		// Creating a new session cookie based on that session
		if ((session != null)
				&& (getContext() != null)
				&& getContext().getServletContext()
						.getEffectiveSessionTrackingModes()
						.contains(SessionTrackingMode.COOKIE)) {
			Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie(
				context, session.getIdInternal(), isSecure());

			response.addSessionCookieInternal(cookie);
		}

		if (session == null) {
			return null;
		}

		session.access();
		return session;
	}

   The requestedSessionId is  parsed by the postParseRequest method under org.apache.catalina.connector.CoyoteAdapter. The specific code snippet

           // Now we have the context, we can parse the session ID from the URL
            // (if any). Need to do this before we redirect in case we need to
            // include the session id in the redirect
            String sessionID = null;
            if (request.getServletContext().getEffectiveSessionTrackingModes()
                    .contains(SessionTrackingMode.URL)) {

                // Get the session ID if there was one
                sessionID = request.getPathParameter(
                        SessionConfig.getSessionUriParamName(
                                request.getContext()));
                if (sessionID != null) {
                    request.setRequestedSessionId(sessionID);
                    request.setRequestedSessionURL(true);
                }
            }

            // Look for session ID in cookies and SSL session
            parseSessionCookiesId(req, request);
            parseSessionSslId(request);

            sessionID = request.getRequestedSessionId();

 

    The management of the session is the Manager interface, under the org.apache.catalina package. Specifically, the implementation class is ManagerBase

 

  //If the jsessionId in the cookie, or the URL paramaters is not empty, find the session through the manager manager
		if (requestedSessionId != null) {
			try {
				session = manager.findSession(requestedSessionId);
			} catch (IOException e) {
				session = null;
			}
			if ((session != null) && !session.isValid()) {
				session = null;
			}
			if (session != null) {
				session.access();
				return (session);
			}
		}

    Corresponding to the ManagerBase class

 

 

   @Override
    public Session findSession(String id) throws IOException {

        if (id == null)
            return (null);
        return sessions.get(id);

    }

     sessions is a property of the ManagerBase object,

 

  protected Map<String, Session> sessions = new ConcurrentHashMap<String, Session>();

用并发的HashMap 来存放session信息,其中Key 值就是cookie 中对应的jsessionId,如果找到就返回找到的session 对象,如果没有找到并且create 参数是false ,表示不创建session 则 返回null,如果是true 就是创建session 对象,具体的创建session 对象的代码片段为:

 

 //判断cookie 中是否有jsessionId 如果有,就使用这个jsessionId ,如果没有就创建新的jsessionId
if (("/".equals(context.getSessionCookiePath()) && isRequestedSessionIdFromCookie())
				|| requestedSessionSSL) {
			session = manager.createSession(getRequestedSessionId());
		} else {
			session = manager.createSession(null);
		}

                //创建一个新的session cookie,基于刚刚创建好的session
		if ((session != null)
				&& (getContext() != null)
				&& getContext().getServletContext()
						.getEffectiveSessionTrackingModes()
						.contains(SessionTrackingMode.COOKIE)) {
			Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie(
				context, session.getIdInternal(), isSecure());

			response.addSessionCookieInternal(cookie);
		}

  关于session 中 cookie name 值默认是JSESSIONID ,如果在web.xml 中配置了session-config ,其中cookie-config 下的name 就是sessionCookieName 值,如果没有配置的话,就是默认

 具体代码如下:

  public static String getSessionCookieName(Context context) {

        String result = getConfiguredSessionCookieName(context);

        if (result == null) {
            result = DEFAULT_SESSION_COOKIE_NAME;
        }

        return result;
    }

   

具体创建session 的逻辑在ManagerBase 中 

 public Session createSession(String sessionId) {
        
        if ((maxActiveSessions >= 0) &&
                (getActiveSessions() >= maxActiveSessions)) {
            rejectedSessions++;
            throw new TooManyActiveSessionsException(
                    sm.getString("managerBase.createSession.ise"),
                    maxActiveSessions);
        }
        
        //创建一个空的session ,其实就是创建org.apache.catalina.session.StandardSession 对象,将该对象交由manager 管理
        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(this.maxInactiveInterval);
        String id = sessionId;
        if (id == null) {
            //生成sessionId,具体的生成SessionId 的逻辑在org.apache.catalina.util.SessionIdGenerator
    下的generateSessionId 方法,
            id = generateSessionId();
        }
        session.setId(id);
        sessionCounter++;

        SessionTiming timing = new SessionTiming(session.getCreationTime(), 0);
        synchronized (sessionCreationTiming) {
            sessionCreationTiming.add(timing);
            sessionCreationTiming.poll();
        }
        return (session);

    }
    

   以上就是创建HttpSession 的过程, 都是个人的理解,由于个人水平有限,还有很多地方没有讲清楚或者说错了,例如session 的持久化技术,具体可以参考 org.apache.catalina.session.StoreBase ,tomcat 提供两种持久化机制,分布是文件持久化,和jdbc 数据持久化 对应的类是FileStore,JDBCStore

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326816929&siteId=291194637