Beispiel: JSP-Grundlagen
Inhalt:
Beispiel 1: JSP-Grundlagen
Beispiel 2: Controller-Servlet
Beispiel 3: Tag Libraries
Beispiel 4: Custom Tag Libraries
Diverse JSP-Beispiele. Alle diese Beispiele arbeiten völlig ohne EJB-Zugriff.
Deshalb wird als Projekttyp hier immer ein "Dynamic Web Project" verwendet.
Beim Anlegen des Projekts ist wichtig dass wir jeweils die Checkbox "Add project to an EAR"
zurücksetzen.
In Schritt 2 des Projekt-Erstellens müssen wir sicherstellen dass der XDoclet-Builder nicht aktiviert ist.
In Schritt 3 können wir alle Einstellungen bei den Default-Werten belassen.
Der Export und Re-Import des Projekts erfolgt diesmal nicht als "EAR file" sondern als
"WAR file", ansonsten ist das Vorgehen identisch. Beim Import ist zu beachten dass
das Projekt wiederum nicht zu einer Enterprise Application zugefügt wird.
In Beispiel 3 verwenden wir TagLibraries, deren JAR-Dateien stecken im Unterverzeichnis "WebContent/WEB-INF/lib".
Beim Re-Import müssen wir beachten dass die JARs nicht als Utility-Projekte importiert werden sondern
als JARs in Verzeichnis "WEB-INF/lib" gepackt werden (d.h. in Schritt 2 des Importers keine Haken setzen).
Wichtige Info: Die im folgenden verwendeten Fehlerseiten scheinen bei einem standard-konfigurierten
Internet Exploder nicht zu funktionieren. Wenn man z.B. im Beispiel "JSP1" eine
negative Zahl eingibt dann kommt eventuell diese Anzeige:
Problem hierbei: der JBoss-Server liefert den HTTP-Fehlercode 500 (Server-Fehler) sowie eine Seite mit
der Fehlermeldung zurück. Der Internet Explorer ignoriert diese jedoch und zeigt seine eigene Seite an.
Lösung des ganzen: In den Internetoptionen unter "Erweitert" in der Kategorie "Browsing"
den Haken vor der Option "Kurze HTTP-Fehlermeldungen anzeigen" entfernen.
Beispiel 1: JSP-Grundlagen
Dieses Beispiel enthält drei JSP-seiten ("index.jsp", "input.jsp" und "errorpage.jsp") und die Klassen
de.fhw.swtvertiefung.knauf.jsp1.Historie
und de.fhw.swtvertiefung.knauf.jsp1.Seitenlaengen
.
Es führt die gleiche Logik aus wie das Beispiel der Stateful Session Bean:
Es errechnet Oberfläche und Volumen eines Quaders.
Hier gibt es das Projekt als WAR-Export-Datei: JSP1.war.
Das Beispiel soll folgende Grundelemente einer JSP zeigen:
- Verwenden des Session-Contexts zum Speichern der bisherigen Berechnungen.
- "jsp:useBean"-Tag für das Erzeugen einer Bean im Session-Context, die bei weiteren
Requests wiederverwendet wird.
- "jsp:useBean"-Tag für das Erzeugen einer Java-Klasse im Page Context und automatisches Befüllen aus Request-Parametern.
- Einbinden einer externen Seite mit jsp:include.
- Bei Fehlern an den Eingaben wird automatisch die Errorpage aufgerufen.
Die Anwendung findet sich unter dieser URL: http://localhost:8080/JSP1/index.jsp.
Beispiel 2: Controller-Servlet
In diesem Beispiel wird ein großer Teil der Anwendungslogik in ein Servlet ausgelagert.
Beim Absenden des Formulars ist nicht die JSP-Seite das Ziel, sondern ein Servlet. Dieses
wertet die Request-Parameter aus, erzeugt die Bean mit den aktuellen Request-Werten, berechnet
Volumen und Oberfläche.
Anschließend wird der Request an "index.jsp" weitergeleitet, diese Seite gibt die errechneten
Werte aus.
Hier gibt es das Projekt als WAR-Export-Datei: JSP2.war.
Das Beispiel zeigt dieses:
- Trennung von Anwendungslogik und Anzeigelogik
- Verwaltung der Session über Servlet.
- Weiterleiten des Requests vom Servlet an die JSP.
- Speichern von Objekten im Request, so dass weitere Serverkomponenten sie nutzen können.
- Fehlerbehandlung: im Servlet ausgelöste Exception an Errorpage weitergeben.
Die Anwendung findet sich unter dieser URL: http://localhost:8080/JSP2/index.jsp.
JBoss-Besonderheit: damit Fehler im Servlet an die Seite "errorpage.jsp" weitergeleitet werden muss
folgendes in web.xml eingetragen werden:
<error-page>
<error-code>500</error-code>
<location>/errorpage.jsp</location>
</error-page>
Beispiel 3: Tag Libraries
In diesem Beispiel wird Beispiel 2 weitergeführt: auf der JSP-Seite "index.jsp" soll
kein Stück Javacode mehr zu sehen sein. Stattdessen soll alle dynamische Formatierung von
TagLibs erledigt werden.
Das Beispiel verwendet folgende Taglibraries:
-jakarta-taglibs-request-1.0.1 (Arbeiten mit dem Request, z.B. Ausgabe von Attributen im Request)
-jakarta-taglibs-standard-1.1.2 (Implementation des Java-Standard-Taglib-Standards).
WICHTIG: Scheinbar hat der JBoss hier ein Problem mit einer web.xml gemäß
JavaEE5-Spezifikation, in diesem Fall kann er die Expression-Language-Ausdrücke auf "index.jsp" nicht auswerten.
Deshalb muss ich hier zähneknirschend doch die Version auf "2.4" setzen:
<web-app id="web-app_1" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
Das heißt: sobald wir EL-Ausdrücke in einer JSP verwenden müssen wir leider im Web-Projekt auf "2.4" zurück. Vielleicht
kommt der JBoss 5 ja bald...
Hier gibt es das Projekt als WAR-Export-Datei: JSP3.war.
Nach dem Anlegen des Dynamic Web Projects müssen die zu verwendenden Tag-Libraries importiert werden.
Dazu müssen die Dateien "taglibs-request.jar" aus dem Paket "jakarta-taglibs-request-1.0.1" und
"jstl.jar" aus "jakarta-taglibs-standard-1.1.2" in das Verzeichnis "WebContent\WEB-INF\lib" des
Projekts eingefügt werden. Anschließend "Refresh" im Projekt wählen. Die beiden Libraries
sollten jetzt im Project Explorer unter "Web App Libraries" auftauchen.
Wir müssen außerdem die Deklarationen der Taglibraries (Dateien mit der Endung ".tld") ins Projekt
packen. Dazu aus "taglibs-request.jar" die Datei "taglib.tld" extrahieren, und aus
"standard.jar" die Datei "c.tld". Beide in das Verzeichnis "WebContent\WEB-INF\tags" (das Ziel ist frei wählbar,
die Dateien könnten auch direkt in WEB-INF gelegt werden) packen.
Jetzt müssen wir die Tag Libraries in "web.xml" eintragen:
<jsp-config>
<taglib>
<taglib-uri>http://jakarta.apache.org/taglibs/request-1.0</taglib-uri>
<taglib-location>/WEB-INF/tags/taglib.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/tags/c.tld</taglib-location>
</taglib>
</jsp-config>
Hier werden symbolische Namen für die Taglibs in "WEB-INF\lib" deklariert, unter diesen URI (Unified Resource
Identifier) werden sie später auf den JSP-Seiten angesprochen.
In "index.jsp" werden die Taglibs so eingebunden:
<%@ taglib uri="http://jakarta.apache.org/taglibs/request-1.0" prefix="req" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
Jetzt können die Tags aus den TagLibraries unter den Alias-Namen "req" bzw. "c" verwendet werden.
Wie im vorherigen Beispiel muss außerdem die Errorpage als Handler für den Error Code 500 eingetragen werden !
Die Anwendung findet sich unter dieser URL: http://localhost:8080/JSP3/index.jsp.
Beispiel 4: Custom Tag Libraries
In diesem Beispiel werden die TagLibraries aus Beispiel 3 ersetzt durch handgeschriebene Taglibraries.
Hier gibt es das Projekt als WAR-Export-Datei: JSP4.war.
In diesem Beispiel habe ich die Version der Servlet-Spezifikation ebenfalls auf "2.4" belassen (siehe Erfahrungen
mit der EL aus dem letzten Beispiel).
Die TagLibraries landen im Package de.fhw.swtvertiefung.knauf.jsp4.tags
.
Die Definition der Tags erfolgt in der Datei "WebContent\WEB-INF\tags\jsp4.tld".
Der Rahmen dieser TagLibrary-Deklaration sieht so aus (gemäß JSP-2.0-Spezifikation, die TagLibs aus dem letzten
Beispiel wurden erstellt gemäß JSP-Spezifikation 1.1, dort wurde eine DTD verwendet und einige Tags hießen leicht anders):
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>jsp4</short-name>
<uri>http://www.informatik.fh-wiesbaden.de/~knauf/jsp4</uri>
...
</taglib>
Hier vergebe ich einen Kurznamen der TagLib und eine URI, wobei beide Werte frei vergebbar sind und nur als Vorschläge
dienen, auf der JSP-Seite können sie beliebig überschrieben werden.
Folgende Tags werden verwendet:
IfExistsRequestAttributeTag
: Prüft ob im Request ein Attribut mit einem bestimmten Namen steckt.
Der Name des Attributs wird auf der JSP-Seite per Attribut gesetzt.
Ist dieses Attribut im Request vorhanden wird der JSP-Inhalt ausgeführt. Die Tag-Klasse ist von
javax.servlet.jsp.tagext.BodyTagSupport
abgeleitet da das Tag JSP-Inhalt haben kann.
Wichtige Methoden sind setRequestAttribute
(hier wird das Attribut "requestAttribute" aus der
JSP-Seite heraus gesetzt) und doStartTag
(hier wird gesteuert ob der Inhalt des Tags ausgeführt wird).
In "jsp4.tld" sieht das so aus:
<tag>
<name>ifExistsRequestAttribute</name>
<tag-class>de.fhw.swtvertiefung.knauf.jsp4.tags.IfExistsRequestAttributeTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>requestAttribute</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
Wichtig ist hier die Angabe dass das Tag JSP-Inhalt haben kann (Tag body-content
).
PrintRequestAttributeTag
: Gibt ein Request-Attribut mit einem konfigurierbaren Namen aus. Die Klasse
ist von javax.servlet.jsp.tagext.SimpleTagSupport
abgeleitet, da das Tag keinen Inhalt hat.
Wichtige Methoden sind setRequestAttribute
(hier wird das Attribut "requestAttribute" aus der
JSP-Seite heraus gesetzt) und doTag
(hier wird die Logik des Tags ausgeführt).
In "jsp4.tld" sieht das so aus:
<tag>
<name>printRequestAttribute</name>
<tag-class>de.fhw.swtvertiefung.knauf.jsp4.tags.PrintRequestAttributeTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>requestAttribute</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
Wichtig ist hier die Angabe dass das Tag keinen Inhalt hat.
LoopOverHistorieTag
: Holt aus dem Session-Context ein Attribut mit einem bestimmten Namen vom Typ
de.fhw.swtvertiefung.knauf.jsp4.Historie
und läuft per java.util.Iterator
über die
Elemente der Collection. Das aktuelle Element wird unter einem konfigurierbaren Namen in den PageContext gesteckt.
Der Name des Session-Context-Attributs in dem die Historie steckt wird auf der JSP-Seite per Attribut gesetzt.
Ist dieses Attribut im Request vorhanden wird der JSP-Inhalt für jedes Item ausgeführt. Die Tag-Klasse ist von
javax.servlet.jsp.tagext.BodyTagSupport
abgeleitet da das Tag JSP-Inhalt haben kann.
Wichtige Methoden sind setRequestAttribute
(hier wird das Attribut "requestAttribute" aus der
JSP-Seite heraus gesetzt), doStartTag
(hier wird der Iterator initialisiert und erstmalig der Inhalt des Tags ausgeführt wird),
doAfterBody
(hier wird nach jedem Schleifendurchlauf geprüft ob ein weiterer Durchlauf nötig ist und
falls ja wird das aktuelle Item in den PageContext geklebt), und doEndTag
(hier wird das Attribut für
das aktuelle Item aus dem PageContext entfernt).
In "jsp4.tld" sieht das so aus:
<tag>
<name>loopOverHistorie</name>
<tag-class>de.fhw.swtvertiefung.knauf.jsp4.tags.LoopOverHistorieTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>sessionContextAttribute</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>item</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
Wichtig ist hier die Angabe dass das Tag JSP-Inhalt haben kann.
PrintPageContextSeitenlaengeTag
: Ausgabe einer der Properties "a", "b" oder "c" einer Instanz
von de.fhw.swtvertiefung.knauf.jsp4.Seitenlaengen
. Die Klasse
ist von javax.servlet.jsp.tagext.SimpleTagSupport
abgeleitet, da das Tag keinen Inhalt hat.
Wichtige Methoden sind setPageContextAttribute
(hier wird das Attribut "pageContextAttribute" aus der
JSP-Seite heraus gesetzt), setSeitenlaengeValue
(auszugebende Property von Seitenlaengen
)
und doTag
(hier wird die Logik des Tags ausgeführt).
In "jsp4.tld" sieht das so aus:
<tag>
<name>printPageContextSeitenlaenge</name>
<tag-class>de.fhw.swtvertiefung.knauf.jsp4.tags.PrintPageContextSeitenlaengeTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>pageContextAttribute</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>seitenlaengeValue</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
Wichtig ist hier die Angabe dass das Tag keinen Inhalt hat.
Abschließend muss die XDoclet-Merge-Datei "WebContent\WEB-INF\taglibs.xml" angelegt werden. Sie hat diesen Inhalt:
<jsp-config>
<taglib>
<taglib-uri>http://www.informatik.fh-wiesbaden.de/~knauf/jsp4</taglib-uri>
<taglib-location>/WEB-INF/tags/jsp4.tld</taglib-location>
</taglib>
</jsp-config>
Die Taglib-URI unter der wir die TagLib später in den JSPs ansprechen ist hier identisch mit der in der
TLD-Datei vorgegebenen, dies ist aber nicht verpflichtend.
In "index.jsp" wird die TagLib so eingebunden:
<%@ taglib uri="http://www.informatik.fh-wiesbaden.de/~knauf/jsp4" prefix="jsp4" %>
Jetzt zeigt uns Eclipse auch brav die verfügbaren Tags an:
Die Anwendung findet sich unter dieser URL: http://localhost:8080/JSP4/index.jsp.
Stand 13.12.2006
Historie:
12.12.2006: Erstellt
13.12.2006: Unnötiges Attribut "flush" in "jsp:include" entfernt.