首页 > 代码库 > how tomcat works 读书笔记九 Session管理

how tomcat works 读书笔记九 Session管理

在看本文之前,请先查阅相关Session与Cookie的资料。

Catalina通过一个叫管理器的组件来完成 session 管理工作,该组件由org.apache.catalina.Manager interface 接口表示。一个管理器通常跟一个上下文容器相关联,它负责创建、更行以及销毁 session 对象并能给任何请求组件返回一个合法的 session。

Session对象

uml图如下:



看上图,我们知道我们使用的session其实是javax.servlet.http.HttpSession接口的实现对象。
又看到了Facade,门面模式,为什么会有它呢?标准session的一些属性功能需要对外部类隐藏,所以就有了一个facade类,对他做一些包装;有一些方法标准session里有,而标准sessionfacade里就没有,例如org.apache.catalina.Session接口里的方法。
仔细看这两个类,StandardSessionFacade与StandardSession。
我们很清楚StandardSessionFacade里面应该有一个StandardSession的引用。
不过我有点不明白为什么StandardSession里面还有一个StandardSessionFacade的引用?
看了注释大概明白了:
     StandardSession.java
    /**
     * The facade associated with this session.  NOTE:  This value is not
     * included in the serialized version of this object.
     */
    private transient StandardSessionFacade facade = null;
Catalina通过一个叫session管理器的组件来管理建立的Session对象,该组件由org.apache.catalina.Manager接口表示。Session管理器与一个Context级别的容器相关联。


Manager

Session管理器组件负责管理Session对象,例如创建和删除Session对象。在catalina中,ManagerBase是一个工具类,提供了最基本的一些功能。


其中,StandardManager将session保存在内存里,PersistentManagerBase将session持久化到文件或数据库中(在本文中,我们只介绍StandardManager)

应用程序:

先看我们的示例程序:
在Bootstrap里,连接器启动之前加上下面的代码;
    // add a Manager
    Manager manager = new StandardManager();
    context.setManager(manager);
我们的servlet如下:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

public class SessionServlet extends HttpServlet {

    private static final long serialVersionUID = -446310114281616885L;

public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    System.out.println("SessionServlet -- service");
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<html>");
    out.println("<head><title>SessionServlet</title></head>");
    out.println("<body>");
    String value = http://www.mamicode.com/request.getParameter("value");>编译好的servletclass文件放在什么地方,还用我说吗?如果不知道就先看看前面几章吧。

先上最终的结果图:

先输入33然后15最后57的效果图



这是从SessionServlet开始的时序图:


在HttpRequestBase类中的doGetSession()方法中会首先判断requestedSessionId是否为null,如果为null,才会调用manager.createSession()...
现在就有一个问题,那这个requestedSessionId是怎么来的?
其实在本书第三章连接器那里,解析cookid的地方
parseHeaders方法下:
      if (name.equals("cookie")) {
        Cookie cookies[] = RequestUtil.parseCookieHeader(value);
        for (int i = 0; i < cookies.length; i++) {
          if (cookies[i].getName().equals("jsessionid")) {
            // Override anything requested in the URL
            if (!request.isRequestedSessionIdFromCookie()) {
              // Accept only the first session id cookie
              request.setRequestedSessionId(cookies[i].getValue());
              request.setRequestedSessionCookie(true);
              request.setRequestedSessionURL(false);
            }
          }
          request.addCookie(cookies[i]);
        }
      }
第一次请求SessionServlet的时候,自然没有jsessionid,RequestedSessionId也为空,就要manager.createSession()
第二回的时候,浏览器在Cookie里面加入了jsessionid这一项,因此后面
     if (requestedSessionId != null) {
            try {
                session = manager.findSession(requestedSessionId);
            } catch (IOException e) {
                session = null;
            }
            if ((session != null) && !session.isValid())
                session = null;
            if (session != null) {
                return (session.getSession());
            }
        }

how tomcat works 读书笔记九 Session管理