Vorwort
Nur für Java -Entwickler sollten wir mit der Sitzung in der J2EE -Spezifikation vertraut sein. Wie implementiert Tomcat für die meisten Entwickler, die Tomcat als Webcontainer verwenden, eine Sitzung, um Benutzer zu markieren und Sitzungsinformationen zu verwalten?
Zusammenfassung
SITZUNG
Tomcat definiert intern die Schnittstellen, die sich auf die Sitzung und HTTPSession beziehen. Das Klasse -Erbschaftssystem ist in Abbildung 1 dargestellt.
Abbildung 1 Sitzungsklassengebähnesystem
In Abbildung 1 werden zusätzlich das Sitzungssystem der Klasse der Sitzung aufgelistet und hier nacheinander eingeführt.
Sitzung: Die grundlegende Schnittstellenspezifikation für Sitzungen in Tomcat.
Tabelle 1 Sitzungsschnittstellenbeschreibung
Verfahren | beschreiben |
GetCreationTime ()/setCreationTime (Zeit: lang) | Holen Sie sich und setzen Sie die Erstellungszeit der Sitzung |
getId ()/setID (ID: String) | Holen Sie sich und setzen Sie die ID der Sitzung |
GetThisAccessTime () | Holen Sie sich die Startzeit der letzten Anfrage |
GetLastaccessTime () | Holen Sie sich die Fertigstellung der letzten Anfrage |
getManager ()/setManager (Manager: Manager) | Holen Sie sich Session Manager und setzen Sie sich ein |
getMaxinactiveInterval ()/setMaxinactiveIctInterval (Intervall: int) | Erhalten Sie das maximale Zugriffsintervall zwischen der Einstellung der Sitzung |
getSession () | Holen Sie sich httpSession |
isvalid ()/setvalid (isvalid: boolean) | Holen Sie sich und setzen Sie den gültigen Status der Sitzung |
Access ()/Endaccess () | Start und beenden Sie den Sitzungszugriff |
erlöschen() | Legen Sie den Ablauf der Sitzung fest |
HttpSession: Eine Schnittstellenspezifikation für eine Sitzung, die von einem HTTP -Client und einem HTTP -Server bereitgestellt wird.
Tabelle 2 HttpSession Interface Beschreibung
Verfahren | beschreiben |
GetCreationTime () | Holen Sie sich die Erstellungszeit der Sitzung |
getid () | Holen Sie sich die Sitzungs -ID |
GetLastaccessTime () | Holen Sie sich die Fertigstellung der letzten Anfrage |
GetServletContext () | Holen Sie sich den ServletContext, zu dem die aktuelle Sitzung gehört |
getMaxinactiveInterval ()/setMaxinactiveIctInterval (Intervall: int) | Erhalten Sie das maximale Zugriffsintervall zwischen der Einstellung der Sitzung |
getAttribute (Name: String) /setAttribute (Name: String, Wert: Objekt) | Holen Sie sich und setzen Sie die Session Scope -Eigenschaften und setzen Sie |
removeTtribute (Name: String) | Löschliche Sitzungssache Eigenschaften |
ungültig () | Die Sitzung ungültig machen und jedes an diese Sitzung gebundene Objekt rückgängig machen |
Clustersession: In der Sitzungsgrenzfabrik -Spezifikation unter Cluster -Bereitstellung werden ihre Hauptmethoden aufgeführt, und in Tabelle 3 wird diese Methoden eingeführt.
Tabelle 3 Clustersession Schnittstelle Beschreibung
Verfahren | beschreiben |
isprimarysesion () | Ist es die Hauptsitzung des Clusters? |
setPrimarysesion (boolesche Primärsession) | Richten Sie die Cluster -Master -Sitzung ein |
StandardSession: In diesem Artikel wird eine Standard -Implementierung von Standard -HTTP -Sitzungen als Beispiel verwendet.
Bei der Bereitstellung eines Tomcat -Clusters muss der Sitzungsstatus jedes Knotens im Cluster synchronisiert werden.
ReplydSession: Jedes Mal wird das gesamte Sitzungsobjekt mit anderen Knoten im Cluster synchronisiert, und die anderen Knoten aktualisieren dann das gesamte Sitzungsobjekt. Diese Implementierung ist relativ einfach und bequem, führt jedoch zu einer großen Menge ungültiger Informationen.
Deltasession: Synchronisiert die in der Sitzung inkrementell modifizierten Eigenschaften. Da diese Methode inkrementell ist, verringert sie den Aufwand der Netzwerk -E/A stark, aber die Implementierung wird komplizierter sein, da sie die Verwaltung von Sitzungsattributbetriebsprozessen umfasst.
Sitzungsmanager
Tomcat definiert intern die Manager -Schnittstelle zur Formulierung der Schnittstellenspezifikationen des Sitzungsmanagers.
Abbildung 2 Klasse Erbschaftssystem des Sitzungsmanagers
Wir werden den entsprechenden Inhalt in Abbildung 2 eins nach dem anderen beschreiben:
Manager: Tomcat für die vom Sitzungsmanager definierte Schnittstellenspezifikation, Abbildung 2 hat die in der Manager -Schnittstelle definierten Hauptmethoden aufgeführt, und in Tabelle 4 beschreibt die Rolle dieser Methoden im Detail.
Tabelle 4 Manager -Schnittstelle Beschreibung
Verfahren | beschreiben |
getContainer ()/setContainer (Container: Container) | Holen Sie sich den Container, der dem Sitzungsmanager zugeordnet ist, oder setzen Sie im Allgemeinen einen Kontextcontainer |
getDivibibleable ()/setDItribibleable (verteilbar: boolean) | Holen Sie sich oder festlegen, ob der Sitzungsmanager verteilt unterstützt wird |
getMaxinactiveInterval ()/setMaxinactiveIctInterval (Intervall: int) | Holen Sie sich das maximale inaktive Intervall für die vom Sitzungsmanager erstellte Sitzung oder setzen Sie |
getSessionIdLength ()/setSessionIdLength (idLength: int) | Holen Sie sich die Länge der vom Sitzungsmanager erstellten Sitzungs -ID |
GetSessionCounter ()/setSessionCounter (Sessioncounter: Long) | Holen Sie sich die Gesamtzahl der vom Sitzungsmanager erstellten Sitzungen oder festlegen |
getMaxactive ()/setMaxactive (maxActive: int) | Holen Sie sich die maximale Anzahl derzeit aktivierter Sitzungen |
GetactiveSsions () | Lassen Sie alle derzeit aktiven Sitzungen aktiviert |
GetExpiredSessions ()/setExpiredSessions (Ablaufsesions: Long) | Holen Sie sich oder setzen Sie die Anzahl der derzeit abgelaufenen Sitzungen |
GetRejecedSesions ()/setRejecedSesions (abgelehnte Besitzungen: int) | Holen Sie sich oder setzen Sie die Anzahl der Sitzungen, die verweigert wurden, um erstellt zu werden |
GetSessionMaxalivetime ()/setSessionMaxalivetime (SessionMaxalivetime: int) | Erhält oder legt die maximale Aktivitätsdauer in einer abgelaufenen Sitzung ab oder legt sie fest |
GetSessionaverageAlivetime ()/setSessionaverageAlivetime (sessionaverageAlivetime: int) | Holen Sie sich die durchschnittliche Aktivitätsdauer für eine abgelaufene Sitzung |
Hinzufügen (Sitzung: Sitzung)/entfernen (Sitzung: Sitzung) | Fügen Sie den Sitzungsmanager aktive Sitzungen hinzu oder löschen Sie sie |
ÄnderungSessionID (Sitzung: Sitzung) | Legen Sie die neu generierte zufällige Sitzungs -ID für die Sitzung fest |
createsession (sessionID: String) | Erstellen Sie eine neue Sitzung basierend auf der Standardattributkonfiguration des Sitzungsmanagers |
FindSession (ID: String) | Gibt die Sitzung mit der eindeutigen Marke des SessionID -Parameters zurück |
Funde () () | Gibt alle vom Sitzungsmanager verwalteten Aktivitäten zurück |
load ()/entladen () | Lastsitzung vom Persistenzmechanismus oder Schreibsitzung zum Persistenzmechanismus |
Hintergrundprozess () | Die Containerschnittstelle ist als Implementierung spezifischer Containerverarbeitungsarbeiten im Hintergrund definiert. |
ManagerBase : Verpfändet eine abstrakte Klasse, die häufig von der Manager -Schnittstelle implementiert wird. Alle Sitzungsmanager werden von Managerbase geerbt.
ClusterManager : Einige Schnittstellen unter Cluster -Bereitstellung basierend auf der Manager -Schnittstelle.
PersistentManagerBase: Bietet eine grundlegende Implementierung der Sitzung Persistenz.
PersistentManager: Von PersistentManagerBase erbelt, kann es verwendet werden, indem das Element <Spors> in server.xml konfiguriert wird. PersistentManager kann die Sitzungsinformationen im Speicher in einer Datei oder Datenbank sichern. Wenn ein Sitzungsobjekt gesichert ist, wird das Sitzungsobjekt in den Speicher (Datei oder Datenbank) kopiert, während das ursprüngliche Objekt im Speicher bleibt. Selbst wenn der Server ausgeht, kann das aktive Sitzungsobjekt dennoch aus dem Speicher abgerufen werden. Wenn das aktive Sitzungsobjekt die Obergrenze überschreitet oder das Sitzungsobjekt zu lange im Leerlauf ist, wird die Sitzung in den Speicher ausgetauscht, um Speicherplatz zu speichern.
StandardManager: Wenn Tomcat normalerweise geschlossen ist, werden die Speichersitzung in der Datei des Tomcat -Verzeichnisses serialisiert. . Wenn der Tomcat -Neustart oder die Anwendung geladen wird, stellt Tomcat die Sitzung in der Datei in den Speicher wieder her. Wenn der Server plötzlich beendet wird, gehen alle Sitzungen verloren, da StandardManager keine Chance hat, die Speicherverarbeitung zu implementieren.
ClusterManagerBase: Bietet eine Cluster -Management -Implementierung für die Sitzung.
Deltamanager: Von ClusterManagerBase geerbt. Dieser Sitzungsmanager ist Tomcats Standard -Manager unter Cluster -Bereitstellung.
BackupManager: Erbt ClusterManagerBase nicht, implementiert jedoch die ClusterManager -Schnittstelle direkt. Es ist ein optionaler Sitzungsmanager für Tomcat unter Cluster -Bereitstellung. Alle Knoten im Cluster können auf diesen Sicherungsknoten zugreifen, um den Sicherungseffekt der Sitzung im Cluster zu erreichen.
Der Einfachheit halber verwendet dieser Artikel StandardManager als Beispiel, um das Management der Sitzung zu erläutern. StandardManager ist eine untergeordnete Komponente von StandardContext, mit der die Erstellung und Wartung aller Sitzungen des aktuellen Kontextes verwaltet wird. Wenn Sie den Inhalt des Artikel "Tomcat Quellcodeanalyse - Lebenszyklusmanagement" lesen oder vertraut sein sollten, wissen Sie, dass die Startinternal -Methode von StandardContext (siehe Listing 1), wenn Standardcontext offiziell gestartet wird startet immer noch StandardManager.
Codeauflistung 1
@Override Protected Synchronized void startInternal () löst LifecycleException {// Code aus, der sich nicht mit dem Sitzungsmanagement bezieht // Clustered Manager -Manager ContextManager = null; && verteilte) {try {contextManager = getCluster (). CreateManager (getName ()); StandardManager (); Lassen Sie den Cluster wissen, dass es einen Kontext gibt // und dass er einen eigenen Manager GetCluster () hat. RegisterManager (Manager); if (Manager! .Error ("Fehlermanager. Start ()", e);
Aus Auflistung 1 können Sie feststellen, dass die Startinterne Methode von StandardContext wie folgt die Sitzungsverwaltung beinhaltet:
StandardManager erstellen;
Wenn Tomcat Apache für die verteilte Bereitstellung kombiniert, wird der aktuelle StandardManager im Cluster registriert.
StandardManager starten;
Die Startmethode von StandardManager wird verwendet, um StandardManager zu starten, und die Implementierung ist in Listing 2 des Codes angezeigt.
Codeauflistung 2
@Override public synchronisierte endgültige void start () löscht LifecycleException {// den Code für die Zustandsüberprüfung weg aus (state.equals (lifecyclestate.new)) {init (); ! } if (state.equals (LifeCyClestate.Failed) || state.equals (LifeCyClestate.must_stop)) {stop (); tun, was sie sollen.
Aus Listing 2 können wir feststellen, dass die Schritte zum Starten von StandardManager wie folgt sind:
Rufen Sie die Init -Methode auf, um den StandardManager zu initialisieren.
Rufen Sie die StartInternal -Methode auf, um StandardManager zu starten.
Initialisierung von StandardManager
Nach der obigen Analyse wissen wir, dass der erste Schritt, um StandardManager zu starten, die Init -Methode der übergeordneten Klassenlebenszyklus aufrufen wird. sich um die Initinterne von StandardManager zu kümmern. StandardManager selbst implementiert nicht die initinternale Methode, aber die übergeordnete Klassenmanagerbasis von StandardManager implementiert diese Methode. Weitere Informationen finden Sie in Listing 3 für ihre Implementierung.
Codeauflistung 3
@Override Protected void initinternal () löscht LifecycleException {Super.initinternal ();
Leseliste von Code 3 fassen die Ausführungsschritte der initinternalen Methode von ManagerBase zusammen:
Registrieren Sie den Container selbst, den StandardManager, in JMX (siehe Artikel "Tomcat -Quellcode -Analyse - Lebenszyklusmanagement" zur Implementierung der initinternalen Methode von LifecyclembeanBase).
Holen Sie sich den aktuellen Tomcat aus dem übergeordneten Container -Standardcontext und stellen Sie ihn auf die Boolesche Eigenschaft von Managerbase Distable ein.
Rufen Sie die GetRandombytes -Methode an, um ein zufälliges Byte -Array aus der Zufallszahlendatei /Dev /Urandom zu erhalten.
Hinweis: Das zufällige Byte -Array, das durch Aufrufen von GetRandombytes -Methode hier generiert wird, wird hier nicht verwendet.
Lesen wir die Code -Implementierung der GetRandombytes -Methode im Detail an, siehe Listing 4 des Code.
Codeauflistung 4
Protected void GetRandombytes (Byte -Bytes []) {// ein Byte -Array mit einer Sitzungskennung generieren, wenn (devrandomsource! int len = randomis.read (bytes); catch (Ausnahme) {// Ignorieren Sie} Devrandomsource = NULL; ) .NextBytes (Bytes);
setRandomFile in Listing 4
Methoden (siehe Auflistung 5 für Code) werden verwendet, um ein Zufallsnummern -Byte -Array aus der Zufallszahlendatei /Dev /Urandom abzurufen.
Liste von Code 5
public void setRandomFile (String s) {// Als Hack können Sie eine statische Datei verwenden und dasselbe Session -IDs (gut für seltsames Debugging) if (globals.is_se curity_enable) {randomis = accesscontroller.doprivilegge (neu (neu PrivilegedRandomFile (s)); Readlong (); ) {try {randomis.close ();
Die SetRandomFile -Methode in Listing 4 (siehe Listing 6) generiert eine Instanz von java.security.securerandom durch Reflexion und verwendet diese Instanz, um ein Array von zufälligen Bytes zu generieren.
Codeauflistung 6
public random GetRandom () {if (this.random == null) {// Berechnen Sie den neuen Zufallszahlen -Generator Long Seed = System.CurrentTimillis (); ) für (int i = 0; i <Entropie.Length; // eine neue zufällige Zahlen -Generatorklasse <?> Clazz = class.Forname (RandomClass); e) {// fallen Sie auf den einfachen Fall log.Error zurück (Sm.getString ("Managerbase.Random", RandomClass), e); (Seed)); ) + "" + (t2-t1));
Gemäß der obigen Analyse führt die Initialisierung von StandardManager hauptsächlich die initinterne Methode von Managerbase aus.
Start von StandardManager
Das Aufrufen der Startinternal -Methode von StandardManager wird verwendet, um StandardManager zu starten, siehe Listing 7.
Codeauflistung 7
@Override Protected Synchronisierte void startInternal () löscht Lebenszyklus aus {// Initialisierung des Zufallszahlengenerators (log.isdebugenable D ()) log.debug ("Initialisierung der Zufallszahlen in Kraft"); isdebugenabled ()) log.debug ("Initialisierung der Zufallsnummer abgeschlossen"); Managerload "), t);} setState (LifeCyClestate.Starting);}
Aus Auflistung 7 können wir feststellen, dass die Schritte zum Starten von StandardManager wie folgt sind:
Schritt 1: Rufen Sie die GenerateSessionID -Methode auf (siehe Listing 8), um eine neue Sitzungs -ID zu generieren.
Codeauflistung 8
geschützte synchronisierte String generateSessionID () {byte random [] = new Byte [16]; {int resultlenBytes = 0; ; zufällig [j] & 0x0f); ; JVMROUTE! ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::
Schritt 2 lädt die anhaltenden Sitzungsinformationen. Warum muss die Sitzung bestehen bleiben? Da alle Sitzungen in einer Concurrenthashmap in StandardManager aufrechterhalten werden, führt der Server -Neustart oder die Ausfallzeiten zu, dass diese Sitzungsinformationen verloren gehen oder ungültig werden. Schauen wir uns die Implementierung der Lademethode von StandardManager an, siehe Listing 9 des Code.
Codeliste 9
public void load () löscht ClassNotFoundException, IOException {if (SecurityUtil.ispackageProteceTezenable ()) {try {AccessController.doper Ivileged (new privilegedDoload ()); Ausnahmeinstanz klassennotFoundException) {throw (classNotFoundException) Ausnahme; ;}} else {doload ();
Wenn der Sicherheitsmechanismus eingeschaltet werden muss und der Paketschutzmodus eingeschaltet wird, wird die persistierte Sitzung durch Erstellen eines privilegierten Doloads geladen, das wie in Listing 10 des Code gezeigt implementiert wird.
Listing 10
privileddoload implementiert privilegedExceptionAction <void> {privilegedDoload () {// noop} öffentlicher void Run () Ausnahme {do load ();
Aus Auflistung 10 können wir sehen, dass die Methode, die tatsächlich für das Laden verantwortlich ist, doload ist. Daher müssen wir uns nur die Implementierung von Doload ansehen, siehe Listing 11 des Code.
Listing 11
Protected void doload () löscht ClassNotFoundException, IOException {if (log.isdebugenable ()) log.debug ("Start: Ladedauer"); zum angegebenen Pfadname, wenn eine Datei file = file (); FileInput Stream Fis = null; Container! Erstellen eines benutzerdefinierten Objekteingangsstroms für Klassenloader "); neuer ObjektinputStream (Bis); .GetString ("StandardManager.Loading .ioe", e), e); null) {try {Bis. ReadObject (); {StandardsSession = GetNewSesion (); ) {// Die Sitzung ist bereits ungültig, die Sitzung abgelaufen, um Speicherleck zu verhindern. getString ("StandardManager.Loading.cnfe", e), e); .GetString ("StandardManager.Loading. ioe", e), e); OIS.CLOSE (); Debuggen ("Finish: Loa Ding bestand an");
Aus den Auflistung 11 finden Sie in den Ausführungsschritten der StandardManager -Doload -Methode wie folgt:
Löschen Sie die Sitzungsinformationen, die durch den Sessions -Cache aufrechterhalten werden.
Rufen Sie die Dateimethode an, um die persistente Datei im aktuellen Kontext zurückzugeben, wie z.
Öffnen Sie den Eingabestream der persistierenden Datei der Sitzung und verkapulieren sie als CustomObjectInputStream.
Lesen Sie die Anzahl der persistierten Sitzungen aus der persistenten Sitzung und lesen Sie dann die Sitzungsinformationen nacheinander und geben Sie sie in den Sitzungscache ein.
Zu diesem Zeitpunkt ist die Einführung in den Start von StandardManager hier.