1. 定义
Session在计算机中,尤其是网络应用中,被称为“会话控制
”。
Session对象可以存储用户在程序中的一些数据,用户在系统中不同的web页面之间进行跳转时,存储在Session中的数据不会丢失。
当用户请求来自web页面时,如果该用户还没有会话,web服务器就会创建一个新的Session对象。当会话过期或者被放弃后,服务器将终止该会话。
2. 和Cookie比较
Session和Cookie都可以保存用户数据,但是Session
是保存在服务端
,Cookie
是保存在客户的浏览器
中。
电脑桌面端应用
与APP应用
不保存Cookie。
Session的实现需要依赖于Cookie,当服务端创建Session后,会返回一个JSESSIONID
存到Cookie中,下次再请求时,请求头中携带的Cookie会将JSESSIONID一并带回到服务端,这样服务端就可以找到对应的Session对象。
3. 图解

Session是在servlet
中遇到request.getSession()
时创建的;JSP本质就是一个servlet,将JSP编译后得到的servlet中,就会有request.getSession()
代码,所以访问JSP也会创建Session。
4. 源码解析(Java)
随便在一个接口中加入以下代码:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
springboot
使用内置tomcat
启动时,request对象是org.apache.catalina.connector.RequestFacade
的实例。
首先进入request.getSession()
方法:
@Override
public HttpSession getSession() {
if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}
return getSession(true);
}
进入getSession(true)
方法:
@Override
public HttpSession getSession(boolean create) {
if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}
if (SecurityUtil.isPackageProtectionEnabled()){
return AccessController.
doPrivileged(new GetSessionPrivilegedAction(create));
} else {
return request.getSession(create);
}
}
此处request属于org.apache.catalina.connector.Request
类,进入request.getSession(create)
方法:
@Override
public HttpSession getSession(boolean create) {
Session session = doGetSession(create);
if (session == null) {
return null;
}
return session.getSession();
}
进入doGetSession(create)
方法:
protected Session doGetSession(boolean create) {
Context context = getContext();
if (context == null) {
return null;
}
if ((session != null) && !session.isValid()) {
session = null;
}
if (session != null) {
return session;
}
Manager manager = context.getManager();
if (manager == null) {
return null;
}
if (requestedSessionId != null) {
try {
session = manager.findSession(requestedSessionId);
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("request.session.failed", requestedSessionId, e.getMessage()), e);
} else {
log.info(sm.getString("request.session.failed", requestedSessionId, e.getMessage()));
}
session = null;
}
if ((session != null) && !session.isValid()) {
session = null;
}
if (session != null) {
session.access();
return session;
}
}
if (!create) {
return null;
}
boolean trackModesIncludesCookie =
context.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.COOKIE);
if (trackModesIncludesCookie && response.getResponse().isCommitted()) {
throw new IllegalStateException(sm.getString("coyoteRequest.sessionCreateCommitted"));
}
String sessionId = getRequestedSessionId();
if (requestedSessionSSL) {
} else if (("/".equals(context.getSessionCookiePath())
&& isRequestedSessionIdFromCookie())) {
if (context.getValidateClientProvidedNewSessionId()) {
boolean found = false;
for (Container container : getHost().findChildren()) {
Manager m = ((Context) container).getManager();
if (m != null) {
try {
if (m.findSession(sessionId) != null) {
found = true;
break;
}
} catch (IOException e) {
}
}
}
if (!found) {
sessionId = null;
}
}
} else {
sessionId = null;
}
session = manager.createSession(sessionId);
if (session != null && trackModesIncludesCookie) {
Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie(
context, session.getIdInternal(), isSecure());
response.addSessionCookieInternal(cookie);
}
if (session == null) {
return null;
}
session.access();
return session;
}
判断session是否失效的session.isValid()
方法:
@Override
public boolean isValid() {
if (!this.isValid) {
return false;
}
if (this.expiring) {
return true;
}
if (ACTIVITY_CHECK && accessCount.get() > 0) {
return true;
}
if (maxInactiveInterval > 0) {
int timeIdle = (int) (getIdleTimeInternal() / 1000L);
if (timeIdle >= maxInactiveInterval) {
expire(true);
}
}
return this.isValid;
}
5. 总结
Session是一项会话存储技术,它的实现需要Cookie的配合。服务端根据请求中Cookie携带的JSESSIONID参数寻找对应的Session对象。
第一次请求没有携带JSESSIONID或者JSESSIONID对应的Session对象已经失效或者不存在,则服务端创建新的Session,并将JSESSIONID添加到响应头中,浏览器端接收到响应后,设置Cookie中的JSESSIONID参数。