session作为会话的标识,Servlet容器会把它自动管理起来,在需要的时候创建Session对象。
当我们调用org.apache.catalina.connector.Request的getSession(true) 和changeSessionId(String newSessionId) 方法时,Servlet容器就会尝试创建新的Session。在创建之前会做一些前置检查:
是否已经有session
当前session是否已失效
确定需要创建session后,默认通过StandardManager 来创建,创建成功后会记录在一个Map 对象中。具体创建逻辑在StandardManager的父类ManagerBase.createSession() 中,代码非常简洁:
public Session createSession(String sessionId) {if ((maxActiveSessions >= 0) &&(getActiveSessions() >= maxActiveSessions)) {rejectedSessions++;throw new TooManyActiveSessionsException(sm.getString("managerBase.createSession.ise"),maxActiveSessions);}// Recycle or create a Session instanceSession session = createEmptySession();// Initialize the properties of the new session and return itsession.setNew(true);session.setValid(true);session.setCreationTime(System.currentTimeMillis());session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60);String id = sessionId;if (id == null) {id = generateSessionId();}session.setId(id);sessionCounter++;SessionTiming timing = new SessionTiming(session.getCreationTime(), 0);synchronized (sessionCreationTiming) {sessionCreationTiming.add(timing);sessionCreationTiming.poll();}return session;
}
创建完session后,如果Servlet容器配置的SessionTrackingMode 包含*COOKIE 就会创建一个包含session ID的cookie。*
创建cookie时,有三种方式配置cookie的属性:
根据容器上下文来配置,org.apache.catalina.Context
根据应用自定义信息来配置,jakarta.servlet.SessionCookieConfig
使用默认值
SpringBoot自定义Cookie信息
SpringBoot在application.yml配置文件里可以配置cookie属性,原理是Spring在启动web servlet时,会调用org.springframework.boot.web.servlet.ServletContextInitializer 来初始化容器上下文。其中SessionConfiguringInitializer 就是用来设置cookie信息,它会将application.yml配置文件里的cookie信息塞进SessionCookieConfig 对象里。
SpringBoot配置cookie:
server:servlet:session:cookie:name: CUSTOM_SESSION
SpringBoot配置SessionCookieConfig :
private void configureSessionCookie(SessionCookieConfig config) {Session.Cookie cookie = this.session.getCookie();PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();map.from(cookie::getName).to(config::setName);map.from(cookie::getDomain).to(config::setDomain);map.from(cookie::getPath).to(config::setPath);map.from(cookie::getComment).to(config::setComment);map.from(cookie::getHttpOnly).to(config::setHttpOnly);map.from(cookie::getSecure).to(config::setSecure);map.from(cookie::getMaxAge).asInt(Duration::getSeconds).to(config::setMaxAge);
}
org.apache.catalina.connector.Request从SessionCookieConfig获取cookie的名字逻辑:
private static String getConfiguredSessionCookieName(Context context) {// 优先级:// 1. 在容器中配置// 2. 在应用者配置// 3. 默认值'JSESSIONID'if (context != null) {String cookieName = context.getSessionCookieName();if (cookieName != null && cookieName.length() > 0) {return cookieName;}SessionCookieConfig scc =context.getServletContext().getSessionCookieConfig();cookieName = scc.getName();if (cookieName != null && cookieName.length() > 0) {return cookieName;}}return null;
}