`
lliang54
  • 浏览: 4359 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

tomcat 7 下 session 的实现详解

 
阅读更多

session 是记录服务器会话的一个对象,他可以跟踪用户从登陆到关闭浏览器一系列动作,具体的创建代码

 

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

 

 

通过 HttpServletRequest 对象获取session 对象, 对应的tomcat 下的org.apache.catalina.connector.RequestFacade 的 getSession()方法 

 

 @Override
    public HttpSession getSession() {

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

        return getSession(true);
    }

     调用 getSession(create) 方法

 

 

   @Override
    //create 参数就是是否创建session 如果false,服务器中不存在对应的session,则返回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);
        }
    }

   将获取session转交给org.apache.catalina.connector.Request 类处理,RequestFacade  是Request 类的一个门面类,他包装了Request 的方法调用,对外开放,隐藏了Request 的实现细节,

 

调用了 Request 类的getSession(create) 方法

 

@Override
      
	public HttpSession getSession(boolean create) {
               //处理获取session
		Session session = doGetSession(create);
		if (session == null) {
			return null;
		}

		return session.getSession();
	}

 

 

    Session session = doGetSession(create);  这个session 是tomcat的session 接口,不是 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
		}
               //如果cookie 中的jsessionId ,或者是URL paramaters不为空,
                 // 通过manager 管理器查找session

 

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

   其中requestedSessionId 是 org.apache.catalina.connector.CoyoteAdapter 下的postParseRequest方法解析的,具体代码片段

           // 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();

 

    对session 的管理 是Manager 接口, org.apache.catalina 包下的。具体是实现类 是ManagerBase

 

  //如果cookie 中的jsessionId ,或者是URL paramaters不为空,通过manager 管理器查找session
		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);
			}
		}

    对应ManagerBase 类中的

 

 

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

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

    }

     sessions 是ManagerBase 对象的一个属性,

 

  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

 

分享到:
评论

相关推荐

    tomcat redis session.rar

    【标题】:“Tomcat Redis Session”指的是在Tomcat集群环境中,通过Redis来实现Session的共享与同步,以解决集群中的Session一致性问题。 【描述】:“Tomcat集群Nginx使用Redis保证Session同步”这一场景中,通常...

    tomcat5 session 复制

    总结起来,Tomcat5 的 Session 复制通过集群配置和 Web 应用配置两方面实现,确保了分布式环境下的会话一致性。配置过程中需注意端口冲突、网络可达性以及正确设置复制策略,以达到高效且稳定的 Session 同步效果。

    Tomcat与JavaWeb开发技术详解

    4.2 WebSocket:Tomcat7及以上版本支持WebSocket协议,实现双向通信,常用于实时聊天、游戏等场景。 4.3 SSL/TLS安全:Tomcat可以配置SSL连接,确保数据传输的安全性,支持各种证书类型和加密算法。 五、优化与...

    Tomcat+memcached+Nginx实现session共享

    从提供的链接中获取memcached-session-manager及其依赖的jar包,如memcached-session-manager-${version}.jar,memcached-session-manager-tc6或tc7-${version}.jar,spymemcached-2.7.3.jar等,根据Tomcat版本选择...

    Tomcat与JavaWeb开发技术详解源代码

    7. **MVC模式**:在JavaWeb开发中,Model-View-Controller模式被广泛使用,理解如何在Tomcat中实现这一模式,例如使用Spring MVC框架。 8. **session和cookie管理**:掌握如何在Web应用中实现用户会话管理和状态...

    Tomcat集群配置,实现session共享

    本文介绍了如何在JDK 1.8.0_131和Tomcat 8环境下搭建一个简单的Tomcat集群,并实现了Session共享。通过这些步骤,不仅可以提高系统的性能和可用性,还能更好地应对高并发场景下的访问需求。希望本文对您有所帮助!

    Memcached-session-manager所需最新jar包-tomcat7-kryo序列

    【描述】:“Memcached-session-manager所需的jar包-tomcat7-kryo序列”意味着为了实现Tomcat7服务器对用户会话的高效存储和管理,开发者选择了Memcached-session-manager这一中间件,并且采用了Kryo序列化技术。...

    Tomcat与java web 开发技术详解-孙卫琴-第二版

    《Tomcat与Java Web开发技术详解》是孙卫琴老师撰写的一本深入解析Java Web开发和Tomcat服务器的著作,其第二版进一步更新了内容,提供了更为详尽的指导。这本书针对初学者和有一定经验的开发者,旨在帮助读者掌握...

    Tomcat与Java Web开发技术详解源代码.rar

    源代码压缩包"Tomcat与Java Web开发技术详解源代码.rar"包含了书中所有示例的完整实现,为读者提供了动手实践的宝贵资源。 首先,Tomcat是Apache软件基金会下的一个开源项目,是一款轻量级的应用服务器,主要支持...

    Tomcat与Java Web开发技术详解(第2版) ,重新制作了完整书签目录,附勘误表

    《Tomcat与Java Web开发技术详解(第2版)》是由孙卫琴编著的一本深入探讨Java Web开发和Tomcat应用服务器的经典书籍。这本书详细介绍了如何使用Tomcat进行Java Web应用程序的部署和运行,是Java开发者的重要参考资料...

    tomcat5配置详解

    Tomcat 5是Apache软件基金会的Jakarta项目中的一个核心项目,是一个开源的Servlet容器,实现了Java Servlet和JavaServer Pages(JSP)规范。本文将深入探讨Tomcat 5的启动流程、目录结构以及配置详解。 1. **Tomcat...

    WebSocket的Java和Tomcat7使用示例

    ### WebSocket的Java和Tomcat7使用详解 #### 一、WebSocket简介 随着互联网技术的不断发展,Web应用变得越来越复杂,传统的HTTP协议已经无法满足实时通信的需求。为了改善这一状况,HTML5引入了WebSocket协议,这...

    memcached-session-manager tomcat7

    《基于Tomcat7的Memcached会话管理器详解》 在现代Web应用中,会话管理是不可或缺的一部分,它确保用户在浏览多个页面时能够保持登录状态和其他个性化设置。然而,随着分布式系统的普及,单一服务器的会话管理方式...

    Tomcat目录结构配置详解

    **Tomcat目录结构配置详解** Tomcat是一款广泛使用的开源Java Servlet容器,它是Apache软件基金会的Jakarta项目的一部分。深入理解Tomcat的目录结构对于优化服务器性能、管理应用程序以及进行安全配置至关重要。...

    tomcat-redis-session-manager

    【标题】"Tomcat-Redis-Session-Manager"是一个用于在Tomcat服务器中实现基于Redis的session管理解决方案。它使得Web应用的session数据能够在多个Tomcat实例之间共享,以实现负载均衡和高可用性。 【描述】这个项目...

Global site tag (gtag.js) - Google Analytics