it-swarm.com.de

Wie funktionieren Servlets? Instantiierung, Sitzungen, gemeinsame Variablen und Multithreading

Angenommen, ich habe einen Webserver, der zahlreiche Servlets enthält. Für Informationen, die zwischen diesen Servlets übergeben werden, setze ich Sitzungs- und Instanzvariablen.

Wenn nun zwei oder mehr Benutzer eine Anfrage an diesen Server senden, was passiert dann mit den Sitzungsvariablen? Sind sie alle für alle Benutzer gleich oder werden sie für jeden Benutzer unterschiedlich sein? Wenn sie sich unterscheiden, wie konnte der Server zwischen verschiedenen Benutzern unterscheiden?

Eine ähnlichere Frage: Wenn n Benutzer auf ein bestimmtes Servlet zugreifen, wird dieses Servlet nur beim ersten Zugriff des ersten Benutzers instanziiert oder wird es für alle Benutzer separat instanziiert? Mit anderen Worten, was passiert mit den Instanzvariablen?

1041
Ku Jon

ServletContext

Wenn der Servlet-Container (wie Apache Tomcat ) gestartet wird, werden alle seine Webanwendungen bereitgestellt und geladen. Wenn eine Webanwendung geladen wird, erstellt der Servlet-Container das ServletContext einmal und speichert es im Speicher des Servers. Der web.xml der Webanwendung und alle darin enthaltenen web-fragment.xml -Dateien werden analysiert, und jeder gefundene <servlet>, <filter> und <listener> (oder jede mit @WebServlet, @WebFilter und @WebListener versehene Klasse) wird einmal instanziiert und im Server gespeichert. Für jeden instanziierten Filter wird seine Methode init() mit einem neuen FilterConfig aufgerufen.

Wenn ein Servlet einen Wert für <servlet><load-on-startup> oder @WebServlet(loadOnStartup) hat, der größer als 0 ist, wird seine Methode init() auch beim Start mit einem neuen ServletConfig aufgerufen. Diese Servlets werden in der durch diesen Wert angegebenen Reihenfolge initialisiert (1 ist 1st, 2 ist 2nd usw.). Wenn für mehr als ein Servlet derselbe Wert angegeben ist, wird jedes dieser Servlets in der Reihenfolge geladen, in der sie im Klassenladeprogramm für web.xml, web-fragment.xml oder @WebServlet aufgeführt sind. Wenn der Wert "load-on-startup" fehlt, wird die Methode init() immer dann aufgerufen, wenn die HTTP-Anforderung dieses Servlet zum ersten Mal trifft.

Wenn der Servlet-Container mit allen oben beschriebenen Initialisierungsschritten fertig ist, wird ServletContextListener#contextInitialized() aufgerufen.

Wenn der Servlet-Container heruntergefahren wird, werden alle Webanwendungen entladen, die Methode destroy() aller initialisierten Servlets und Filter aufgerufen und alle Instanzen ServletContext, Servlet, Filter und Listener werden in den Papierkorb verschoben. Schließlich wird die ServletContextListener#contextDestroyed() aufgerufen.

HttpServletRequest und HttpServletResponse

Der Servlet-Container ist an einen Webserver angeschlossen, der auf HTTP-Anforderungen über eine bestimmte Portnummer wartet (Port 8080 wird normalerweise während der Entwicklung und Port 80 in der Produktion verwendet). Wenn ein Client (z. B. Benutzer mit einem Webbrowser oder programmgesteuert mit URLConnection ) eine HTTP-Anforderung sendet, erstellt der Servlet-Container neue HttpServletRequest und HttpServletResponse Objekte und übergibt sie an alle definierten Filter in der Kette und schließlich an die Servlet-Instanz.

Im Fall von Filter wird die Methode doFilter() aufgerufen. Wenn der Code des Servlet-Containers chain.doFilter(request, response) aufruft, fahren die Anforderung und die Antwort mit dem nächsten Filter fort oder drücken auf das Servlet, wenn keine weiteren Filter vorhanden sind.

Im Fall von Servlets wird die Methode service() aufgerufen. Standardmäßig bestimmt diese Methode, welche der doXxx()-Methoden basierend auf request.getMethod() aufgerufen wird. Wenn die ermittelte Methode im Servlet nicht vorhanden ist, wird in der Antwort ein HTTP 405-Fehler zurückgegeben.

Das Anforderungsobjekt bietet Zugriff auf alle Informationen zur HTTP-Anforderung, z. B. URL, Header, Abfragezeichenfolge und Text. Das Antwortobjekt bietet die Möglichkeit, die HTTP-Antwort nach Ihren Wünschen zu steuern und zu senden, indem Sie beispielsweise die Header und den Text festlegen können (normalerweise mit generiertem HTML-Inhalt aus einer JSP-Datei). Wenn die HTTP-Antwort festgeschrieben und abgeschlossen ist, werden sowohl das Anforderungs- als auch das Antwortobjekt wiederverwendet und zur Wiederverwendung bereitgestellt.

HttpSession

Wenn ein Client die Webapp zum ersten Mal besucht und/oder das HttpSession zum ersten Mal über request.getSession() abgerufen wird, erstellt der Servlet-Container ein neues HttpSession-Objekt und generiert eine lange und eindeutige ID (die Sie verwenden können) get by session.getId()) und speichert es im Speicher des Servers. Der Servlet-Container setzt außerdem ein Cookie im Header Set-Cookie der HTTP-Antwort mit JSESSIONID als Namen und der eindeutigen Sitzungs-ID als Wert.

Gemäß der HTTP-Cookie-Spezifikation (ein Vertrag, den ein anständiger Webbrowser und Webserver einhalten muss) muss der Client (der Webbrowser) dieses Cookie bei nachfolgenden Anforderungen im Header Cookie für zurücksenden solange der Cookie gültig ist (dh die eindeutige ID muss sich auf eine nicht abgelaufene Sitzung beziehen und die Domain und der Pfad sind korrekt). Mit dem integrierten HTTP-Verkehrsmonitor Ihres Browsers können Sie überprüfen, ob das Cookie gültig ist (drücken Sie F12 in Chrome/Firefox 23+/IE9 + und überprüfen Sie das Netz/Netzwerk tab). Der Servlet-Container überprüft den Cookie-Header jeder eingehenden HTTP-Anforderung auf das Vorhandensein des Cookies mit dem Namen JSESSIONID und verwendet seinen Wert (die Sitzungs-ID), um das zugeordnete HttpSession aus dem Serverspeicher abzurufen.

HttpSession bleibt so lange am Leben, bis es länger als den in <session-timeout> angegebenen Zeitüberschreitungswert inaktiv war (d. H. In einer Anforderung nicht verwendet wurde), eine Einstellung in web.xml. Der Timeout-Wert beträgt standardmäßig 30 Minuten. Wenn der Client die Webanwendung nicht länger als angegeben besucht, wird die Sitzung vom Servlet-Container in den Papierkorb verschoben. Jede nachfolgende Anfrage, auch mit dem angegebenen Cookie, hat keinen Zugriff mehr auf dieselbe Sitzung. Der Servlet-Container erstellt eine neue Sitzung.

Auf der Clientseite bleibt das Sitzungscookie so lange aktiv, wie die Browserinstanz ausgeführt wird. Wenn der Client die Browser-Instanz (alle Registerkarten/Fenster) schließt, wird die Sitzung auf der Client-Seite gelöscht. In einer neuen Browser-Instanz würde das mit der Sitzung verknüpfte Cookie nicht existieren, sodass es nicht mehr gesendet würde. Dadurch wird ein völlig neues HttpSession erstellt, wobei ein völlig neues Sitzungscookie verwendet wird.

In einer Nussschale

  • Die ServletContext ist so lange gültig wie die Web-App. Es wird unter allen Anforderungen in allen Sitzungen geteilt.
  • HttpSession ist so lange gültig, wie der Client mit derselben Browserinstanz mit der Web-App interagiert und die Sitzung auf der Serverseite keine Zeitüberschreitung aufweist. Es wird zwischen allen Anforderungen in der gleichen Sitzung geteilt.
  • HttpServletRequest und HttpServletResponse sind ab dem Zeitpunkt gültig, an dem das Servlet eine HTTP-Anforderung vom Client empfängt, bis die vollständige Antwort (die Webseite) eingegangen ist. Es wird nicht an anderer Stelle geteilt.
  • Alle Instanzen von Servlet, Filter und Listener sind so lange gültig, wie die Web-App ausgeführt wird. Sie werden zwischen allen Anforderungen in allen Sitzungen geteilt.
  • Jedes attribute, das in ServletContext, HttpServletRequest und HttpSession definiert ist, lebt so lange, wie das betreffende Objekt lebt. Das Objekt selbst stellt den "Gültigkeitsbereich" in Bean-Management-Frameworks wie JSF, CDI, Spring usw. dar. Diese Frameworks speichern ihre Gültigkeitsbereichsbeans als attribute des am besten passenden Gültigkeitsbereichs.

Thread-Sicherheit

Das heißt, Ihr Hauptanliegen ist möglicherweise Thread-Sicherheit . Sie sollten jetzt wissen, dass Servlets und Filter von allen Anforderungen gemeinsam genutzt werden. Das ist das Schöne an Java, es ist multithreaded und verschiedene Threads (lesen Sie: HTTP-Anforderungen) können dieselbe Instanz verwenden. Andernfalls wäre es zu teuer, sie für jede einzelne Anforderung neu zu erstellen, init() und destroy().

Sie sollten sich auch darüber im Klaren sein, dass Sie niemals Daten mit einem Anforderungs- oder Sitzungsbereich als Instanzvariable von zuweisen sollten ein Servlet oder Filter. Es wird mit allen anderen Anfragen in anderen Sitzungen geteilt. Das ist nicht threadsicher! Das folgende Beispiel veranschaulicht dies:

public class ExampleServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

Siehe auch:

1760
BalusC

Sitzungen

enter image description hereenter image description here

Kurz: Der Webserver vergibt eine eindeutige Kennung an jeden Besucher bei seinem ersten Besuch. Der Besucher muss diesen Ausweis zurückbringen, damit er beim nächsten Mal wiedererkannt wird. Diese Kennung ermöglicht es dem Server auch, Objekte, deren Eigentümer eine Sitzung ist, ordnungsgemäß von denen einer anderen Sitzung zu trennen.

Servlet-Instantiierung

Wenn Laden beim Start falsch ist :

enter image description hereenter image description here

Wenn Laden beim Start wahr ist :

enter image description hereenter image description here

Sobald er sich im Servicemodus und im Groove befindet, bearbeitet das same Servlet die Anforderungen aller anderen Clients.

enter image description here

Warum ist es keine gute Idee, eine Instanz pro Client zu haben? Denken Sie darüber nach: Werden Sie für jede Bestellung einen Pizzabäcker einstellen? Wenn Sie das tun, haben Sie in kürzester Zeit kein Geschäft mehr.

Es ist jedoch mit einem geringen Risiko verbunden. Denken Sie daran: Dieser einzelne Mann hat alle Bestellinformationen in der Tasche. Wenn Sie also nicht vorsichtig sind Thread-Sicherheit für Servlets , gibt er möglicherweise einem bestimmten Kunden die falsche Bestellung.

421
Jops

Sitzung in Java-Servlets entspricht der Sitzung in anderen Sprachen wie PHP. Es ist für den Benutzer eindeutig. Der Server kann den Vorgang auf verschiedene Arten verfolgen, z. B. durch Cookies, das Umschreiben von URLs usw. In diesem Artikel von Java doc wird er im Zusammenhang mit Java-Servlets erläutert. Außerdem wird angegeben, wie die Sitzung verwaltet wird. Dies ist ein Implementierungsdetail, das den Konstrukteuren verbleibt des Servers. Die Spezifikation legt lediglich fest, dass sie für einen Benutzer über mehrere Verbindungen zum Server hinweg eindeutig sein muss. In diesem Artikel von Oracle finden Sie weitere Informationen zu beiden Fragen.

Edit Es gibt ein ausgezeichnetes Tutorial here , wie Sie mit Session innerhalb von Servlets arbeiten. Und here ist ein Kapitel von Sun über Java Servlets, was sie sind und wie man sie benutzt. Zwischen diesen beiden Artikeln sollten Sie in der Lage sein, alle Ihre Fragen zu beantworten. 

42
Chris Thompson

Wenn der Servlet-Container (wie Apache Tomcat) gestartet wird, liest er aus der Datei web.xml (nur eine pro Anwendung), wenn etwas schief geht oder ein Fehler in der Containerseitenkonsole auftritt. Andernfalls wird das gesamte Web bereitgestellt und geladen Anwendungen mithilfe von web.xml (so genannt als Implementierungsdeskriptor).

Während der Instantiierungsphase des Servlets ist die Servlet-Instanz bereit, kann jedoch die Clientanforderung nicht bedienen, da sie mit zwei Informationen fehlt:
1: Kontextinformationen
2: Informationen zur Erstkonfiguration

Die Servlet-Engine erstellt das Interface-Objekt servletConfig, in dem die oben genannten fehlenden Informationen eingeschlossen sind. Die Servlet-Engine ruft init () des Servlets auf, indem sie die Objektreferenzen von servletConfig als Argument angibt. Sobald init () vollständig ausgeführt wurde, ist das Servlet bereit, die Clientanforderung zu bedienen. 

Q) Während der Lebensdauer des Servlets wie oft erfolgt die Instantiierung und Initialisierung?

A) nur einmal (für jede Clientanforderung wird ein neuer Thread erstellt) Nur eine Instanz des Servlets bedient eine beliebige Anzahl der Clientanfragen, dh, nachdem ein Clientanforderungsserver bedient wurde, stirbt er nicht. Sie wartet auf andere Client-Anforderungen, dh welche CGI-Einschränkung (für jede Client-Anforderung wird ein neuer Prozess erstellt wird) wird mit dem Servlet überwunden (die Servlet-Engine erstellt intern den Thread).

F) Wie funktioniert das Sitzungskonzept?

A) Immer wenn getSession () für das HttpServletRequest-Objekt aufgerufen wird 

Schritt 1 : Anforderungsobjekt wird auf eingehende Sitzungs-ID ausgewertet.

Schritt 2 : Wenn die ID nicht verfügbar ist, wird ein brandneues HttpSession-Objekt erstellt und die entsprechende Sitzungs-ID wird generiert (dh von HashTable). Die Sitzungs-ID wird im httpservlet-Antwortobjekt gespeichert und die Referenz des HttpSession-Objekts wird an das Servlet zurückgegeben ( doGet/doPost). 

Schritt 3 : Wenn die ID zur Verfügung steht, wird ein brandneues Sitzungsobjekt nicht erstellt. Die Sitzungs-ID wird aus der Abfrage des Anforderungsobjekts abgerufen. Die Sitzung wird in der Sammlung von Sitzungen unter Verwendung der Sitzungs-ID als Schlüssel durchgeführt. 

Nach erfolgreicher Suche wird die Sitzungs-ID in HttpServletResponse gespeichert und die vorhandenen Sitzungsobjektverweise an doGet () oder doPost () von UserDefineservlet zurückgegeben.

Hinweis:

1) Wenn die Kontrolle vom Servlet-Code an den Client übergeht, vergessen Sie nicht, dass das Session-Objekt vom Servlet-Container, dh der Servlet-Engine, gehalten wird

2) Multithreading wird Servlet-Entwicklern zum Implementieren überlassen, dh, die mehrfachen Anforderungen des Clients müssen sich nicht mit Multithread-Code beschäftigen 

Kurzform:

Ein Servlet wird erstellt, wenn die Anwendung gestartet wird (sie wird im Servlet-Container bereitgestellt) oder beim ersten Zugriff darauf (abhängig von der Einstellung für das Laden beim Start) Wenn das Servlet instanziiert ist, wird die Methode init () der Servlet heißt Dann verarbeitet das Servlet (seine einzige Instanz) alle Anforderungen (seine service () - Methode wird von mehreren Threads aufgerufen). Aus diesem Grund ist es nicht ratsam, eine Synchronisierung zu verwenden, und Sie sollten Instanzvariablen des Servlets vermeiden. Wenn die Anwendung nicht implementiert ist (der Servlet-Container wird angehalten), wird die destroy () -Methode aufgerufen.

33
Ajay Takur

Sitzungen - was Chris Thompson gesagt hat.

Instantiation - Ein Servlet wird instanziiert, wenn der Container die erste dem Servlet zugeordnete Anforderung empfängt (es sei denn, das Servlet ist so konfiguriert, dass es beim Start mit dem Element <load-on-startup> in web.xml geladen wird). Dieselbe Instanz wird für nachfolgende Anforderungen verwendet.

20
Lauri Lehtinen

Die Servlet-Spezifikation JSR-315 definiert das Verhalten des Web-Containers in den Dienstmethoden (und den Methoden doGet, doPost, doPut usw.) eindeutig (2.3.3.1 Multithreading-Probleme, Seite 9):

Ein Servlet-Container kann gleichzeitige Anforderungen über den Dienst senden Methode des Servlets. Um die Anfragen zu bearbeiten, muss der Servlet Developer. müssen ausreichende Vorkehrungen für die gleichzeitige Verarbeitung mit mehreren Threads in der Dienstmethode.

Obwohl dies nicht empfohlen wird, kann der Entwickler mit Implementieren Sie die SingleThreadModel-Schnittstelle, die den Container benötigt um zu gewährleisten, dass sich in der .__ jeweils nur ein Anforderungsthread befindet. Servicemethode. Ein Servlet-Container kann diese Anforderung durch .__ erfüllen. Serialisierung von Anforderungen auf einem Servlet oder durch Aufrechterhalten eines Servlet-Pools Instanzen. Wenn das Servlet Teil einer Webanwendung ist, die Als vertreibbar gekennzeichnet, kann der Container einen Pool von Servlets enthalten Instanzen in jeder JVM, auf die die Anwendung verteilt ist.

Bei Servlets, die die SingleThreadModel-Schnittstelle nicht implementieren, wenn die Servicemethode (oder Methoden wie doGet oder doPost, die an die Servicemethode der abstrakten HttpServlet-Klasse gesendet werden.) wurde mit dem synchronisierten Schlüsselwort, dem Servlet-Container, definiert Die Instanzpoolmethode kann nicht verwendet werden, aber Anforderungen müssen serialisiert werden durch. Es wird dringend empfohlen, dass Entwickler nicht .__ synchronisieren. die Dienstmethode (oder die an sie gesendeten Methoden) in diesen Umstände wegen nachteiliger Auswirkungen auf die Leistung

13
tharindu_DG

Wie aus den obigen Erläuterungen hervorgeht, wird durch die Implementierung der SingleThreadModelEin Servlet kann durch den Servlet-Container Thread-Sicherheit gewährleistet werden. Die Containerimplementierung kann dies auf zwei Arten tun:

1) Serialisierung von Anforderungen (Warteschlangen) an eine einzelne Instanz - dies ist vergleichbar mit einem Servlet, das nicht SingleThreadModel BUT implementiert, das die service/doXXX-Methoden synchronisiert. ODER

2) Erstellen eines Pools von Instanzen - Dies ist eine bessere Option und ein Kompromiss zwischen dem Start/Initialisierungsaufwand/-zeit des Servlets und den restriktiven Parametern (Speicher/CPU-Zeit) der Umgebung, in der das Servlet gehostet wird.