|
已经成功关注 zddava 的动态
Tomcat的Session管理(一) - Session的生成
博客分类:
Tomcat配置管理ApacheAccessF#
Session对象的创建一般是源于这样的一条语句:
Session session = request.getSession(false);或者Session session = request.getSession();如果不在乎服务器压力可能多那么一点点的话。
在Tomcat的实现中,这个request是org.apache.catalina.connector.Request类的包装类org.apache.catalina.connector.RequestFacade的对象,它的两个#getSession()方法如下:
Java代码
- public HttpSession getSession(boolean create) {
- if (request == null) {
- throw new IllegalStateException(
- sm.getString("requestFacade.nullRequest"));
- }
-
- if (SecurityUtil.isPackageProtectionEnabled()){
- return (HttpSession)AccessController.
- doPrivileged(new GetSessionPrivilegedAction(create));
- } else {
- return request.getSession(create);
- }
- }
Java代码
- public HttpSession getSession() {
- if (request == null) {
- throw new IllegalStateException(
- sm.getString("requestFacade.nullRequest"));
- }
-
- return getSession(true);
- }
其实差不太多,最后都会进入org.apache.catalina.connector.Request的#getSession()方法。这个方法的源代码如下:
Java代码
- public HttpSession getSession(boolean create) {
- Session session = doGetSession(create);
- if (session != null) {
- return session.getSession();
- } else {
- return null;
- }
- }
然后调用就到了#doGetSession()这个方法了。源代码如下
Java代码
- protected Session doGetSession(boolean create) {
- // 没有Context的话直接返回null
- if (context == null)
- return (null);
-
- // 判断Session是否有效
- if ((session != null) && !session.isValid())
- session = null;
- if (session != null)
- return (session);
-
- // 返回Manager对象,这里是StandardManager类的对象
- Manager manager = null;
- if (context != null)
- manager = context.getManager();
- if (manager == null)
- return (null); // Sessions are not supported
- // 判断是否有SessionID
- if (requestedSessionId != null) {
- try {
- // 在Manager中根据SessionID查找Session
- session = manager.findSession(requestedSessionId);
- } catch (IOException e) {
- session = null;
- }
- if ((session != null) && !session.isValid())
- session = null;
- if (session != null) {
- // 更新访问时间
- session.access();
- return (session);
- }
- }
-
- // 创建新的Session
- if (!create)
- return (null);
- if ((context != null) && (response != null) && context.getCookies()
- && response.getResponse().isCommitted()) {
- throw new IllegalStateException(sm.getString("coyoteRequest.sessionCreateCommitted"));
- }
-
- // 判断是否使用 "/" 作为Session Cookie的存储路径 并且 是否SessionID来自Cookie
- if (connector.getEmptySessionPath() && isRequestedSessionIdFromCookie()) {
- // 创建Session
- session = manager.createSession(getRequestedSessionId());
- } else {
- session = manager.createSession(null);
- }
-
- // 创建一个新的Session Cookies
- if ((session != null) && (getContext() != null) && getContext().getCookies()) {
- Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getIdInternal());
- // 配置Session Cookie
- configureSessionCookie(cookie);
- // 在响应中加入Session Cookie
- response.addCookieInternal(cookie);
- }
-
- if (session != null) {
- // 更新访问时间
- session.access();
- return (session);
- } else {
- return (null);
- }
-
- }
这个方法说明了Session创建的大致过程,首先判断requestedSessionId是否存在,如果存在,那么根据这个ID去查找Session对象。如果requestedSessionId不存在或者没有取到Session,并且传递给#getSession(boolean)的参数为真,那么要创建一个新的Session,并且给客户端写回去一个Session Cookie。
首先,我感兴趣的是requestedSessionId的赋值,它到底是什么时候被赋值的呢?
还要向回看Tomcat的请求处理过程,请求曾到过这一步,org.apache.catalina.connector.CoyoteAdapter的#service()方法。里边有这样一句方法调用:postParseRequest(req, request, res, response)。就是这一步处理了SessionID的获取,这个方法调用了#parseSessionId()和parseSessionCookiesId()这两个方法,就是它对Session ID进行了提取,源代码分别如下:
Java代码
- protected void parseSessionId(org.apache.coyote.Request req, Request request) {
-
- ByteChunk uriBC = req.requestURI().getByteChunk();
- // 判断URL中是不是有";jsessionid="这个字符串
- int semicolon = uriBC.indexOf(match, 0, match.length(), 0);
-
- if (semicolon > 0) {
- // Parse session ID, and extract it from the decoded request URI
- // 在URL中提取Session ID
- int start = uriBC.getStart();
- int end = uriBC.getEnd();
-
- int sessionIdStart = semicolon + match.length();
- int semicolon2 = uriBC.indexOf(';', sessionIdStart);
- if (semicolon2 >= 0) {
- request.setRequestedSessionId(new String(uriBC.getBuffer(), start + sessionIdStart,
- semicolon2 - sessionIdStart));
- byte[] buf = uriBC.getBuffer();
- for (int i = 0; i < end - start - semicolon2; i++) {
- buf[start + semicolon + i] = buf[start + i + semicolon2];
- }
- uriBC.setBytes(buf, start, end - start - semicolon2 + semicolon);
- } else {
- request.setRequestedSessionId(new String(uriBC.getBuffer(), start + sessionIdStart,
- (end - start) - sessionIdStart));
- uriBC.setEnd(start + semicolon);
- }
- // 设定Session ID来自于URL
- request.setRequestedSessionURL(true);
-
- } else {
- request.setRequestedSessionId(null);
- request.setRequestedSessionURL(false);
- }
-
- }
Java代码
- protected void parseSessionCookiesId(org.apache.coyote.Request req, Request request) {
- Context context = (Context) request.getMappingData().context;
- if (context != null && !context.getCookies())
- return;
-
- // 返回Cookie
- Cookies serverCookies = req.getCookies();
- int count = serverCookies.getCookieCount();
- if (count = 0) && (sessions.size() >= maxActiveSessions)) {
- rejectedSessions++;
- throw new IllegalStateException(sm.getString("standardManager.createSession.ise"));
- }
- return (super.createSession(sessionId));
- }
最后调用到了它的基类的#createSession()方法了。
Java代码
- public Session createSession(String sessionId) {
- // 创建一个新的Session
- Session session = createEmptySession();
-
- // 初始化Session的属性
- session.setNew(true);
- session.setValid(true);
- session.setCreationTime(System.currentTimeMillis());
- session.setMaxInactiveInterval(this.maxInactiveInterval);
- // 如果Session ID为null,那么就生成一个
- if (sessionId == null) {
- sessionId = generateSessionId();
- }
- session.setId(sessionId);
- sessionCounter++;
-
- return (session);
-
- }
通过上述过程,一个新的Session就创建出来了。
http://zddava.iteye.com/blog/311053 |
|
|