`
lliang54
  • 浏览: 4054 次
  • 性别: 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如何监控并删除超时Session详解

    前言 偶然发现Tomcat会话时间的半小时,并不是说会话创建后,... StandardSession是标准的HttpSession实现,同时它也实现了Session接口,用于Tomcat内部管理 StandardSessionFacade,类名已经指明它就是一个“门面

    Ngxin+双tomcat负载+mem做session共享

    Tomcat集群 目录 Tomcat集群 1 一、环境介绍: 1 二、安装JDK 1 三、安装tomcat 2 四、安装nginx 2 ...6.4 修改tomcat中的server.xml文件 7 6.5放入项目文件 7 七、测试 7 八、关于tomcat的轮训模式 8

    Apache2.2.11 + Tomcat 6.0.20 集群配置详解

    最新Apache2.2.11 + Tomcat 6.0.20 集群配置详解,版主亲测试,并且布署了真实的项目进行了测试,session 成功共享。欢迎大家下载。

    孙卫琴《Tomcat与Java Web开发技术详解》培训讲义.rar

    孙卫琴《Tomcat与Java Web开发技术详解》培训讲义.rar 01__JavaWeb应用简介.pdf 02_Servlet技术.pdf 03_JSP技术.pdf 04_使用HTTP会话(Session).pdf 05_使用JavaBean.pdf 06_使用Servlet过滤器....

    Tomcat Nginx Redis实现session共享过程图解

    jar包:commons-pool2-2.4.2.jar、jedis-2.8.0.jar、tomcat-redis-session-manager-2.0.0.jar 二、配置Tomcat 多台Tomacat需要配置不同的端口号 /lib 将jar包存放到此位置 /conf/server.xml ​ ​ /conf/context.xml...

    redission-tomcat快速实现从单机部署到多机部署详解

    主要介绍了redission-tomcat快速实现从单机部署到多机部署详解,本文介绍一个基于redis的tomcat session管理开源项目:redission-tomcat,可无代码侵入式地快速实现session共享,需要的朋友可以参考下

    CentOS6.5下Tomcat7 Nginx Redis配置步骤教程详解

    注意:由于Redis配置对jar包和tomcat版本比较严格,请务必使用tomcat7和本文中提供的jar包。 下载地址: http://pan.baidu.com/s/1bO67Ky tomcat: tomcat1 localhost:8080 tomcat2 localhost:9080 nginx: ...

    详解SpringSession架构与设计

    开始进行Web开发时,您可能在使用...容器(例如Tomcat、Jetty)包含Session的实现,当服务器重启之后,之前的登录状态会失效需要重新登录。 我们先从HTTP协议说起。HTTP协议有个特点,是无状态的,意味着请求与请求是没

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    14.8.7 设定内容类别的实现类SetContentTypeImpl.java 14.8.8 发布实现类EditImpl.java 14.9 编写内容管理系统的控制器类 14.9.1 登录控制器类LoginAction.java 14.9.2 注册控制器类RegeditAction.java 14.9.3 设定...

    详解基于Centos7+Nginx+Tomcat8的负载均衡服务器的搭建

    由于工作的需求,在使用中,需要搭建负载均衡,研究了Apache+Tomat负载均衡的方案,并且通过检索相关的文章,进行了比较发现,Apache负载负载均衡在使用的效率上,远远不如Nginx的效率高,因此决定使用Nginx来进行...

    Nginx服务器详解加配置教程

    目录 常见WEB服务器 1 1、Nginx简介 2 2、反向代理Web服务器的“经纪人” 2 2.1反向代理初印象 2 2.2反向代理的作用 3 3、安装及配置 5 3.1下载 5 ...4.1.1 配置Tomcat的session共享可以有三种解决方案: 13

    深入Memcache的Session数据的多服务器共享详解

    当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识- 称为sessionid,如果已包含一个sessionid则说明以前已经为此客户端创建过session,服务器就...

    低清版 大型门户网站是这样炼成的.pdf

    1.2.5 支持集群功能的web服务器tomcat 21 1.2.6 开源数据库服务器之骄子mysql 23 1.2.7 功能强大的flv流媒体服务器red5 24 1.3 门户网站开发指导思想 26 1.4 ssh 2组合框架—门户网站开发之首选 28 1.4.1 mvc...

    JAVA高并发高性能高可用高扩展架构视频教程

    WEB服务器优化之Tomcat7性能调优 JVM概述 Java开发技术之(项目工程的日志管理) 数据库连接池原理详解 Java企业级框架之核心技术(反射) Java-Base64算法(创新_防止表单重复提交) 揭开springAOP神秘面纱之动态代理 ...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part2

    7.1 配置任意目录下的web应用程序 240 7.2 war文件 242 7.3 tomcat中servlet的另一种运行方式 244 7.4 与servlet配置相关的元素 247 7.4.1 [servlet]元素及其子元素 247 7.4.2 [servlet-mapping]元素及其子元素...

    《程序天下:J2EE整合详解与典型案例》光盘源码

    14.8.7 设定内容类别的实现类SetContentTypeImpl.java 14.8.8 发布实现类EditImpl.java 14.9 编写内容管理系统的控制器类 14.9.1 登录控制器类LoginAction.java 14.9.2 注册控制器类RegeditAction.java 14.9.3 设定...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    7.1 配置任意目录下的web应用程序 240 7.2 war文件 242 7.3 tomcat中servlet的另一种运行方式 244 7.4 与servlet配置相关的元素 247 7.4.1 [servlet]元素及其子元素 247 7.4.2 [servlet-mapping]元素及其子元素...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (2)

    14.8.7 设定内容类别的实现类SetContentTypeImpl.java 14.8.8 发布实现类EditImpl.java 14.9 编写内容管理系统的控制器类 14.9.1 登录控制器类LoginAction.java 14.9.2 注册控制器类RegeditAction.java 14.9.3 设定...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    14.8.7 设定内容类别的实现类SetContentTypeImpl.java 14.8.8 发布实现类EditImpl.java 14.9 编写内容管理系统的控制器类 14.9.1 登录控制器类LoginAction.java 14.9.2 注册控制器类RegeditAction.java 14.9.3 设定...

Global site tag (gtag.js) - Google Analytics