jetty对sessionId的处理分析
jetty7对sessionId的处理,首先入口在SessionHandler.java的doScope方法,jetty的源码分析可以参考这篇http://zhwj184.iteye.com/admin/blogs/1161542。
/* ------------------------------------------------------------ */ /* * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) */ @Override public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { setRequestedId(baseRequest,request); SessionManager old_session_manager=null; HttpSession old_session=null; try { old_session_manager = baseRequest.getSessionManager(); old_session = baseRequest.getSession(false); if (old_session_manager != _sessionManager) { // new session context baseRequest.setSessionManager(_sessionManager); baseRequest.setSession(null); } // access any existing session HttpSession session=null; if (_sessionManager!=null) { session=baseRequest.getSession(false); if (session!=null) { if(session!=old_session) { HttpCookie cookie = _sessionManager.access(session,request.isSecure()); if (cookie!=null ) // Handle changed ID or max-age refresh baseRequest.getResponse().addCookie(cookie); } } else { session=baseRequest.recoverNewSession(_sessionManager); if (session!=null) baseRequest.setSession(session); } } if(Log.isDebugEnabled()) { Log.debug("sessionManager="+_sessionManager); Log.debug("session="+session); } // start manual inline of nextScope(target,baseRequest,request,response); if (_nextScope!=null) _nextScope.doScope(target,baseRequest,request, response); else if (_outerScope!=null) _outerScope.doHandle(target,baseRequest,request, response); else doHandle(target,baseRequest,request, response); // end manual inline (pathentic attempt to reduce stack depth) } finally { HttpSession session=request.getSession(false); if (old_session_manager != _sessionManager) { //leaving context, free up the session if (session!=null) _sessionManager.complete(session); // Leave last session in place if (old_session_manager!=null ) { baseRequest.setSessionManager(old_session_manager); baseRequest.setSession(old_session); } } } }
setRequestedId(baseRequest,request); 就是从request请求中获取sessionId的过程,首先是从cookie中获取,获取不到再从url中获取,是否设置useCookie,也可以通过配置文件配置
/* ------------------------------------------------------------ */ /** Look for a requested session ID in cookies and URI parameters * @param baseRequest * @param request */ protected void setRequestedId(Request baseRequest, HttpServletRequest request) { String requested_session_id=request.getRequestedSessionId(); if (!DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()) || requested_session_id!=null) return; SessionManager sessionManager = getSessionManager(); boolean requested_session_id_from_cookie=false; HttpSession session=null; // Look for session id cookie if (_sessionManager.isUsingCookies()) { Cookie[] cookies=request.getCookies(); if (cookies!=null && cookies.length>0) { for (int i=0;i<cookies.length;i++) { if (sessionManager.getSessionCookie().equalsIgnoreCase(cookies[i].getName())) { if (requested_session_id!=null) { // Multiple jsessionid cookies. Probably due to // multiple paths and/or domains. Pick the first // known session or the last defined cookie. if (sessionManager.getHttpSession(requested_session_id)!=null) break; } requested_session_id=cookies[i].getValue(); requested_session_id_from_cookie = true; if(Log.isDebugEnabled())Log.debug("Got Session ID "+requested_session_id+" from cookie"); session=sessionManager.getHttpSession(requested_session_id); if (session!=null) baseRequest.setSession(session); } } } } if (requested_session_id==null || session==null) { String uri = request.getRequestURI(); String prefix=sessionManager.getSessionIdPathParameterNamePrefix(); if (prefix!=null) { int s = uri.indexOf(prefix); if (s>=0) { s+=prefix.length(); int i=s; while (i<uri.length()) { char c=uri.charAt(i); if (c==';'||c=='#'||c=='?'||c=='/') break; i++; } requested_session_id = uri.substring(s,i); requested_session_id_from_cookie = false; if(Log.isDebugEnabled()) Log.debug("Got Session ID "+requested_session_id+" from URL"); } } } baseRequest.setRequestedSessionId(requested_session_id); baseRequest.setRequestedSessionIdFromCookie(requested_session_id!=null && requested_session_id_from_cookie); }
sessionId的默认参数名为:JSESSIONID
/** * @return the session cookie name, by default "JSESSIONID". * @see #setSessionCookie(String) */ public String getSessionCookie(); /** * @return a formatted version of {@link #getSessionIdPathParameterName()}, by default * ";" + sessionIdParameterName + "=", for easier lookup in URL strings. * @see #getSessionIdPathParameterName() */ public String getSessionIdPathParameterNamePrefix();
而如果sessionId不存在,同样也是在request.getSession的时候才生成session,并且把sessionId的信息存入cookjie中
package org.eclipse.jetty.server; public class Request implements HttpServletRequest{ ...... /* ------------------------------------------------------------ */ /* * @see javax.servlet.http.HttpServletRequest#getSession() */ public HttpSession getSession() { return getSession(true); } /* ------------------------------------------------------------ */ /* * @see javax.servlet.http.HttpServletRequest#getSession(boolean) */ public HttpSession getSession(boolean create) { if (_sessionManager==null && create) throw new IllegalStateException("No SessionManager"); if (_session != null && _sessionManager!=null && _sessionManager.isValid(_session)) return _session; _session=null; String id=getRequestedSessionId(); if (id != null && _sessionManager!=null) { _session=_sessionManager.getHttpSession(id); if (_session == null && !create) return null; } if (_session == null && _sessionManager!=null && create ) { _session=_sessionManager.newHttpSession(this); HttpCookie cookie=_sessionManager.getSessionCookie(_session,getContextPath(),isSecure()); if (cookie!=null) _connection.getResponse().addCookie(cookie); } return _session; } ...... }
我们再看下如果session不存在,则会通过_sessionManager.newHttpSession(this);创建一个,创建过程如下:
/* ------------------------------------------------------------ */ /** * Create a new HttpSession for a request */ public HttpSession newHttpSession(HttpServletRequest request) { Session session=newSession(request); session.setMaxInactiveInterval(_dftMaxIdleSecs); addSession(session,true); return session; } /* ------------------------------------------------------------ */ //HashSessionManager的实现 @Override protected AbstractSessionManager.Session newSession(HttpServletRequest request) { return new HashedSession(request); } /** * Session from a request. * * @param request */ //JDBCSESSIONManager的实现 protected Session (HttpServletRequest request) { super(request); _data = new SessionData(_clusterId,_attributes); if (_dftMaxIdleSecs>0) _data.setMaxIdleMs(_dftMaxIdleSecs*1000); _data.setCanonicalContext(canonicalize(_context.getContextPath())); _data.setVirtualHost(getVirtualHost(_context)); _data.setExpiryTime(_maxIdleMs < 0 ? 0 : (System.currentTimeMillis() + _maxIdleMs)); }
而通过request创建对应SESSIONID的,sessionId分为两部分:clusterId和nodeId, nodeId就是SESSIONID
protected Session(HttpServletRequest request) { _newSession=true; _created=System.currentTimeMillis(); _clusterId=_sessionIdManager.newSessionId(request,_created); _nodeId=_sessionIdManager.getNodeId(_clusterId,request); _accessed=_created; _lastAccessed=_created; _requests=1; Log.debug("new session & id "+_nodeId+" "+_clusterId); }
JDBC的getNodeId
/** * Get the session id, including this node's id as a suffix. * * @see org.eclipse.jetty.server.SessionIdManager#getNodeId(java.lang.String, javax.servlet.http.HttpServletRequest) */ public String getNodeId(String clusterId, HttpServletRequest request) { if (_workerName!=null) return clusterId+'.'+_workerName; return clusterId; }
Hash的getNodeId
/* ------------------------------------------------------------ */ /** Get the session ID with any worker ID. * * @param clusterId * @param request * @return sessionId plus any worker ID. */ public String getNodeId(String clusterId,HttpServletRequest request) { // used in Ajp13Parser String worker=request==null?null:(String)request.getAttribute("org.eclipse.jetty.ajp.JVMRoute"); if (worker!=null) return clusterId+'.'+worker; if (_workerName!=null) return clusterId+'.'+_workerName; return clusterId; }
jetty是做好了集群sessionId生成的配置。