In Java-Servlets kann über response.getOutputStream()
oder auf den Antworttext zugegriffen werden response.getWriter()
. Sollte ein Anruf .close()
auf das , OutputStream
nachdem es wurde geschrieben?
Einerseits gibt es die blochianische Ermahnung, OutputStream
s immer zu schließen . Andererseits glaube ich nicht, dass in diesem Fall eine zugrunde liegende Ressource geschlossen werden muss. Das Öffnen / Schließen von Sockets wird auf HTTP-Ebene verwaltet, um beispielsweise dauerhafte Verbindungen und dergleichen zu ermöglichen.
java
servlets
outputstream
Steven Huwig
quelle
quelle
close()
, die nichts tut. Was Sie tun sollten, ist jede verschließbare Ressource zu schließen.Antworten:
Normalerweise sollten Sie den Stream nicht schließen. Der Servlet-Container schließt den Stream automatisch, nachdem das Servlet als Teil des Servlet-Anforderungslebenszyklus ausgeführt wurde.
Wenn Sie beispielsweise den Stream geschlossen haben, ist er nicht verfügbar, wenn Sie einen Filter implementiert haben .
Trotzdem passiert nichts Schlimmes, wenn Sie es schließen, solange Sie nicht versuchen, es erneut zu verwenden.
BEARBEITEN: ein weiterer Filterlink
EDIT2: adrian.tarau ist insofern richtig, als wenn Sie die Antwort ändern möchten, nachdem das Servlet seine Aufgabe erfüllt hat, sollten Sie einen Wrapper erstellen, der HttpServletResponseWrapper erweitert, und die Ausgabe puffern. Dies soll verhindern, dass die Ausgabe direkt an den Client gesendet wird, ermöglicht Ihnen jedoch auch den Schutz, wenn das Servlet den Stream schließt, gemäß diesem Auszug (Hervorhebung von mir):
Artikel
Aus diesem offiziellen Sun-Artikel kann man schließen, dass das Schließen
OutputStream
eines Servlets etwas Normales ist, aber nicht obligatorisch.quelle
Die allgemeine Regel lautet: Wenn Sie den Stream geöffnet haben, sollten Sie ihn schließen. Wenn Sie nicht, sollten Sie nicht. Stellen Sie sicher, dass der Code symmetrisch ist.
Im Fall von
HttpServletResponse
ist es etwas weniger eindeutig, da es nicht offensichtlich ist, ob der AufrufgetOutputStream()
eine Operation ist, die den Stream öffnet. Der Javadoc sagt nur, dass es "Returns a ServletOutputStream
"; ähnlich fürgetWriter()
. In jedem Fall ist klar, dassHttpServletResponse
der Stream / Writer "gehört" und er (oder der Container) dafür verantwortlich ist, ihn wieder zu schließen.Um Ihre Frage zu beantworten - nein, Sie sollten den Stream in diesem Fall nicht schließen. Der Container muss dies tun, und wenn Sie zuvor dort hineinkommen, besteht die Gefahr, dass Ihre Anwendung subtile Fehler enthält.
quelle
close()
mit dem Stream fertig bin, kehrt der Client sofort zurück und der Rest des Servlets wird weiter ausgeführt. Macht das die Antwort dann nicht etwas relativer? im Gegensatz zu einem definitiven Ja oder NeinWenn die Möglichkeit besteht, dass der Filter für eine "eingeschlossene" Ressource aufgerufen wird, sollten Sie den Stream auf keinen Fall schließen. Dies führt dazu, dass die eingeschlossene Ressource mit einer Ausnahme "Stream geschlossen" fehlschlägt.
quelle
Sie sollten den Stream schließen, der Code ist sauberer, da Sie getOutputStream () aufrufen und der Stream nicht als Parameter an Sie übergeben wird, wenn Sie ihn normalerweise nur verwenden und nicht versuchen, ihn zu schließen. Die Servlet-API gibt nicht an, dass, wenn der Ausgabestream geschlossen werden kann oder nicht geschlossen werden darf. In diesem Fall können Sie den Stream sicher schließen, jeder Container da draußen dafür sorgt, dass der Stream geschlossen wird, wenn er nicht vom Servlet geschlossen wurde.
Hier ist die Methode close () in Jetty. Sie schließen den Stream, wenn er nicht geschlossen wird.
Auch als Entwickler eines Filters sollten Sie nicht davon ausgehen, dass der OutputStream nicht geschlossen ist. Sie sollten immer einen anderen OutputStream übergeben, wenn Sie den Inhalt ändern möchten, nachdem das Servlet seine Arbeit erledigt hat.
EDIT: Ich schließe immer den Stream und hatte keine Probleme mit Tomcat / Jetty. Ich denke nicht, dass Sie Probleme mit alten oder neuen Containern haben sollten.
quelle
Ein weiteres Argument gegen die Schließung der
OutputStream
. Schau dir dieses Servlet an. Es wird eine Ausnahme ausgelöst. Die Ausnahme wird in der Datei web.xml einer fehlerhaften JSP zugeordnet:Die Datei web.xml enthält:
Und die error.jsp:
Wenn Sie
/Erroneous
in den Browser laden, wird auf der Fehlerseite "Ein Fehler" angezeigt. Wenn Sie jedoch dieout.close()
Zeile im obigen Servlet auskommentieren, die Anwendung erneut bereitstellen und neu laden/Erroneous
, wird im Browser nichts angezeigt. Ich habe keine Ahnung, was tatsächlich passiert, aber ich denke, dasout.close()
verhindert die Fehlerbehandlung.Getestet mit Tomcat 7.0.50, Java EE 6 unter Verwendung von Netbeans 7.4.
quelle