Sobald ich auf ein Muster gestoßen bin, werden ServletRequest
und Antwortobjekte in die lokalen ThreadLocal
Variablen des Servlets gestellt. Die Servlet-Klasse verfügt auch über Methoden zum Abrufen aktueller Anfrage- und Antwortobjekte. Um diese Objekte zu erhalten, müssen Sie dennoch mit dem Servlet-Objekt arbeiten.
Wozu dienen diese ThrealLocal
lokalen Variablen?
Der Punkt besteht darin, die Anfrage- und Antwortobjekte in Klassen zu haben, die sie sonst nicht hätten (zum Beispiel sind sie keine Servlets). Ein Beispiel sind JSF-gemanagte Beans - ihre Methoden nehmen keine HttpServletRequest
-Parameter, und so können Sie die Anfrage über die FacesContext
erhalten, die sie in ThreadLocal
Variablen hat.
Der Grund dafür ist, dass jede Anfrage von einem separaten Thread (vom Servlet-Container) bearbeitet wird. Also Thread = Anfrage. Aber es gibt einen Vorbehalt - Container neigen dazu, Thread-Pools zu verwenden. Also muss man im Threadlocal immer eine neue Anfrage stellen und diese danach möglichst aufräumen (zB in Filter
). Andernfalls können Sie unerwartetes Verhalten feststellen.
Aber Sie sollten das wirklich in Ihrem Code vermeiden. Wenn Sie etwas von der Anfrage oder Antwort benötigen, übergeben Sie es als Methodenargument. Andernfalls riskieren Sie, Ebenengrenzen zu verletzen (wenn Sie versucht sind, die Anforderung beispielsweise in der Serviceebene zu verwenden)
Sie ermöglichen Ihnen Zugriff auf die HttpServletRequest und HttpServletResponse von anderen Klassen innerhalb Ihres Projekts, ohne Verweise auf diese Objekte an die anderen Klassen übergeben zu müssen. Es ist kein Muster, das mir besonders gefällt, da es dazu neigt, Ihren Web-Tier-Code mit Ihrer Geschäftslogik zu verwechseln und Unit-Tests schwieriger zu machen.
Andere haben ziemlich genau angegeben, welche Verwendung von Thread-Locals in dem von Ihnen dargestellten Szenario vorliegt. Aber seien Sie gewarnt, Thread-Local-abhängige Implementierungen sind "threadspezifisch" und brechen, wenn sich die Dinge von einem einzelnen Thread pro Anforderungsmodell entfernen. Beispiel wären ereignisbasierte Server, bei denen eine Handvoll Threads gleichzeitig für viele Benutzeranfragen verwendet werden.
Da die Request- und Response-Objekte in thread-lokalen Variablen gespeichert sind, erhalten Sie Thread-sicheren Zugriff auf diese Objekte, ohne sie als Methodenparameter weitergeben zu müssen.
Beispiel 1: Ohne lokalen Thread
%Vor%Beispiel 2: mit Thread lokal
%Vor%Offensichtlich ist es für einfache Servlets am einfachsten, die Objekte herumzugeben, aber in komplexen Szenarien ist es manchmal nützlich, einen statischen, aber Thread-sicheren Getter zu haben.
Ich bin mir nicht 100% sicher, was der Autor des Codes, auf den Sie einmal gestoßen sind, beabsichtigt hat, aber ich denke, dass die ServletRequest
-Instanz von jeder Methode im Code verfügbar ist, ohne sie zu übergeben als Parameter oder Einstellung als Instanzvariable. Normalerweise ist die Variable ThreadLocal
statisch und es gibt eine Methode, mit der die Instanz von ServletRequest
statisch abgerufen werden kann. Zum Beispiel könnten Sie in Struts FromBeans mit dieser Technik einfach auf ServletRequest
zugreifen.
Wenn Sie ein Objekt haben, das nicht threadsicher ist, aber den Zugriff auf dieses Objekt (SimpleDateFormat) nicht synchronisieren möchten. Geben Sie stattdessen jedem Thread eine eigene Instanz des Objekts.
Sie müssen sehr vorsichtig sein, um alle ThreadLocals, die Sie get()
oder set()
haben, zu bereinigen, indem Sie die remove()
-Methode von ThreadLocal verwenden.
Das ist wirklich schrecklich. Sie sollten die von Ihnen benötigten Werte so schnell wie möglich von der HTTP-Anfrage / Sitzung erhalten. Sie können diese Werte in Methodenaufrufen oder Transferobjekten übergeben. Sie sollten sich bemühen, Methoden / Klassen technologiefrei zu schreiben. Wenn Ihre Methode / Klasse eine HTTP-Anfrage von ThreadLocal erhält, ist sie eine wertlose Klasse - sie ist in keinem Nicht-HTTP-Kontext mehr nützlich.
Es ist besonders schockierend für mich, dass Leute HTTP-Anfragen von ThreadLocal in BOs (Business Objects) oder DAOs ziehen. HTTP-Anfragen sollten niemals in einer anderen Schicht als der Präsentationsebene der Anwendung erscheinen.
Tags und Links java java-ee thread-local servlets