Jetty中提供了两个接口对seesion进行管理,SessionManager、SessionIdManager;且有对应的提供了两个抽象类,AbstractSessionManager,AbstractSessionIdManager;
具体怎么实现,上代码:
(1)首先一个客户端的request请求到达服务器,通过调用request.getSession调用SessionManager生成一个新的sessionId:
public HttpSession getSession(boolean create)
{
if (_session != null)
{
if (_sessionManager != null && !_sessionManager.isValid(_session))
_session = null;
else
return _session;
}
if (!create)
return null;
if (_sessionManager == null)
throw new IllegalStateException("No SessionManager");
_session = _sessionManager.newHttpSession(this);
HttpCookie cookie = _sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
if (cookie != null)
_connection.getResponse().addCookie(cookie);
return _session;
}
(2)通过_sessionManager.newHttpSession(this); 继续往下调用,newSession(request),最后发现它会调用AbstractSession的构造方法,其中_nodeId就是我们的sessionId;
public HttpSession newHttpSession(HttpServletRequest request)
{
AbstractSession session=newSession(request);
session.setMaxInactiveInterval(_dftMaxIdleSecs);
addSession(session,true);
return session;
}
protected AbstractSession(AbstractSessionManager abstractSessionManager, HttpServletRequest request)
{
_manager = abstractSessionManager;
_newSession=true;
_created=System.currentTimeMillis();
_clusterId=_manager._sessionIdManager.newSessionId(request,_created);
_nodeId=_manager._sessionIdManager.getNodeId(_clusterId,request);
_accessed=_created;
_lastAccessed=_created;
_requests=1;
_maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000L:-1;
if (LOG.isDebugEnabled())
LOG.debug("new session & id "+_nodeId+" "+_clusterId);
}
(3)具体看_manager._sessionIdManager.getNodeId(_clusterId,request);【这里看的是HashSessionIdManager的实现】是怎么实现的:它是由 clusterId+'.'+_workerName
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;
}
(4)接下来就看clusterId是怎么生成的,看步骤2中的_manager._sessionIdManager.newSessionId(request,_created):,最后返回值 id=_workerName + id;
public String newSessionId(HttpServletRequest request, long created)
{
synchronized (this)
{
if (request!=null)
{
// A requested session ID can only be used if it is in use already.
String requested_id=request.getRequestedSessionId();
if (requested_id!=null)
{
String cluster_id=getClusterId(requested_id);
if (idInUse(cluster_id))
return cluster_id;
}
// Else reuse any new session ID already defined for this request.
String new_id=(String)request.getAttribute(__NEW_SESSION_ID);
if (new_id!=null&&idInUse(new_id))
return new_id;
}
// pick a new unique ID!
String id=null;
while (id==null||id.length()==0||idInUse(id))
{
long r0=_weakRandom
?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^(((long)request.hashCode())<<32))
:_random.nextLong();
if (r0<0)
r0=-r0;
long r1=_weakRandom
?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^(((long)request.hashCode())<<32))
:_random.nextLong();
if (r1<0)
r1=-r1;
id=Long.toString(r0,36)+Long.toString(r1,36);
//add in the id of the node to ensure unique id across cluster
//NOTE this is different to the node suffix which denotes which node the request was received on
if (_workerName!=null)
id=_workerName + id;
}
request.setAttribute(__NEW_SESSION_ID,id);
return id;
}
}
结论,如果设置了workname,jetty的seesionid的规则为:workname+按照一定规则生成的id+“.”+workname,假如我的workname为mycis,则seesionid为mycisha6u3swt3ltxuk6rxad4ew2u.mycis;如没设置的话,就是为 按照一定规则生成的id :ha6u3swt3ltxuk6rxad4ew2u