自己写的controller类: @Controller public class UserController { @Autowired UserService userService; @RequestMapping("/index.action") @ResponseBody public String index(HttpServletRequest req ,String name){ HttpSession session = req.getSession(true);//从这里开始解剖session,调用了RequestFacade类:getSession(boolean create) String id = session.getId(); System.out.println("id : "+id); Cookie[] cookies = req.getCookies(); //调用了RequestFacade类:getSession(boolean create) // for(Cookie c :cookies){ // System.out.println(c.getValue()); // } System.out.println(" /index.action name: "+name); return "index"; } }RequestFacade类: 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 // 调用Request类:getSession(boolean create),request为RequestFacade类的成员变量类型为Request类 return request.getSession(create); }Request类: public HttpSession getSession(boolean create) { Session session = doGetSession(create); //这里开始创建session if(session != null) return session.getSession(); else return null; } protected Session doGetSession(boolean create) { if(context == null) return null; if(session != null && !session.isValid()) session = null; if(session != null) return session; Manager manager = null; if(context != null) manager = context.getManager(); if(manager == null) return null; if(requestedSessionId != null) { try { session = manager.findSession(requestedSessionId);//现根据sessionId 查询,如果没有则创建 } catch(IOException e) { session = null; } if(session != null && !session.isValid()) session = null; if(session != null) { session.access(); return session; } } if(!create) return null; if(context != null && response != null && context.getCookies() && response.getResponse().isCommitted()) throw new IllegalStateException(sm.getString("coyoteRequest.sessionCreateCommitted")); if(connector.getEmptySessionPath() && isRequestedSessionIdFromCookie())
//根据请求中sessionID创建session,调用ManagerBase类:createSession(String sessionId) session = manager.createSession(getRequestedSessionId()); else
//调用ManagerBase类:createSession(String sessionId) session = manager.createSession(null); //这里是自动生成sessionID(往下看),并创建session
//创建session完成后,根据已经生成的或已有的sessionId创建cookie,并且把cookie加入response中反应给前台 if(session != null && getContext() != null && getContext().getCookies()) { String scName = context.getSessionCookieName(); if(scName == null) scName = Globals.SESSION_COOKIE_NAME; //拿取cookie的名字,可以自己配置,(如果没有配置cookie的名字则使用默认) Cookie cookie = new Cookie(scName, session.getIdInternal()); //根据cookieName 和 sessionID 创建一个cookie configureSessionCookie(cookie); //设置cookie的一些属性 response.addSessionCookieInternal(cookie, context.getUseHttpOnly());//将cookie设置到response中 } if(session != null) { session.access(); return session; //返回创建的session } else { return null; } } //设置cookie的一些属性 // cookie的发送限制是由 domain+path 进行限制的,解决客户端访问不同的服务器,传递对应的cookie protected void configureSessionCookie(Cookie cookie) { cookie.setMaxAge(-1); //设置永远不过时 Context ctxt = getContext(); String contextPath = null; if(ctxt != null && !getConnector().getEmptySessionPath()) if(ctxt.getSessionCookiePath() != null) contextPath = ctxt.getSessionCookiePath(); else contextPath = ctxt.getEncodedPath(); //设置在客户端保存cookie的路径 if(contextPath != null && contextPath.length() > 0) cookie.setPath(contextPath); //设置cookie的保存路径path(如果手动配置的话) else cookie.setPath("/"); //设置cookie的保存路径path,默认为根目录 / if(ctxt != null && ctxt.getSessionCookieDomain() != null) //设置域名domain,默认为 当前请求的域名,手动设置的时候必须以 . 开头 否者无效 //同时也暗示只能是子域名 cookie.setDomain(ctxt.getSessionCookieDomain()); if(isSecure()) cookie.setSecure(true); //设置安全模式 }
ManagerBase类: public Session createSession(String sessionId) { Session session = createEmptySession(); session.setNew(true); //设置为新的创建 session.setValid(true); //设置是有效的 session.setCreationTime(System.currentTimeMillis());//设置创建的时间 //60:为秒,设置存活时间默认 sessionTimeout = 30; 30分钟 session.setMaxInactiveInterval(((Context)getContainer()).getSessionTimeout() * 60); if(sessionId == null) //生成sessionId,永远不会重复,因为生成的时候会:sessions.containsKey(result) // 如果发现sessions 的key中存在了sessionID 则会重新生成,直到不存在返回生成的 sessionID sessionId = generateSessionId(); //给当的session设置sessionId并 保存当前新创建的session对象到 Map sessions 中,sessionId 作为key,session 作为v //保存的逻辑请看 调用了 ManagerBase类: add(Session session) 方法 session.setId(sessionId); sessionCounter++; SessionTiming timing = new SessionTiming(session.getCreationTime(), 0); synchronized(sessionCreationTiming) { sessionCreationTiming.add(timing); sessionCreationTiming.poll(); } return session; } //将session放入容器中 public void add(Session session) { sessions.put(session.getIdInternal(), session); //将session放入到 Map sessions 中 int size = sessions.size(); if(size > maxActive) synchronized(maxActiveUpdateLock) { if(size > maxActive) maxActive = size; } } 解剖tomcat 创建session的源码就到这里吧。
