`
jameswxx
  • 浏览: 776525 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

tomcat之session实现

阅读更多

        由于HTTP是无状态的协议,客户程序每次都去web页面,都打开到web服务器的单独的连接,并且不维护客户的上下文信息。如果需要维护上下文信息,比如用户登录系统后,每次都能够知道操作的是此登录用户,而不是其他用户。对于这个问题,存在三种解决方案:cookie,url重写和隐藏表单域。

1 cookie
      cookie是一个服务器和客户端相结合的技术,服务器可以将会话ID发送到浏览器,浏览器将此cookie信息保存起来,后面再访问网页时,服务器又能够从浏览器中读到此会话ID,通过这种方式判断是否是同一用户。
 1 请求: 
 2 POST /ibsm/LoginAction.do HTTP/1.1 
 3 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */* 
 4 Referer: http://192.168.1.20:8080/crm/ 
 5 Accept-Language: zh-cn 
 6 Content-Type: application/x-www-form-urlencoded 
 7 UA-CPU: x86 
 8 Accept-Encoding: gzip, deflate 
 9 User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2) 
10 Host: 192.168.1.20:8080 
11 Content-Length: 13
12 Connection: Keep-Alive 
13 Cache-Control: no-cache 
14  
15 username=jack
16  
17 响应: 
18 HTTP/1.1 200 OK 
19 Server: Apache-Coyote/1.1 
20 Set-Cookie: JSESSIONID=3267A671BFEAA147A2383B7E083D4G7E; Path=/crm
21 Content-Type: text/html;charset=GBK 
22 Content-Length: 436 
23 Date: Sat, 10 June 2009 12:43:26 GMT


生成响应的时候,服务器向客户端发送cookie。cookie的属性是JSESSIONID,值是267A671BFEAA147A2383B7E083D4G7E。以后每次客户端请求时,都会附上此cookie,服务器端就可以读取到。
1    1. GET /ibsm/ApplicationFrame.frame HTTP/1.1 
2    2. Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */* 
3    3. Accept-Language: zh-cn 
4    4. UA-CPU: x86 
5    5. Accept-Encoding: gzip, deflate 
6    6. User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2) 
7    7. Host: 192.168.1.20:8080 
8    8. Connection: Keep-Alive 
9    9. Cookie: JSESSIONID=267A671BFEAA147A2383B7E083D4G7E

服务器端根据读取到的JSESSIONID,在一个map里面查找其对应的session对象,这个map的key是jsessionid的值,value是session对象。


2 URL重写
       重写这种方式,客户端程序在每个URL的尾部自动添加一些额外数据,这些数据以表示这个会话,比如http://192.168.1.20:8080/crm/getuserprofile.html;jsessionid=abc123。URL重写的额外数据是服务器自动添加的,那么服务器是怎么添加的呢?Tomcat在返回Response的时候,检查JSP页面中所有的URL,包括所有的链接,和 Form的Action属性,在这些URL后面加上“;jsessionid=xxxxxx”。添加url后缀的代码片段如下:
org.apache.coyote.tomcat5.CoyoteResponse类的toEncoded()方法支持URL重写。  
1 StringBuffer sb = new StringBuffer(path);
2         if( sb.length() > 0 ) { // jsessionid can't be first.
3             sb.append(";jsessionid=");
4             sb.append(sessionId);
5         }
6         sb.append(anchor);
7         sb.append(query);
8         return (sb.toString());


从上面URL的实现原理可知,URL重写有一个缺点:在你的站点上不能有任何静态的HTML页面(至少静态页面中不能有任何链接到站点动态页面的链接)。因此,每个页面都必须使用servlet或 JSP动态生成。即使所有的页面都动态生成,如果用户离开了会话并通过书签或链接再次回来,会话的信息都会丢失,因为存储下来的链接含有错误的标识信息-该URL后面的SESSION ID已经过期了。

3 隐藏表单域
       这种方式借助html表单中的hidden来实现,适用特定的一个流程,但是不适用于通常意义的会话跟踪。



4 服务器端实现原理
       综上所述,session实现会话跟踪通常是cookie和url重写,如果浏览器不禁止cookie 的话,tomcat优先使用cookie实现。 Session在服务器端具体是怎么实现的呢?我们使用session的时候一般都是这么使用的:
request.getSession()或者request.getSession(true)。
这个时候,服务器就检查是不是已经存在对应的Session对象,见HttpRequestBase类
doGetSession(boolean create)方法:
 1  if ((session != null) && !session.isValid())
 2             session = null;
 3         if (session != null)
 4             return (session.getSession());
 5
 7         // Return the requested session if it exists and is valid
 8         Manager manager = null;
 9         if (context != null)
10             manager = context.getManager();
11         if (manager == null)
12             return (null);      // Sessions are not supported
13         if (requestedSessionId != null) {
14             try {
15                 session = manager.findSession(requestedSessionId);
16             } catch (IOException e) {
17                 session = null;
18             }
19             if ((session != null) && !session.isValid())
20                 session = null;
21             if (session != null) {
22                 return (session.getSession());
23             }
24         }

requestSessionId从哪里来呢?这个肯定是通过Session实现机制的cookie或URL重写来设置的。见HttpProcessor 类中的parseHeaders(SocketInputStream input):
 1 for (int i = 0; i < cookies.length; i++) {
 2                     if (cookies[i].getName().equals
 3                         (Globals.SESSION_COOKIE_NAME)) {
 4                         // Override anything requested in the URL
 5                         if (!request.isRequestedSessionIdFromCookie()) {
 6                             // Accept only the first session id cookie
 7                             request.setRequestedSessionId
 8                                 (cookies[i].getValue());
 9                             request.setRequestedSessionCookie(true);
10                             request.setRequestedSessionURL(false);
11                            
12                         }
13                     }
14 }


或者HttpOrocessor类中的parseRequest(SocketInputStream input, OutputStream output)
 1 // Parse any requested session ID out of the request URI
 2         int semicolon = uri.indexOf(match);  //match 是";jsessionid="字符串
 3         if (semicolon >= 0) {
 4             String rest = uri.substring(semicolon + match.length());
 5             int semicolon2 = rest.indexOf(';');
 6             if (semicolon2 >= 0) {
 7                 request.setRequestedSessionId(rest.substring(0, semicolon2));
 8                 rest = rest.substring(semicolon2);
 9             } else {
10                 request.setRequestedSessionId(rest);
11                 rest = "";
12             }
13             request.setRequestedSessionURL(true);
14             uri = uri.substring(0, semicolon) + rest;
15             if (debug >= 1)
16                 log(" Requested URL session id is " +
17                     ((HttpServletRequest) request.getRequest())
18                     .getRequestedSessionId());
19         } else {
20             request.setRequestedSessionId(null);
21             request.setRequestedSessionURL(false);
22         }
23

里面的manager.findSession(requestSessionId)用于查找此会话ID对应的session对象。Tomcat实现是通过一个HashMap实现,见ManagerBase.java的findSession(String id):
1         if (id == null)
2             return (null);
3         synchronized (sessions) {
4             Session session = (Session) sessions.get(id);
5             return (session);
6         }

Session本身也是实现为一个HashMap,因为Session设计为存放key-value键值对,Tomcat里面Session实现类是 StandardSession,里面一个attributes属性:
1     /**
2      * The collection of user data attributes associated with this Session.
3      */
4     private HashMap attributes = new HashMap();


所有会话信息的存取都是通过这个属性来实现的。Session会话信息不会一直在服务器端保存,超过一定的时间期限就会被删除,这个时间期限可以在 web.xml中进行设置,不设置的话会有一个默认值,Tomcat的默认值是60。那么服务器端是怎么判断会话过期的呢?原理服务器会启动一个线程,一直查询所有的Session对象,检查不活动的时间是否超过设定值,如果超过就将其删除。见StandardManager类,它实现了Runnable 接口,里面的run方法如下:
 1     /**
 2      * The background thread that checks for session timeouts and shutdown.
 3      */
 4     public void run() {
 5
 6         // Loop until the termination semaphore is set
 7         while (!threadDone) {
 8             threadSleep();
 9             processExpires();
10         }
11
12     }
13
14     /**
15      * Invalidate all sessions that have expired.
16      */
17     private void processExpires() {
18
19         long timeNow = System.currentTimeMillis();
20         Session sessions[] = findSessions();
21
22         for (int i = 0; i < sessions.length; i++) {
23             StandardSession session = (StandardSession) sessions[i];
24             if (!session.isValid())
25                 continue;
26             int maxInactiveInterval = session.getMaxInactiveInterval();
27             if (maxInactiveInterval < 0)
28                 continue;
29             int timeIdle = // Truncate, do not round up
30                 (int) ((timeNow - session.getLastUsedTime()) / 1000L);
31             if (timeIdle >= maxInactiveInterval) {
32                 try {
33                     expiredSessions++;
34                     session.expire();
35                 } catch (Throwable t) {
36                     log(sm.getString("standardManager.expireException"), t);
37                 }
38             }
39         }
40
41     }


Session信息在create,expire等事情的时候都会触发相应的Listener事件,从而可以对session信息进行监控,这些 Listener只需要继承HttpSessionListener,并配置在web.xml文件中。如下是一个监控在线会话数的Listerner:
import java.util.HashSet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MySessionListener implements HttpSessionListener {      
 public void sessionCreated(HttpSessionEvent event) {            
 HttpSession session = event.getSession();            
ServletContext application = session.getServletContext();                          
 // 在application范围由一个HashSet集保存所有的 session            
 HashSet sessions = (HashSet) application.getAttribute("sessions");            
if (sessions == null) {                   
sessions = new HashSet();                   
application.setAttribute("sessions", sessions);            
}                          

// 新创建的session均添加到HashSet集中            
 sessions.add(session);            

// 可以在别处从application范围中取出sessions集合            
// 然后使用sessions.size()获取当前活动的session数,即为“在线人数”     
}      

public void sessionDestroyed(HttpSessionEvent event) {            
HttpSession session = event.getSession();            
 ServletContext application = session.getServletContext();            
 HashSet sessions = (HashSet) application.getAttribute("sessions");                          
 // 销毁的session均从HashSet集中移除            
sessions.remove(session);     
}
}

分享到:
评论

相关推荐

    tomcat实现session共享

    而`tomcat-redis-session-manager-1.2-tomcat-7.jar`则是Tomcat 7的Redis session manager实现。 以下是实现步骤: 1. **配置Redis服务器**:确保你有一个运行中的Redis服务器,可以是本地或者远程。配置好服务器...

    Tomcat8(Tomcat9)+redis实现Session共享(支持Redis集群)

    本教程将详细介绍如何利用Tomcat 8或9以及Redis实现Session共享,支持Redis集群,以提高系统的可伸缩性和数据一致性。 首先,我们需要理解Session的概念。Session是服务器端用于存储用户状态的一种机制,通常在用户...

    tomcat redis session.rar

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

    设定tomcat中session过期时间.txt

    在Web开发中,Session管理是确保用户状态跟踪的重要机制之一。Tomcat作为一款广泛使用的Java应用服务器及Servlet容器,提供了多种方式来设定Session的有效时长。这有助于开发者根据具体业务需求灵活调整Session的...

    tomcat8+memcached session共享

    2. `memcached-session-manager-1.8.3.jar`:这个库提供了session管理器,实现了将Tomcat的session数据存储到Memcached的能力。 3. `kryo-1.04.jar` 和 `kryo-serializers-0.11.jar`:Kryo是一个快速、高效的序列化...

    tomcat7集群实现session共享

    当我们谈论“Tomcat7集群实现session共享”时,我们关注的是如何在多个Tomcat实例之间有效地同步用户会话信息,以便在集群环境中提供高可用性和负载均衡。 首先,理解session共享的重要性。在Web应用中,session是...

    nginx+Redis+tomcat实现session共享jar

    包含的jar包如下: commons-pool2-2.0.jar jedis-2.5.2.jar tomcat-juli-adapters.jar tomcat-juli.jar tomcat-redis-session-manager1.2.jar

    linux.redis+tomcat实现session共享

    linux.tomcat-session共享.redis.安装包

    Tomcat_Session的持久化

    Tomcat_Session 的持久...Tomcat 提供了 StandardManager 和 PersistentManager 两个实现类来管理 Session,其中 PersistentManager 能够把 Session 对象保存到 Session Store 中,提供了更为灵活的 Session 管理功能。

    nginx实现多个tomcat7直接session共享所需jar包

    标题中的“nginx实现多个tomcat7直接session共享所需jar包”指的是在分布式系统环境中,使用Nginx作为反向代理服务器,将用户请求分发到多个Tomcat7应用服务器上,同时实现用户会话(Session)在这些服务器之间的...

    nginx+tomcat shiro实现多tomcat下session共享

    "nginx+tomcat shiro实现多tomcat下session共享"这一主题,就是探讨在这样的架构中,如何有效管理和共享session。 1. **Nginx的作用**: Nginx是一个高性能的HTTP和反向代理服务器,常用于负载均衡,可以将用户的...

    tomcat集群实现session复制

    在IT领域,特别是Web应用服务器的管理与优化中,Tomcat集群实现Session复制是一个关键的技术点,它确保了高可用性和负载均衡,特别是在处理大量并发请求的场景下。本文将深入探讨这一主题,涵盖其原理、配置方法以及...

    redis+tomcat实现session的jar

    标题中的"redis+tomcat实现session的jar"指的是在Tomcat服务器中利用Redis数据库来实现Web应用程序的会话(session)共享技术。Redis是一个高性能的键值存储系统,常用于缓存和分布式环境下的数据共享。在传统的Web...

    Tomcat memcached Session依赖jar包

    在Tomcat中集成memcached作为Session管理器,可以将Session数据分布在网络中的多个节点上,实现Session复制和高可用性。 为了在Tomcat中使用memcached进行Session管理,你需要以下关键的依赖jar包: 1. **...

    resis实现tomcat7 session 共享

    【标题】"resis实现tomcat7 session 共享"主要涉及的是在分布式环境中如何实现Tomcat服务器间的Session共享问题。Resin(ReStructured Servlet & JSP Engine)是一款轻量级、高性能的Java应用服务器,它支持Servlet...

    Tomcat实现session共享demo

    本示例将深入探讨如何使用Tomcat8与Redis相结合来实现session共享,这是一个高效且广泛应用的解决方案。 首先,我们需要理解什么是Session。在Web应用中,Session是用来跟踪用户状态的一种机制。当用户登录后,...

    tomcat集群session共享

    综上所述,实现Tomcat集群session共享主要涉及Tomcat的session管理机制、Redis的集成以及相应的配置和优化。通过合理配置,可以确保在高并发环境下提供无缝的用户体验,同时提升系统的可扩展性和可靠性。

    tomcat-redis-session-manager实现session共享 配置文件

    "tomcat-redis-session-manager"是一个解决方案,它将用户的Session信息存储在Redis缓存服务器中,从而实现跨服务器的Session共享。本篇文章将深入探讨这个话题,包括它的原理、配置以及实际应用。 **一、Session...

    tomcat-redis-session-tomcat tomcat集成redis实现tomcat集群session共享jar包

    2. `tomcat-catalina-8.0.9.jar`:这是Tomcat服务器的核心组件之一,包含了Catalina模块,负责处理Servlet容器的主要功能,包括session管理。这里的版本号8.0.9表明它是针对Tomcat 8的一个特定版本。 3. `jedis-...

    tomcat8实现session共享jar包

    此压缩包为tomcat8利用redis实现session共享所需要的jar包,包含(commons-pool2-2.6.0.jar、jedis-2.9.0.jar、tomcat-redis-session-manager.jar)直接将三个jar包复制Tomcat目录lib下面,在修改conf下context.xml...

Global site tag (gtag.js) - Google Analytics