Normalerweise gibt es nur den lesenden Zugriff auf alle dem Server bekannten Resourcen. Das sind alle statischen Ressourcen des Servers (HTML Files, Bilder...). Mit
String file = getServletContext().getRealPath("/resources/myfile.txt");versucht der Container den realen, lokalen Pfad der Ressource zu ermitteln. Schlägt dieser Versuch fehl (die Ressource befindet sich zum Beispiel in einem war-Archive), wird null zurückgegeben!
Die Spec beschreibt jedoch auch eine eingeschränkte Möglichkeit für den schreibenden Zugriff auf das Filesystem. Mit
File dir = (File) session.getServletContext().getAttribute("javax.servlet.context.tempdir");
bekommt man Zugriff auf ein Verzeichnis für temporäre Daten mit Schreibrechten. Dieses Verzeichnis ist dem ServletContext zugeordnet und an seinen Lifecycle gebunden, was nichts anderes bedeutet, als dass das Verzeichnis bei jedem Restart leer ist! In geclusterten Umgebungen darf diese Ablage nicht für das Hinterlegen eines konversational state benutzt werden.
Komprimierung erfolgt serverseitig, wenn der Client im Request-Header (Attribut: Accept-Encoding) seine Möglichkeiten zur Dekodierung angegeben hat. Praktisch alle modernen Clients unterstützen gzip-Kodierung, findet der Server im Request einen entsprechenden Hinweis, steht der Komprimierung nichts im Wege. Für die Kompression der Webinhalte eines J2EE Containers bedient man sich am besten der Filtertechnologie. Jeder Response-Stream (einer bestimmten Request-URL Signatur) wird dabei vor dem Abschicken komprimiert. Dazu sind drei Implementierungsklassen nötig: der Filter, ein ResponseWrapper den dieser Filter zurückliefert und ein OutputStream der die Komprimierung erledigt und vom ResponseWrapper geliefert wird. Die fertige Implementierung habe ich in weiten Teilen bei http://www.jspbook.com abgeguckt.
Die fehlerfreie Abarbeitung im Servlet kann jederzeit von einer IOException gestört werden. Solche Abbrüche sind nichts Ungewöhnliches, der Nutzer selbst ist die häufigste Ursache:
Insbesondere wenn Containerressourcen oder FileIO im Spiel sind, muss die Freigabe der Ressource dann in einem finally Block erzwungen werden:
doGet(..) { // Connection con = null; try { // Connection con = conFactory.getConnection(); out.write(con.getAnswerToUniverseLifeAndAllTheRest()); // } finally { if (con != null) { con.close(); } } }Falsch wäre hingegen dieses Beispiel, im Falle einer IOException im try Block wird die Connection nicht geschlossen und bleibt bis zu ihrem Timeout blockiert:
doGet(..) { // Connection con = null; try { // Connection con = conFactory.getConnection(); out.write(con.getAnswerToUniverseLifeAndAllTheRest()); // } catch(SomeConnectionException e) { // try to recover } if (con != null) { con.close(); } }