<jsptutorial />

Verzeichnisstruktur von Java-Webanwendungen


SUN und die anderen an den Servlet- und JSP-Spezifikationen beteiligten Firmen haben großes Gewicht darauf gelegt, dass am Ende ein echter Container-übergreifender Standard entsteht. Dank dieser gründlichen Arbeit der Spezifikationsgruppe ist es nun wirklich möglich, Web-Anwendungen einfach von einem Container zu einem anderen zu migrieren.
Um dies zu erreichen, wurde eine für alle Container verbindliche Verzeichnisstruktur für Web-Anwendungen festgelegt. Zudem wurde das Format der WAR-Dateien (WAR steht für Web-Archiv) spezifiziert. Diese Web-Archiv-Dateien sind fertig gepackte Web-Anwendungen. Durch das Deployment einer einzigen WAR-Datei kann eine gesamte Web-Anwendung auf den Server aufgespielt werden.
Wir beschreiben zuerst den Verzeichnisbaum einer Java-Webanwendung und gehen danach auf die WAR-Dateien, deren Erstellung und deren Nutzung ein.

Zum SeitenanfangZum Seitenanfang

Document Root, die Wurzel der Webanwendung

Die sogenannte "Document Root" ist die Wurzel einer Webanwendung. Unterhalb dieser Wurzel liegen die HTML- und JSP-Dateien, Bilder, CSS-Dateien usw. Es können außerdem beliebige Unterverzeichnisse angelegt werden. Zudem gibt es zwei Verzeichnisse, "WEB-INF" und "META-INF", die eine besondere Bedeutung haben und bestimmten Regeln folgen müssen. Das Verzeichnis "WEB-INF" ist für jede Web-Anwendung obligatorisch, "META-INF" ist hingegen eher nur in Ausnahmefällen vorhanden.
Ein typisches Verzeichnis könnte bspw. wie folgt aussehen:
directory_structure.png
Hier existieren bspw. die Verzeichnisse "css", "js" und "pics" für CSS-, JavaScript- und Bild-Dateien. HTML- und JSP-Dateien würden hier bspw. direkt in der Wurzel des Verzeichnisses "example" liegen und in "WEB-INF" finden wir die weiter unten beschriebene Struktur. Bei Tomcat würde das abgebildete Verzeichnis unterhalb von "$TOMCAT_HOME/webapps" liegen.
Jeder Webanwendung ist ein Servlet-Kontext zugeordnet. I.a.R. heißt dieser genau so wie das Verzeichnis, das die "Document Root" bildet, in unserem Beispiel also würde der Servlet-Kontext "example" heißen. Jede Anwendung verfügt über ein ihr zugeordnetes Objekt der Klasse "javax.servlet.ServletContext", über das es Zugriff auf Informationen und Hilfsobjekte für diese Anwendung hat (mehr zu diesem Objekt im Kapitel "Implizite Objekte").
Der Servlet-Container mappt zwischen den Anforderungs-URLs und der entsprechenden Web-Anwendung einfach anhand des Pfades. Bei der URL

http://www.jsptutorial.org/example/index.html

prüft der Container, ob eine Webanwendung mit dem Namen "example" existiert. Wenn ja, wird der Request für die Datei "/index.html" an diese Anwendung weitergeleitet. Wenn nicht, wird der Request an die Standard-Anwendung weitergeleitet und dort nach einer Datei "index.html" im Verzeichnis "example" gesucht.

Zum SeitenanfangZum Seitenanfang

WEB-INF

Das Verzeichnis "WEB-INF" unterhalb der "Document Root" ist ein besonderes Verzeichnis. Es enthält Konfigurations-Dateien und die benötigten Bibliotheken und Java-Klassen der Anwendung.
Da dies durchweg kritische Dateien sind, schreibt die Servlet-Spezifikation aus Sicherheitsgründen verpflichtend vor, dass Dateien und Verzeichnisse unterhalb von "WEB-INF" niemals direkt von einem Client angefragt werden können. Der Aufruf

http://www.jsptutorial.org/examples/WEB-INF/web.xml

würde bspw. zu einem Fehler "Page Not Found" (Status-Code 404) führen, obwohl die Datei existiert.
Man kann dort aber durchaus HTML- und JSP-Seiten nutzen, wenn sie von einem Servlet aus mittels Request-Forwarding aufgerufen werden. Dies ist sogar gängige Praxis bei Anwendungen, die dieses Modell nutzen, um ein versehentliches Aufrufen der JSPs ohne die dringend benötigten Request-Attribute zu unterbinden. Wir kommen darauf noch im Kapitel "Anwendungsarchitektur" zu sprechen.
Wie schon erwähnt, befinden sich alle Blibliotheken und Klassen unterhalb von "WEB-INF". Dazu müssen diese in speziellen Verzeichnissen liegen. Bibliotheken, die als jar-Dateien vorliegen, kommen direkt in das "WEB-INF/lib"-Unterverzeichnis. Bibliotheken oder Anwendungsklassen, die nur in einer ausgepackten Verzeichnisstruktur existieren, müssen unterhalb des Verzeichnisses "WEB-INF/classes" liegen. Dabei gilt hier wie bei Java üblich, dass Klassen eines Packages unterhalb eines Verzeichnisses entsprechenden Namens liegen müssen. Also bspw. die Klasse "WebUtils" des Packages "org.jsptutorial.util" im Verzeichnis "WEB-INF/classes/org/jsptutorial/util/". In das "WEB-INF/classes"-Verzeichnis kommen im Übrigen auch alle Dateien, die im Classpath liegen müssen, also insbesondere properties-Dateien oder xml-Konfigurationsdateien.
Seit der JSP-Spezifikation 2.0 gibt es noch ein weiteres Unterverzeichnis "WEB-INF/tags", das Tag-Files enthält. Tag-Files sind neue Elemente der JSP-Spezifikation, die das Erstellen von Tag-Libraries vereinfachen (s. dazu das Kapitel Tag-Libraries). Tag-Files kommen entweder direkt in das "WEB-INF/tags"-Verzeichnis oder in weitere Unterverzeichnisse unterhalb von diesem.

Zum SeitenanfangZum Seitenanfang

META-INF

Dieses Verzeichnis existiert eigentlich nur bei ausgepackten WAR-Dateien. Aber ob nun direkt angelegt oder aufgrund eines ausgepackten WAR-Datei entstanden, es gilt immer, dass sämtliche Dateien und Verzeichnisse unterhalb dieses Verzeichnisses als nicht existent gelten. Jeder Aufruf einer dieser Dateien führt zu einem "Page Not Found"-Fehler (Status-Code 404).
Dieses Verzeichnis wird beim Erstellen von WAR-Dateien automatisch vom jar-Tool innerhalb der WAR-Dateien selbst angelegt. Es enthält lediglich Informationen, die für den Umgang mit WAR-Dateien seitens der Java-Tools selbst notwendig sind.

Zum SeitenanfangZum Seitenanfang

WAR-Dateien

WAR-Dateien sind eigentlich nichts wirklich Besonderes. Sie sind im Kern lediglich ganz normale JAR-Dateien, die allerdings eine andere Extrension haben müssen. Und sie enthalten eben nicht eine Klassen-Hierarchie, eine Bibliothek, wie bei JAR-Dateien üblich, sondern ein vollständig gepacktes Web-Verzeichnis. D.h. alle Dateien unterhalb der "Document Root" werden in eine WAR-Datei gepackt.
Nehmen wir an, wir wollten unsere "example"-Webanwendung packen. Dann würde wir zunächst in das entsprechende Verzeichnis wechseln und dort dann folgenden Befehl eingeben:

"jar cfv example.war ." oder "jar cfv example.war -C pathToDir ."

Dabei muss das jar-Tool des JDKs im Pfad der ausführbaren Dateien liegen. Ansonsten muss das Tool über seinen vollständigen Pfad aufgerufen werden. Das jar-Tool schreibt die relativen Verzeichnis-Namen der gepackten Dateien mit in die Datei. Daher muss man entweder in das Wurzelverzeichnis der zu packenden Webanwendung wechseln, oder mit "-C pathToDir" dem Tool mitteilen, in welches Verzeichnis es zum Packen wechseln soll.
Der Befehl besagt nun, dass eine Datei Namens "example.war" erzeugt werden soll und zwar mit dem gesamten Inhalt des Verzeichnisses (dafür steht der abschließende Punkt des ersten Befehls). Das ist schon die gesamte Magie einer war-Datei. Diese kann nun in das für den jeweiligen Servlet-Container definierte Deploy-Verzeichnis (bei Tomcat ist dies $TOMCAT_HOME/webapps) kopiert werden. Je nach Konfiguration des Containers muss dieser evtl. noch neu gestartet werden, oder aber die Anwendung ist unmittelbar nach dem Deploy-Vorgang live zugänglich.
Der Vorteil von war-Dateien ist, dass sie das Deployment extrem vereinfachen und die Verzeichnis-Struktur des Servers sauber halten. Der Server ist dafür verantwortlich, dass keine Leichen vorheriger Deployments übrig bleiben. Zudem kann so zunächst einfach in eine Test-Umgebung deployt werden, bevor die WAR-Datei dann nach erfolgreichem Abschluss der Tests ins Produktions-System deployt wird. In geclusterten Umgebungen übernimmt u.U. das Cluster selbst die Propagierung deployter WAR-Dateien an alle weiteren beteiligten Knoten.
Eine WAR-Datei ist völlig unabhängig vom Container. Container-spezifische Ergänzungen oder Erweiterungen für eine Anwendung (bspw. die Definition des Sicherheits-Handlings) müssen außerhalb des Web-Anwendungs-Verzeichnisses vorgenommen werden. Somit könnte eine Entwicklerin lokal mit einem anderen Container arbeiten, als auf dem Produktiv-System zum Einsatz kommt. Lediglich die Versionen der unterstützten JSP- und Servlet-Spezifikationen müssen übereinstimmen. Aber Vorsicht: Es empfiehlt sich immer, wenigstens die Test-Umgebung und die Produktiv-Umgebung weitestgehend gleich zu halten, will man beim Live-Gehen später nicht unangenehme Überraschungen erleben. Hat man keine spezielle Test-Umgebung, so sollte man unbedingt eine saubere Versionierung der war-Dateien vornehmen, um ggf. schnell wieder auf eine alte stabile Version zurückschalten zu können!

Zum SeitenanfangZum Seitenanfang


www.jsptutorial.org
© 2005, 2006, 2007