Servlet容器如何管理Session

session作为会话的标识,Servlet容器会把它自动管理起来,在需要的时候创建Session对象。

何时创建session

当我们调用org.apache.catalina.connector.Request的getSession(true) 和changeSessionId(String newSessionId) 方法时,Servlet容器就会尝试创建新的Session。在创建之前会做一些前置检查:

  1. 是否已经有session

  1. 当前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 instance
    Session session = createEmptySession();

    // Initialize the properties of the new session and return it
    session.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时,有三种方式配置cookie的属性:

  1. 根据容器上下文来配置,org.apache.catalina.Context

  1. 根据应用自定义信息来配置,jakarta.servlet.SessionCookieConfig

  1. 使用默认值

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李昂的数字之旅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值