前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Tomcat】《How Tomcat Works》英文版GPT翻译(第九章)

【Tomcat】《How Tomcat Works》英文版GPT翻译(第九章)

作者头像
阿东
发布2024-01-13 14:03:13
830
发布2024-01-13 14:03:13
举报

Chapter 9: Session Management

Overview(概述)

Catalina supports session management through a component called manager, which is represented by the org.apache.catalina.Manager interface. A manager is always associated with a context. Among others, a manager is responsible for creating, updating, and destroying (invalidating) session objects as well as returning a valid session object to any requesting component.

Catalina 通过一个称为 manager 的组件来支持会话管理,该组件由org.apache.catalina.Manager接口表示。

一个manager总是与一个上下文相关联。

除其他功能外,manager 负责创建、更新和销毁(使无效)会话对象,以及向任何请求组件返回一个有效的会话对象。

A servlet can obtain a session object by calling the getSession method of the javax.servlet.http.HttpServletRequest interface, which is implemented by the org.apache.catalina.connector.HttpRequestBase class in the default connector. Here are some related methods in the HttpRequestBase class.

一个 servlet 可以通过调用javax.servlet.http.HttpServletRequest接口的getSession方法来获取一个session对象,该接口由默认连接器中的org.apache.catalina.connector.HttpRequestBase类实现。

以下是HttpRequestBase类中的一些相关方法。

代码语言:javascript
复制
  
public HttpSession getSession() {  
  return (getSession(true));  
}  
public HttpSession getSession(boolean create) {  
...  
  return doGetSession(create);  
}  
private HttpSession doGetSession(boolean create) {  
  // There cannot be a session if no context has been assigned yet  
  if (context == null)  
   return (null);  
  // Return the current session if it exists and is valid  
  if ((session != null) && !session.isValid())  
   session = null;  
  if (session != null)  
   return (session.getSession());  
  // Return the requested session if it exists and is valid  
  Manager manager = null;  
  if (context != null)  
   manager = context.getManager();  
  if (manager == null)  
   return (null); // Sessions are not supported  
  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());  
   }  
  }  
  // Create a new session if requested and the response is not  
  // committed      if (!create)  
   return (null);  
...  
  session = manager.createSession();  
  if (session != null)  
   return (session.getSession());  
  else          return (null);  
}

By default, a manager stores its session objects in memory. However, Tomcat also allows a manager to persist its session objects into a file store or a database (through JDBC). Catalina provides the org.apache.catalina.session package that contains types related to session objects and session management.

默认情况下,管理器将其 session 对象存储在内存中。

然而,Tomcat 还允许管理器将其 session 对象持久化到文件存储或数据库(通过JDBC)。

Catalina提供了org.apache.catalina.session包,其中包含与 session 对象和session管理相关的类型。

This chapter explains the session management in Catalina in three sections, "Sessions", "Managers", and "Stores". The last section explains the application that uses a context with an associated Manager.

本章将以三个部分解释Catalina中的会话管理,即"会话"、"管理器"和"存储"。

最后一节解释了使用具有关联管理器的上下文的应用程序。

Sessions(会话)

In servlet programming, a session object is represented by the javax.servlet.http.HttpSession interface. The implementation of this interface is the StandardSession class in the org.apache.catalina.session package. However, for security reasons, a manager does not pass a StandardSession instance to a servlet. Instead, it uses a fa?ade class StandardSessionFacade in the org.apache.catalina.session package. Internally, a manager works with another fa?ade: the org.apache.catalina.Session interface. The UML diagram for the session-related types are given in Figure 9.1. Note that for brevity, the org.apache.catalina prefix on Session, StandardSession, and StandardSessionFacade has been omitted.

servlet 编程中,一个会话对象由 javax.servlet.http.HttpSession 接口表示。

这个接口的实现是org.apache.catalina.session包中的StandardSession类。

然而,出于安全原因,管理器不会将StandardSession实例传递给servlet,而是使用org.apache.catalina.session包中的StandardSessionFacade外观类。

在内部,管理器与另一个外观类一起工作:org.apache.catalina.Session接口。

会话相关类型的UML图如图9.1所示。

请注意,为了简洁起见,省略了SessionStandardSessionStandardSessionFacade上的org.apache.catalina前缀。

Figure 9.1: Session-related types

Figure 9.1: Session-related types

图9.1:会话相关类型

The Session Interface(会话接口)

The Session interface acts as a Catalina-internal fa?ade. The standard implementation of the Session interface, StandardSession, also implements the javax.servlet.http.HttpSession interface. The Session interface is given in Listing 9.1.

话接口充当Catalina内部的外观。会话接口的标准实现StandardSession也实现了javax.servlet.http.HttpSession接口。

会话接口如清单9.1所示。

Listing 9.1: The Session interface

清单 9.1:会话接口

代码语言:javascript
复制
package org.apache.catalina;
import java.io.IOException;
import java.security.Principal;
import java.util.Iterator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
public interface Session {
 public static final String SESSION_CREATED_EVENT = "createSession";
 public static final String SESSION_DESTROYED_EVENT =
   "destroySession";
 public String getAuthType();
 public void setAuthType(String authType);
 public long getCreationTime();
 public void setCreationTime(long time);
 public String getId();
 public void setId(String id);
 public String getInfo();
 public long getLastAccessedTime();
 public Manager getManager();
 public void setManager(Manager manager);
 public int getMaxInactiveInterval();
 public void setMaxInactiveInterval(int interval);
 public void setNew(boolean isNew);
 public Principal getPrincipal();
 public void setPrincipal(Principal principal);
 public HttpSession getSession();
 public void setValid(boolean isValid);
 public boolean isValid();
 public void access();
 public void addSessionListener(SessionListener listener);
 public void expire();
 public Object getNote(String name);
 public Iterator getNoteNames();
 public void recycle();
 public void removeNote(String name);
 public void removeSessionListener(SessionListener listener);
 public void setNote(String name, Object value);
}

A Session object is always contained in a manager, and the setManager and getManager methods are used for associating a Session instance with a manager. A Session instance also has a unique identifier throughout the context associated with its manager. Session identifiers are accessed through the setId and getId methods. The getLastAccessedTime method is invoked by the manager to determine a Session object's validity. The manager calls the setValid method to set or reset a session's validity. Every time a Session instance is accessed, its access method is called to update its last accessed time. Finally, the manager can expire a session by calling its expire method and the getSession method returns an HttpSession object wrapped by this fa?ade.

一个 Session 对象总是包含在一个管理器中,使用 setManager 和 getManager 方法将Session实例与管理器关联。

Session实例在与其管理器相关联的上下文中具有唯一的标识符。

通过 setIdgetId 方法可以访问 Session 标识符。

getManager 调用 getLastAccessedTime 方法来确定 Session 对象的有效性。

管理器调用 setValid 方法来设置或重置会话的有效性。

每次访问 Session 实例时,都会调用其访问方法来更新其最后访问时间。

最后,管理器可以通过调用其 expire 方法来使会话过期,而 getSession 方法返回一个由此外观包装的 HttpSession 对象。

The StandardSession Class(标准会话类)

The StandardSession class is the standard implementation of the Session interface. In addition to implementing javax.servlet.http.HttpSession and org.apache.catalina.Session, StandardSession implements java.lang.Serializable to make Session objects serializable.

StandardSession 类是 Session 接口的标准实现。

除了实现javax.servlet.http.HttpSessionorg.apache.catalina.Session之外,StandardSession 还实现了java.lang.Serializable,使得Session对象可序列化。

The constructor of this class accepts a Manager instance, forcing a Session object to always have a Manager.

该类的构造函数接受一个 Manager 实例,强制使Session对象始终具有一个 Manager

代码语言:javascript
复制
public StandardSession(Manager manager);

The following are some important private variables for maintaining states. Note that the transient keyword makes a variable non-serializable.

下面是一些用于维护状态的重要私有变量。

请注意,transient 关键字会使变量不可序列化。

代码语言:javascript
复制
// session attributes
private HashMap attributes = new HashMap();
// the authentication type used to authenticate our cached Principal,
if any
private transient String authType = null;
private long creationTime = 0L;
private transient boolean expiring = false;
private transient StandardSessionFacade facade = null;
private String id = null;
private long lastAccessedTime = creationTime;
// The session event listeners for this Session.
private transient ArrayList listeners = new ArrayList();
private Manager manager = null;
private int maxInactiveInterval = -1;
// Flag indicating whether this session is new or not.
private boolean isNew = false;
private boolean isValid = false;
private long thisAccessedTime = creationTime;

Note In Tomcat 5 the above variables are protected, in Tomcat 4 they are private. Each of these variables has an accessor and a mutator (the get/set methods). 注意 在 Tomcat 5 中,上述变量是受保护的,而在 Tomcat 4 中,它们是私有的。每个变量都有一个访问器和一个突变器(get/set 方法)。

The getSession method creates a StandardSessionFacade object by passing this instance:

getSession 方法通过传递此实例来创建 StandardSessionFacade 对象:

代码语言:javascript
复制
public HttpSession getSession() {
 if (facade == null)
 facade = new StandardSessionFacade(this);
 return (facade);
}

A Session object that has not been accessed for a period of time exceeding the value of the maxInactiveInterval variable in the Manager will be made expired. Expiring a Session object is achieved by calling the expire method of the Session interface. The implementation of this method in StandardSession in Tomcat 4 is given in Listing 9.2.

会话对象在超过管理器中如果没有在 maxInactiveInterval 变量值的时间内被访问,会话对象将被视为过期。

会话对象的过期可通过调用会话接口的 expire 方法来实现。

Tomcat 4StandardSession 中该方法的实现见清单 9.2。

Listing 9.2: The expire method

清单 9.2:过期方法

代码语言:javascript
复制
  
public void expire(boolean notify) {  
    // Mark this session as "being expired" if needed  
    if (expiring)  
        return;  
    expiring = true;  
    setValid(false);  
    // Remove this session from our manager's active sessions  
    if (manager != null)  
        manager.remove(this);  
    // Unbind any objects associated with this session  
    String keys [] = keys();  
    for (int i = 0; i < keys.length; i++)  
        removeAttribute(keys[i], notify);  
    // Notify interested session event listeners  
    if (notify) {  
        fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);  
    }  
    // Notify interested application event listeners  
    // FIXME - Assumes we call listeners in reverse order  
    Context context = (Context) manager.getContainer();  
    Object listeners[] = context.getApplicationListeners();  
    if (notify && (listeners != null)) {  
        HttpSessionEvent event = new HttpSessionEvent(getSession());  
        for (int i = 0; i < listeners.length; i++) {  
            int j = (listeners.length - 1) - i;  
            if (!(listeners[j] instanceof HttpSessionListener))  
                continue;  
            HttpSessionListener listener =  
                    (HttpSessionListener) listeners[j];  
            try {  
                fireContainerEvent(context, "beforeSessionDestroyed",  
                        listener);  
                listener.sessionDestroyed(event);  
                fireContainerEvent(context, "afterSessionDestroyed", listener);  
            }  
            catch (Throwable t) {  
                try {  
                    fireContainerEvent(context, "afterSessionDestroyed",  
                            listener);  
                }  
                catch (Exception e) {  
                    ;  
                }  
                // FIXME - should we do anything besides log these?  
                log(sm.getString("standardSession.sessionEvent"), t);  
            }  
        }  
    }  
    // We have completed expire of this session  
    expiring = false;  
    if ((manager != null) && (manager instanceof ManagerBase)) {  
        recycle();  
    }  
}

The expiring process as shown in Listing 9.2 includes the setting of an internal variable called expiring, removing the Session instance from Manager, and firing of a few events.

如图9.2所示,列表9.2中的过期过程包括设置一个名为 expiring 的内部变量、从 Manager 中移除 Session 实例以及触发一些事件。

The StandardSessionFacade Class(标准会话面板类)

To pass a Session object to a servlet, Catalina could instantiate the StandardSession class, populate it, and then pass it to the servlet. However, instead, it passes it to an instance of StandardSessionFacade that provides only implementation of the methods in javax.servlet.http.HttpSession. This way, the servlet programmers cannot downcast the HttpSession object back to StandardSessionFacade and access its public methods that are not supposed to be available to the programmer.

为了将 Session 对象传递给 servletCatalina 可以实例化 StandardSession 类,填充它,然后将其传递给 servlet

然而,它将其传递给 StandardSessionFacade 的一个实例,该实例仅提供 javax.servlet.http.HttpSession 中方法的实现。

这样,servlet 程序员无法将 HttpSession 对象向下转型为 StandardSessionFacade 并访问其不应该对程序员可用的公共方法。

Manager(管理器)

A manager manages session objects. For example, it creates session objects and invalidates them. A manager is represented by the org.apache.catalina.Manager interface. In Catalina, the org.apache.catalina.session package contains the ManagerBase class that provides implementation of common functionality. ManagerBase has two direct subclasses: StandardManager and PersistentManagerBase.

管理器用于管理会话对象。

例如,它创建会话对象并使其无效。

管理器由 org.apache.catalina.Manager 接口表示。

Catalina 中,org.apache.catalina.session包包含提供常见功能实现的 ManagerBase 类。

ManagerBase 有两个直接子类:StandardManagerPersistentManagerBase

When running, StandardManager stores session objects in memory. However, when stopped, it saves all the session objects currently in memory to a file. When it is started again, it loads back these session objects.

在运行时,StandardManager 将会话对象存储在内存中。

然而,在停止时,它将当前在内存中的所有会话对象保存到文件中。

当再次启动时,它会加载这些会话对象。

PersistentManagerBase is a base class for manager components that store session objects in secondary storage. It has two sub-classes: PersistentManager and DistributedManager (DistributedManager is only available in Tomcat 4). The UML diagram of the Manager interface and its implementation classes is given in Figure 9.2.

PersistentManagerBase 是存储会话对象在辅助存储中的管理器组件的基类。

它有两个子类:PersistentManagerDistributedManagerDistributedManager 仅在Tomcat 4中可用)。

Manager 接口及其实现类的UML图如图9.2所示。

Figure 9.2: The Manager interface and its implementations

Figure 9.2: The Manager interface and its implementations

图 9.2:管理器接口及其实现

The Manager Interface(管理器界面)

The Manager interface represents a Manager component. It is given in Listing 9.3.

管理器接口表示一个管理器组件。

它在清单 9.3 中给出。

Listing 9.3: The Manager interface

清单 9.3:管理器接口

代码语言:javascript
复制
package org.apache.catalina;  
import java.beans.PropertyChangeListener;  
import java.io.IOException;  
public interface Manager {  
 public Container getContainer();  
 public void setContainer(Container container);  
 public DefaultContext getDefaultContext();  
 public void setDefaultContext(DefaultContext defaultContext);  
 public boolean getDistributable();  
 public void setDistributable(boolean distributable);  
 public String getInfo();  
 public int getMaxInactiveInterval();  
 public void setMaxInactiveInterval(int interval);  
 public void add(Session session);  
 public void addPropertyChangeListener(PropertyChangeListener  
              listener);  
 public Session createSession();  
 public Session findSession(String id) throws IOException;  
 public Session[] findSessions();  
 public void load() throws ClassNotFoundException, IOException;  
 public void remove(Session session);  
 public void removePropertyChangeListener(PropertyChangeListener  
              listener);  
 public void unload() throws IOException;  
}

First of all, the Manager interface has the getContainer and setContainer methods to associate a Manager implementation with a context. The createSession method creates a Session object. The add method adds a Session instance to the session pool and the remove method removes the Session object from the pool. The getMaxInactiveInterval and the setMaxInactiveInterval methods return and specifies the number of seconds the Manager will wait for the user associated with a session to come back before destroying the session.

首先,管理器接口有 getContainersetContainer 方法,用于将管理器实现与上下文关联起来。

createSession 方法创建会话对象。

add 方法会将会话实例添加到会话池中,remove 方法会将会话对象从池中移除。

getMaxInactiveIntervalsetMaxInactiveInterval 方法返回并指定管理器在销毁会话前等待会话关联用户返回的秒数。

Finally, the load and unload methods are there to support persisting sessions to a secondary storage in a Manager implementation that supports a kind of persistence mechanism. The unload method saves currently active sessions to a store specified by the Manager implementation, and the load method brings back the sessions persisted to the memory.

最后,在支持某种持久化机制的管理器实现中,加载和卸载方法用于支持将会话持久化到二级存储中。

卸载方法会将当前活动会话保存到管理器实现指定的存储空间中,而加载方法则会将持久化到内存中的会话带回来。

The ManagerBase Class(管理器基类)

The ManagerBase class is an abstract class from which all Manager classes derive. This class provides common functionality for its child classes. Among others, ManagerBase has the createSession method for creating a Session object. Each session has a unique identifier, and the ManagerBase class's protected method generateSessionId returns a unique identifier.

ManagerBase 类是一个抽象类,所有 Manager 类都是从它派生出来的。该类为其子类提供通用功能。

其中,ManagerBase 具有 createSession 方法,用于创建会话对象。

每个会话都有一个唯一标识符,ManagerBase 类的受保护方法 generateSessionId 会返回一个唯一标识符。

Note An active session is a session object that is still valid (has not expired) 注意 活动会话是指仍然有效(未过期)的会话对象

The instance of Manager for a given context manages all active sessions in the context. These active sessions are stored in a HashMap called sessions:

给定上下文的 Manager 实例管理该上下文中的所有活动会话。

这些活动会话存储在名为 sessionsHashMap 中:

代码语言:javascript
复制
protected HashMap sessions = new HashMap();

The add method adds a Session object to the sessions HashMap. This method is given below.

add 方法将一个会话对象添加到会话 HashMap 中。

该方法如下所示。

代码语言:javascript
复制
public void add(Session session) {  
    synchronized (sessions) {  
        sessions.put(session.getId(), session);  
    }  
}

The remove method removes a Session from the sessions HashMap. Here is the remove method.

remove 方法会从 sessions HashMap 中移除一个 Session。下面是 remove 方法。

代码语言:javascript
复制
public void remove(Session session) {  
    synchronized (sessions) {  
        sessions.remove(session.getId());  
    }  
}

The no-argument findSession method returns all active sessions from the sessions HashMap as an array of Session instances. The findSession method that accepts a session identifier as an argument returns the Session instance with that identifier. These method overloads are given below.

无参数 findSession 方法以会话实例数组的形式返回会话 HashMap 中的所有活动会话。

findSession 方法接受会话标识符作为参数,返回具有该标识符的会话实例。

下面给出了这些方法的重载。

代码语言:javascript
复制
public Session[] findSessions() {  
    Session results[] = null;  
    synchronized (sessions) {  
        results = new Session[sessions.size()];  
        results = (Session[]) sessions.values().toArray(results);  
    }  
    return (results);  
}  
public Session findSession(String id) throws IOException {  
    if (id == null)  
        return (null);  
    synchronized (sessions) {  
        Session session = (Session) sessions.get(id);  
        return (session);  
    }  
}

StandardManager

The StandardManager class is the standard implementation of Manager and stores session objects in memory. It implements the Lifecycle interface (See Chapter 6, "Lifecycles") so that it can be started and stopped. The implementation of the stop method calls the unload method that serializes valid Session instances to a file called SESSIONS.ser for each context. The SESSIONS.ser file can be found under the work directory under CATALINA_HOME. For example, in Tomcat 4 and 5, if you have run the examples application, you can find a SESSIONS.ser file under CATALINA_HOME/work/Standalone/localhost/examples. When StandardManager is started again, these Session objects are read back to memory by calling the load method.

StandardManager 类是 Manager 的标准实现,它将会话对象存储在内存中。

它实现了 Lifecycle 接口(见第 6 章“生命周期”),因此可以启动和停止。

停止方法的实现调用 unload 方法,将有效的 Session 实例序列化到名为 SESSIONS.ser 的文件中,每个上下文一个文件。

SESSIONS.ser 文件可以在 CATALINA_HOME 的 work 目录下找到

例如,在 Tomcat 4 和 5 中,如果您运行了示例应用程序,可以在 CATALINA_HOME/work/Standalone/localhost/examples 下找到一个 SESSIONS.ser 文件。

StandardManager 再次启动时,通过调用 load 方法,这些 Session 对象将被读回到内存中。

A manager is also responsible for destroying session objects that are no longer valid. In StandardManager in Tomcat 4, this is achieved by employing a dedicated thread. For this reason, StandardManager implements java.lang.Runnable. Listing 9.4 presents the run method of the StandardManager class in Tomcat 4

Manager 也负责销毁不再有效的会话对象。

在 Tomcat 4 的 StandardManager 中,这是通过使用专用线程来实现的。

因此,StandardManager 实现了 java.lang.Runnable。清单 9.4 展示了 Tomcat 4 中 StandardManager 类的 run 方法。

Listing 9.4: The run method of StandardManager in Tomcat 4

清单 9.4: Tomcat 4 中 StandardManager 的运行方法

代码语言:javascript
复制
public void run() {
 // Loop until the termination semaphore is set
 while (!threadDone) {
 threadSleep();
 processExpires();
 }
}

The threadSleep method puts the thread to sleep for the number of seconds specified by the checkInterval variable, which by default has a value of 60. You can change this value by calling the setCheckInterval method.

threadSleep 方法会将线程休眠指定的秒数,该秒数由 checkInterval 变量指定,默认值为 60。您可以通过调用 setCheckInterval 方法来更改该值。

The processExpire method loops through all Session objects managed by StandardManager and compares each Session instance's lastAccessedTime with the current time. If the difference between the two exceeds maxInactiveInterval, the method calls the Session interface's expire method to expire the Session instance. The value of maxInactiveInternal can be changed by calling the setMaxInactiveInterval method. The default value of maxInactiveInterval variable in StandardManager is 60. Don't be fooled into thinking that this is the value used in a Tomcat deployment, though. The setContainer method, which is called by the setManager method in the org.apache.catalina.core.ContainerBase class (you always call setManager to associate a manager with a context), overwrites this value. Here is the piece of code in the setContainer method:

processExpire 方法会循环遍历 StandardManager 管理的所有 Session 对象,并将每个 Session 实例的 lastAccessedTime 与当前时间进行比较。

如果两者之间的差值超过 maxInactiveInterval,该方法将调用 Session 接口的 expire 方法来使 Session 实例过期。

可以通过调用 setMaxInactiveInterval 方法来更改 maxInactiveInterval 的值。

StandardManager 中,maxInactiveInterval 变量的默认值为 60

但请不要被误导以为这是Tomcat部署中使用的值。

实际上,org.apache.catalina.core.ContainerBase类中的 setContainer 方法会覆盖这个值。以下是 setContainer 方法中的代码片段:

代码语言:javascript
复制
setMaxInactiveInterval(((Context)
this.container).getSessionTimeout()*60 );

Note The default value of the sessionTimeOut variable in the org.apache.catalina.core.StandardContext class is 30. 注意 org.apache.catalina.core.StandardContext 类中 sessionTimeOut 变量的默认值是 30。

In Tomcat 5, the StandardManager class does not implement java.lang.Runnable. The processExpires method in a StandardManager object in Tomcat 5 is directly called by the backgroundprocess method, which is not available in Tomcat 4.

在 Tomcat 5 中,StandardManager 类没有实现 java.lang.Runnable

在 Tomcat 5 中,StandardManager 对象中的 processExpires 方法是由 backgroundprocess 方法直接调用的,而在 Tomcat 4 中则不可用。

代码语言:javascript
复制
public void backgroundProcess() {
 processExpires();
}

The backgroundProcess method in StandardManager is invoked by the backgroundProcess method of the org.apache.catalina.core.StandardContext instance, the container associated with this manager. StandardContext invokes its backgroundProcess method periodically and will be discussed in Chapter 12

StandardManager 中的 backgroundProcess 方法由与该管理器关联的容器org.apache.catalina.core.StandardContext 实例的 backgroundProcess 方法调用。

StandardContext 会定期调用其 backgroundProcess 方法,这将在第 12 章中讨论。

PersistentManagerBase

The PersistentManagerBase class is the parent class of all persistent managers. The main difference between a StandardManager and a persistent manager is the presence of a store in the latter. A store represents a secondary storage for the managed session objects. The PersistentManagerBase class uses a private object reference called store.

PersistentManagerBase 类是所有持久化管理器的父类。

StandardManager 与持久化管理器的主要区别在于后者有一个存储空间。

存储空间代表被管理会话对象的二级存储空间。

PersistentManagerBase 类使用名为 store 的私有对象引用。

代码语言:javascript
复制
private Store store = null;

In a persistent manager, session objects can be backed up as well as swapped out. When a session object is backed up, the session object is copied into a store and the original stays in memory. Therefore, if the server crashes, the active session objects can be retrieved from the store. When a session object is swapped out, it is moved to the store because the number of active session objects exceeds a specified number or the session object has been idle for too long. The purpose of swapping out is to save memory.

在持久化管理器中,会话对象可以被备份和交换出去。

当一个会话对象被备份时,该会话对象被复制到存储中,而原始对象仍然留在内存中。

因此,如果服务器崩溃,活动会话对象可以从存储中检索出来。

当一个会话对象被交换出去时,它被移动到存储中,因为活动会话对象的数量超过了指定的数量,或者会话对象已经闲置了太长时间。

交换出的目的是为了节省内存。

In Tomcat 4 PersistentManagerBase implements java.lang.Runnable to employ a separate thread that routinely backs up and swaps out active sessions. Here is its run method implementation:

Tomcat 4中,PersistentManagerBase 实现了java.lang.Runnable,以利用一个单独的线程定期备份和交换出活动会话。以下是其 run 方法的实现:

代码语言:javascript
复制
public void run() {  
    // Loop until the termination semaphore is set  
    while (!threadDone) {  
        threadSleep();  
        processExpires();  
        processPersistenceChecks();  
    }  
}

The processExpired method, just like in StandardManager, checks for expiring session objects. The processPersistenceChecks method calls three other methods:

processExpired 方法与 StandardManager 中的一样,用于检查过期的会话对象。

processPersistenceChecks 方法会调用其他三个方法:

代码语言:javascript
复制
public void processPersistenceChecks() {
 processMaxIdleSwaps();
 processMaxActiveSwaps();
 processMaxIdleBackups();
}

In Tomcat 5 PersistentManagerBase does not implement java.lang.Runnable. Backing up and swapping out is done by its backgroundProcess manager, which is periodically invoked by the associated StandardContext instance.

在 Tomcat 5 中,PersistentManagerBase 没有实现 java.lang.Runnable

备份和换出由其后台进程管理器(backgroundProcess manager)完成,该进程由相关的 StandardContext 实例定期调用。

Swap out and back up are discussed in the following sub-sections.

交换和备份将在下面的小节中讨论。

Swap Out(交换)

The PersistentManagerBase class applies a number of rules in swapping out session objects. A session object is swapped out either because the number of active sessions has exceeded the value of maxActiveSessions variable or because the session has been idle for too long.

PersistentManagerBase 类在交换会话对象时应用了一些规则。

会话对象之所以被交换出,要么是因为活动会话的数量超过了 maxActiveSessions 变量的值,要么是因为会话已经闲置了太长时间。

In the case where there are too many session objects, a PersistentManagerBase instance simply swaps out any session objects until the number of active session objects is equal to maxActiveSessions. (See the processMaxActiveSwaps method)

在会话对象过多的情况下,PersistentManagerBase 实例会简单地交换出任何会话对象,直到活动会话对象的数量等于 maxActiveSessions 。(参见 processMaxActiveSwaps 方法)

In the case where a session object has been idle for too long, the PersistentManagerBase class uses two variables to determine whether or not a session object should be swapped out: minIdleSwap and maxIdleSwap. A session object will be swapped out if its lastAccessedTime is exceeds both minIdleSwap and maxIdleSwap. To prevent any swapping out, you can set the maxIdleSwap to a negative number. (See the processMaxIdleSwaps method)

在会话对象闲置时间过长的情况下,PersistentManagerBase 类使用两个变量来确定是否应该交换出会话对象:minIdleSwapmaxIdleSwap

如果会话对象的 lastAccessedTime 超过了 minIdleSwapmaxIdleSwap 的值,会话对象将被交换出。

如果要防止任何交换出,可以将 maxIdleSwap 设置为负数。

(参见 processMaxIdleSwaps 方法)

Because an active session can be swapped out, it can either reside in memory or in a store. Therefore, the findSession (String id) method first looks for the Session instance in the memory and, if none is found, in the store. Here is the method implementation in the PersistentManagerBase class.

由于活动会话可以被交换出,它可以驻留在内存中或者存储中。

因此,findSessionString id)方法首先在内存中查找 Session 实例,如果找不到,则在存储中查找。

下面是 PersistentManagerBase 类中该方法的实现。

代码语言:javascript
复制
public Session findSession(String id) throws IOException {  
    Session session = super.findSession(id);  
    if (session != null)  
        return (session);  
    // not found in memory, see if the Session is in the Store  
    session = swapIn(id); // swapIn returns an active session in the  
    // Store    return (session);  
}

Back-up(备份)

Not all active session objects are backed up. A PersistentManagerBase instance only backs up session objects that have been idle longer than the value of maxIdleBackup. The processMaxIdleBackups method performs the session object back-up.

并非所有活动的会话对象都会被备份。

PersistentManagerBase 实例只会备份那些闲置时间超过 maxIdleBackup 值的会话对象。

processMaxIdleBackups 方法用于执行会话对象的备份。

PersistentManager(持久化管理器)

The PersistentManager class extends PersistentManagerBase. There is not much addition here, except two properties. The PersistentManager class is given in Listing 9.5.

PersistentManager 类继承自 PersistentManagerBase

除了两个属性外,这里没有太多的添加。 PersistentManager 类的代码如下所示:

Listing 9.5: The PersistentManager class

代码清单9.5:PersistentManager

代码语言:javascript
复制
package org.apache.catalina.session;
public final class PersistentManager extends PersistentManagerBase {
 // The descriptive information about this implementation.
 private static final String info = "PersistentManager/1.0";
 // The descriptive name of this Manager implementation (for logging).
 protected static String name = "PersistentManager";
 public String getInfo() {
  return (this.info);
 }
 public String getName() {
  return (name);
 }
}

DistributedManager(分布式管理器)

Tomcat 4 provides the DistrubutedManager class. A subclass of PersistentManagerBase, DistributedManager is used in a clustered environment with two or more nodes. A node represents a Tomcat deployment. Nodes in a cluster can exist in different machines or the same machine. In a clustered environment, each node must use an instance of DistributedManager as its Manager to support session replication, which is the main responsibility of DistributedManager.

Tomcat 4提供了 DistributedManager 类。DistributedManagerPersistentManagerBase 的子类,用于在具有两个或多个节点的集群环境中使用。

一个节点代表一个Tomcat部署。集群中的节点可以存在于不同的机器或同一台机器上。

在集群环境中,每个节点必须使用 DistributedManager 的一个实例作为其 Manager 来支持会话复制,这是 DistributedManager 的主要职责。

For the replication purpose, DistributedManager sends notification to other nodes whenever a session object is created or destroyed. In addition, a node must be able to receive notification from other nodes as well. This way, an HTTP request can be served by any node in the cluster.

为了复制目的,每当会话对象被创建或销毁时,DistributedManager 会向其他节点发送通知。

此外,一个节点必须能够接收来自其他节点的通知。

这样,一个HTTP请求可以由集群中的任何节点来提供服务。

For sending and receiving notification to and from other instances of DistributedManager in other nodes, Catalina provides classes in the org.apache.catalina.cluster package. Among others, the ClusterSender class is used for sending notifications to other nodes and the ClusterReceiver class for receiving notifications from other nodes.

为了与其他节点中的 DistributedManager 实例发送和接收通知,Catalina 提供了 org.apache.catalina.cluster 包中的类。

除其他外,ClusterSender 类用于向其他节点发送通知,ClusterReceiver类用于从其他节点接收通知。

The createSession method of DistrbutedManager must create a session object to be stored in the current instance and use a ClusterSender instance to send notification to other nodes. Listing 9.6 presents the createSession method.

DistributedManagercreateSession 方法必须创建一个会话对象以存储在当前实例中,并使用 ClusterSender 实例向其他节点发送通知。

以下是 createSession 方法的示例代码:

Listing 9.6: The createSession method

示例代码9.6: createSession方法

代码语言:javascript
复制
public Session createSession() {  
    Session session = super.createSession();  
    ObjectOutputStream oos = null;  
    ByteArrayOutputStream bos = null;  
    ByteArraylnputStream bis = null;  
    try {  
        bos = new ByteArrayOutputStream();  
        oos = new ObjectOutputStream(new BufferedOutputStream(bos));  
        ((StandardSession)session).writeObjectData(oos);  
        oos.close();  
        byte[] obs = bos.toByteArray();  
        clusterSender.send(obs);  
        if(debug > 0)  
            log("Replicating Session: "+session.getId());  
    }  
    catch (IOException e) {  
        log("An error occurred when replicating Session: " +  
                session.getId());  
    }  
    retun (session);  
}

First, the createSession method calls the super class's createSession method to create a session object for itself. Then, it sends the session object as an array of bytes using the ClusterSender.

首先,createSession 方法调用其超类的 createSession 方法为自身创建一个会话对象。

然后,它使用 ClusterSender 将会话对象作为字节数组发送出去。

The DistribubedManager class also implements java.lang.Runnable to have a separate thread for expiring session objects and receive notification from other nodes. The run method is as follows.

DistribubedManager 类还实现了 java.lang.Runnable 接口,以便为过期的会话对象和来自其他节点的通知接收单独的线程。

run 方法如下所示。

代码语言:javascript
复制
public void run() {
  // Loop until the termination semaphore is set
  while (!threadDone) {
   threadSleep();
   processClusterReceiver();
   processExpires();
   processPersistenceChecks();
  }
}

What's worth noting in this method is the call to the processClusterReceiver method that processes session create notification from other nodes.

该方法中值得注意的是对 processClusterReceiver 方法的调用,该方法用于处理来自其他节点的会话创建通知。

Stores(存储器)

A store, represented by the org.apache.catalina.Store interface, is a component that provides a permanent storage for sessions managed by a manager. The Store interface is given in Listing 9.7.

存储由 org.apache.catalina.Store 接口表示,是为管理器管理的会话提供永久存储的组件。

清单 9.7 给出了存储接口。

Listing 9.7: The Store interface

清单 9.7:存储接口

代码语言:javascript
复制

package org.apache.catalina;
import java.beans.PropertyChangeListener;
import java.io.IOException;
public interface Store {
 public String getInfo();
 public Manager getManager();
 public void setManager(Manager manager);
 public int getSize() throws IOException;
 public void addPropertyChangeListener(PropertyChangeListener
              listener);
 public String[] keys() throws IOException;
 public Session load(String id)
   throws ClassNotFoundException, IOException;
 public void remove(String id) throws IOException;
 public void clear() throws IOException;
 pubiic void removePropertyChangeListener(PropertyChangeListener
              listener);
 public void save(Session session) throws IOException;
}

The two most important methods in the Store interface are save and load. The save method saves the specified session object to a permanent storage. The load method loads the session object with a given session identifier from the storage. Also, the keys method returns a String array containing all session identifiers.

在Store接口中,最重要的两个方法是 saveload

save 方法将指定的会话对象保存到永久存储中。

load 方法从存储中加载具有给定会话标识符的会话对象。

另外,keys 方法返回一个包含所有会话标识符的字符串数组。

The UML diagram for the Store interface and its implementation classes is given in Figure 9.3. Note that the org.apache.catalina prefix has been omitted from all type names.

Store 接口及其实现类的UML图如图9.3所示。

请注意,所有类型名称中都省略了org.apache.catalina前缀。

Figure 9.3: The Store interface and its implementations

Figure 9.3: The Store interface and its implementations

图 9.3:存储接口及其实现

The following sub-sections discuss the StoreBase, FileStore, and JDBCStore classes.

下面的小节将讨论 StoreBaseFileStoreJDBCStore 类。

StoreBase(存储库)

The StoreBase class is an abstract class that provides common functionality for the two child classes: FileStore and JDBCStore. The StoreBase class does not implement the Store interface's save and load methods because the implementations of these methods depend on the type of storage to persist sessions to.

StoreBase 类是一个抽象类,为两个子类提供通用功能: FileStoreJDBCStore

StoreBase 类没有实现存储接口的保存和加载方法,因为这些方法的实现取决于会话持久化的存储类型。

The StoreBase class in Tomcat 4 employs a separate thread to regularly check for expired session and remove expired sessions from the collection of active sessions. Here is the run method in StoreBase in Tomcat 4.

Tomcat 4 中的 StoreBase 类使用一个单独的线程定期检查过期会话,并从活动会话集合中删除过期会话。

下面是 Tomcat 4 中 StoreBase 的运行方法。

代码语言:javascript
复制
public void run() {
 // Loop until the termination semaphore is set
 while (!threadDone) {
 threadSleep();
 processExpires();
 }
}

The processExpires method retrieves all active sessions and checks the lastAccessedTime value of each session, and removes the session objects that have been inactive for too long. The processExpires method is given in Listing 9.7

processExpires 方法检索所有活动会话,并检查每个会话的 lastAccessedTime 值,并删除那些长时间不活动的会话对象。

processExpires 方法在清单 9.7 中给出。

Listing 9.7: the processExpires method

清单 9.7:processExpires 方法

代码语言:javascript
复制
  
protected void processExpires() {  
    long timeNow = System.currentTimeMillis();  
    String[] keys = null;  
    if (!started)  
        return;  
    try {  
        keys = keys();  
    }  
    catch (IOException e) {  
        log (e.toString());  
        e.printStackTrace();  
        return;    }  
    for (int i = 0; i < keys.length; i++) {  
        try {  
            StandardSession session = (StandardSession) load(keys[i]);  
            if (!session.isValid())  
                continue;  
            int maxInactiveInterval = session.getMaxInactiveInterval();  
            if (maxInactiveInterval < 0)  
                continue;  
            int timeIdle = // Truncate, do not round up  
                    (int) ((timeNow - session.getLastAccessedTime()) / 1000L);  
            if (timeIdle >= maxInactiveInterval) {  
                if ( ( (PersistentManagerBase) manager).isLoaded( keys[i] )) {  
                    // recycle old backup session  
                    session.recycle();  
                }  
                else {  
                    // expire swapped out session  
                    session.expire();  
                }  
                remove(session.getId());  
            }  
        }  
        catch (IOException e) {  
            log (e.toString());  
            e.printStackTrace();  
        }  
        catch (ClassNotFoundException e) {  
            log (e.toString());  
            e.printStackTrace();  
        }  
    }  
}

In Tomcat 5 there is no special thread for calling the processExpires method. Instead, this method is periodically called by the backgroundProcess method of the associated PersistentManagerBase instance.

Tomcat 5中,没有专门的线程来调用 processExpires 方法。

相反,这个方法是由关联的 PersistentManagerBase 实例的 backgroundProcess 方法定期调用的。

FileStore

The Filestore class stores session objects in a file. The file is named the same as the identifier of the session object plus the extension .session. This file resides in the temporary work directory. You can change the temporary directory by calling the Filestore class's setDirectory

FileStore类将会话对象存储在文件中。文件的名称与会话对象的标识符相同,加上扩展名.session

这个文件位于临时工作目录中。您可以通过调用FileStore类的setDirectory方法来更改临时目录。

The java.io.ObjectOutputStream class is used in the save method to serialize the session objects. Therefore, all objects stored in a Session instance must implement java.lang.Serializable. To deserialize a session object in the load method, the java.io.ObjectInputStream class is used.

在save方法中,使用 java.io.ObjectOutputStream 类来序列化会话对象。

因此,存储在Session实例中的所有对象都必须实现java.lang.Serializable接口。

load 方法中,使用java.io.ObjectInputStream类来反序列化会话对象。

JDBCStore

The JDBCStore class stores session objects in a database and transfers are done through JDBC. As such, to use JDBCStore you need to set the driver name and the connection URL by calling the setDriverName and setConnectionURL respectively.

JDBCStore 类将会话对象存储在数据库中,并通过 JDBC 进行传输。

因此,要使用 JDBCStore,需要分别调用 setDriverNamesetConnectionURL 来设置驱动程序名称和连接 URL。

The Application

The application accompanying this article is similar to the one in Chapter 8. It uses the default connector and has a context as its main container with one wrapper. One difference, however, is that the context in this application has a StandardManager instance to manage session objects. To test this application, you use the third example servlet SessionServlet. This servlet is represented by a wrapper named wrapper1.

本文附带的应用程序与第8章中的应用程序类似。

它使用默认连接器,并将上下文作为主容器,其中包含一个包装器。

然而,与之不同的是,该应用程序中的上下文具有一个StandardManager实例来管理会话对象。

要测试此应用程序,您可以使用第三个示例servlet SessionServlet

此servlet由名为wrapper1的包装器表示。

Note You can find the SessionServlet class under the myApp/WEB-INF/classes directory. 注意 您可以在myApp/WEB-INF/classes目录下找到SessionServlet类。

The application has two packages, ex09.pyrmont.core and ex09.pyrmont.startup, and uses various classes in Catalina. There are four classes in the ex09.pyrmont.core package: SimpleContextConfig, SimplePipeline, SimpleWrapper, and SimpleWrapperValve. The first three classes are simply copies of the same classes in Chapter 8. There are, however, two additional lines of code in the SimpleWrapperValve class. The ex09.pyrmont.startup package has one class: Bootstrap.

该应用程序有两个包,ex09.pyrmont.core和ex09.pyrmont.startup,并使用Catalina中的各种类。ex09.pyrmont.core包中有四个类:SimpleContextConfigSimplePipelineSimpleWrapperSimpleWrapperValve

前三个类只是第8章中相同类的副本。

然而,SimpleWrapperValve 类中有两行额外的代码。

ex09.pyrmont.startup包中有一个类:Bootstrap

The Bootstrap class is explained in the first sub-section of this section and the SimpleWrapperValve class in the second sub-section. The last subsection discusses how to run the application.

Bootstrap 类在本节的第一个小节中进行了解释,SimpleWrapperValve 类在第二个小节中进行了解释。

最后一个小节讨论了如何运行该应用程序。

The Bootstrap Class

The Bootstrap class starts the application and it is very similar to the Bootstrap class in Chapter 8. However, the Bootstrap class in this chapter creates an instance of the org.apache.catalina.session.StandardManager class and associate it with the Context.

引导类启动应用程序,与第8章中的引导类非常相似。

然而,本章中的引导类创建了一个 org.apache.catalina.session.StandardManager 类的实例,并将其与上下文关联起来。

The main method starts by setting the catalina.base system property and instantiating the default connector

主方法首先设置 catalina.base 系统属性,然后实例化默认连接器。

代码语言:javascript
复制
System.setProperty("catalina.base",
 System.getProperty("user.dir"));
 Connector connector = new HttpConnector();

For the SessionServlet, it creates a wrapper called wrapper1

对于 SessionServlet,它会创建一个名为 wrapper1 的封装器

代码语言:javascript
复制
Wrapper wrapper1 = new SimpleWrapper();
 wrapper1.setName("Session");
 wrapper1.setServletclass("SessionServlet");

Then, it creates a StandardContext object, sets its path and docBase properties, and adds the wrapper to the context.

然后,它会创建一个 StandardContext 对象,设置其路径和 docBase 属性,并将包装器添加到上下文中。

代码语言:javascript
复制
Context context = new StandardContext();
 context.setPath("/myApp");
 context.setDocBase("myApp");
 context.addChild(wrapper1);

Next, the start method continues by adding a servlet mapping. The mapping is different from the ones in the application in Chapter 8. Instead of /Session, we use /myApp/Session as the pattern. This is required because we set the path name of the context to /myApp. The path name will be used to send the session cookie, and the browser will only send the cookie back to the server if the path is also /myApp.

接下来,start 方法继续添加一个 servlet 映射。

这个映射与第8章中的应用程序中的映射不同。

我们使用/myApp/Session作为模式,而不是/Session。 这是必需的,因为我们将上下文的路径名称设置为/myApp

路径名称将用于发送会话 cookie,只有当路径也为/myApp时,浏览器才会将cookie发送回服务器。

代码语言:javascript
复制
context.addServletMapping("/myApp/Session", "Session");

The URL used to request SessionServlet is as follows.

用于请求 SessionServlet 的 URL 如下。

http://localhost:8080/myApp/Session.

Just like in Chapter 8, we need a listener and a loader for the context.

与第 8 章中一样,我们需要为上下文设置一个监听器和一个加载器。

代码语言:javascript
复制
LifecycleListener listener = new SimpleContextConfig();
 ((Lifecycle) context).addLifecycleListener(listener);
 // here is our loader
 Loader loader = new WebappLoader();
 // associate the loader with the Context
 context.setLoader(loader);
 connector.setContainer (context);

Now, new to this application is a manager. We use an instance of StandardManager and pass it to the context.

现在,管理器是本应用程序的新成员。我们使用 StandardManager 的一个实例,并将其传递给上下文。

代码语言:javascript
复制
Manager manager = new StandardManager();
 context.setManager(manager);

Finally, we initialize and start the connector and start the context.

最后,我们初始化和启动连接器,并启动上下文。

代码语言:javascript
复制
connector.initialize();
 ((Lifecycle) connector).start();
 ((Lifecycle) context).start();

The SimpleWrapperValve Class

Recall that at the beginning of this chapter, we mentioned that the servlet can get a session object by calling the getSession method of the javax.servlet.http.HttpServletRequest interface. When the getSession method is invoked, the request object must somehow call the manager associated with the context. The manager either creates a new session object or returns the existing one. For the request object to be able to access the manager, it must have access to the context. To achieve this, in the invoke method of the SimpleWrapperValve class, you call the setContext method of the org.apache.catalina.Request interface, passing the Context. Remember that the SimpleWrapperValve class's invoke method calls the requested servlet's service method. Therefore, you must set the Context before the servlet's service method is called. The invoke method of the SimpleWrapperValve class is given in Listing 9.8. The highlighted lines are the addition to this class.

回想一下,在本章的开头,我们提到servlet可以通过调用javax.servlet.http.HttpServletRequest接口的 getSession 方法来获取一个会话对象。

当调用 getSession 方法时,请求对象必须以某种方式调用与上下文相关联的管理器。

管理器要么创建一个新的会话对象,要么返回现有的会话对象。

为了使请求对象能够访问管理器,它必须能够访问上下文。

为了实现这一点,在 SimpleWrapperValve 类的 invoke 方法中,您需要调用 org.apache.catalina.Request 接口的setContext方法,将上下文传递给它。

请记住,SimpleWrapperValve 类的 invoke 方法调用了所请求的 servletservice 方法。

因此,在调用 servletservice 方法之前,您必须设置上下文。

SimpleWrapperValve 类的 invoke 方法如9.8节所示。

这些突出显示的行是对该类的添加内容。

Listing 9.8: The invoke method of the SimpleWrapperValve class

清单 9.8:SimpleWrapperValve 类的 invoke 方法

代码语言:javascript
复制
 public void invoke(Request request, Response response,
                       ValveContext valveContext) throws IOException, ServletException {
        SimpleWrapper wrapper = (SimpleWrapper) getContainer();
        ServletRequest sreq = request.getRequest();
        ServletResponse sres = response.getResponse();
        Servlet servlet = null;
        HttpServletRequest hreq = null;
        if (sreq instanceof HttpServletRequest)
            hreq = (HttpServletRequest) sreq;
        HttpServletResponse hres = null;
        if (sres instanceof HttpServletResponse)
            hres = (HttpServletResponse) sres;
        // pass the Context to the Request object so that
        // the Request object can call the Manager
        Context context = (context) wrapper.getparent();
        request.setcontext(context);
        // Allocate a servlet instance to process this request
        try {
            servlet = wrapper.allocate();
            if (hres!=null && hreq!=null) {
                servlet.service(hreq, hres);
            }
            else {
                servlet.service(sreq, sres);
            }
        }
        catch (ServletException e) {
        }
    }

You have access to the wrapper, therefore you can obtain the context by calling the getParent method of the Container interface. Note that the wrapper was added to a context. Once you have the context, you can then call the setContext method of the Request interface.

你可以通过调用 Container 接口的 getParent 方法,获得对包装器的访问权限,从而获取上下文。

注意,包装器已添加到上下文中。

一旦获取到上下文,你可以调用 Request 接口的 setContext 方法。

As explained at the beginning of the chapter, the private doGetSession method in the org.apache.catalina.connector.HttpRequestBase class can then call the getManager method of the Context interface to obtain the manager.

正如在本章开头解释的那样,org.apache.catalina.connector.HttpRequestBase类中的私有方法 doGetSession 可以调用 Context 接口的 getManager 方法来获取管理器。

代码语言:javascript
复制
// Return the requested session if it exists and is valid
 Manager manager = null;
 if (context != null)
 manager = context.getManager();

Once you have the manager, obtaining a session object or creating a new one is straightforward.

有了管理器后,获取会话对象或创建新的会话对象就很简单了。

Running the Application

To run the application in Windows, from the working directory, type the following:

要在 Windows 中运行应用程序,请在工作目录中键入以下内容:

代码语言:javascript
复制
java -classpath ./lib/servlet.jar;./lib/commons-collections.jar;./
ex09.pyrmont.startup.Bootstrap

In Linux, you use a colon to separate between libraries.

在 Linux 中,库与库之间用冒号分隔。

代码语言:javascript
复制
java -classpath ./lib/servlet.jar:./lib/commons-collection.jar:./
ex09.pymont.startup.Bootstap

To invoke the SessionServlet servlet, you use the following URL in your browser.

要调用 SessionServlet 服务程序,可在浏览器中使用以下 URL。

http://localhost:8080/myApp/Session

SessionServlet uses a session object to store a value. This servlet displays the previous value and the current value in the Session object, It also displays a form that the user can use to enter a new value, Figure 9.4 displays the output from SessionServlet when it is first invoked.

SessionServlet 使用会话对象来存储一个数值。

Servlet 显示了会话对象中的先前数值和当前数值。

它还显示了一个表单,用户可以用来输入新数值。图9.4显示了当首次调用 SessionServlet 时的输出。

Figure 9.4: The output from SessionServlet

Figure 9.4: The output from SessionServlet

图 9.4: SessionServlet 的输出

Summary

This chapter discussed the manager, the component that manages sessions in the session management. It explained the types of managers and how a manager can persist session objects into a store. At the end of the chapter, you have learned how to build an application that uses a StandardManager instance to run a servlet that uses session objects to store values.

本章讨论了会话管理中管理会话的组件--管理器。

它解释了管理器的类型以及管理器如何将会话对象持久化到存储中。

在本章结束时,你已学会如何构建一个应用程序,使用 StandardManager 实例运行一个使用会话对象存储值的 servlet

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-01-12,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 懒时小窝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Chapter 9: Session Management
  • Overview(概述)
  • Sessions(会话)
    • The Session Interface(会话接口)
      • The StandardSession Class(标准会话类)
        • The StandardSessionFacade Class(标准会话面板类)
        • Manager(管理器)
          • The Manager Interface(管理器界面)
            • The ManagerBase Class(管理器基类)
              • StandardManager
                • PersistentManagerBase
                  • Swap Out(交换)
                  • Back-up(备份)
              • PersistentManager(持久化管理器)
              • DistributedManager(分布式管理器)
              • Stores(存储器)
                • StoreBase(存储库)
                  • FileStore
                    • JDBCStore
                    • The Application
                      • The Bootstrap Class
                        • The SimpleWrapperValve Class
                        • Running the Application
                        • Summary
                        相关产品与服务
                        对象存储
                        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                        http://www.vxiaotou.com