<jsptutorial />

JSP-Standardaktionen


Was sind Aktionen und wozu dienen sie

Aktionen, häufig auch Tags genannt1, sind spezielle XML-ähnliche Elemente zur Erzeugung und Bearbeitung von Objekten zur Steuerung der Verarbeitung des Contents. Aktionen können dabei zugekauft oder selbstentwickelt sein, sie können Bestandteil der Standard Tag Library (s. dazu das eigene Kapitel in diesem Tutorial) sein oder sie gehören zu dem von der Spezifikation festgeschriebenen Set von vom Container verpflichtend zur Verfügung zu stellenden Standard-Aktionen.
Was für Tags gibt es nun? Beispiele umfassen Tags, die die üblichen Steuerungskonstrukte wie "if", "for", "try/catch" ohne Skriptlets verfügbar machen, die der Formatierung und Internationalisierung dienen oder die Fehlerausgaben formatieren. Aber es sind im Prinzip auch beliebige andere Tags denkbar. Beispielsweise komplett formatierte Grafiken oder Reports. Darüber hinaus gibt es auch (häufig kommerzielle) Tags, um vom Desktop her geläufige Controls wie bspw. Ausklappmenüs auch im Web zugänglich zu machen.
Die in der JSP-Spezifikation sogenannten Standardaktionen sind neben den drei schon im vorigen Kapitel kennen gelernten Tags auch bspw. solche zum Weiterleiten der Requestbearbeitung oder zur Inkludierung von weiterem Content. Die volle Spezifikation der Standardaktionen kann in der JSP-Spezifikation nachgelesen werden (Kapitel 5). Alle - nicht gerade wenigen - Tags, die lediglich dazu dienen, das Java-Plugin für Applets einzubinden, werden hier bewusst weggelassen. Im (extrem seltenen) Einzelfall mögen Applets ihre Berechtigung haben, in aller Regel aber sind sie nicht notwendig und aufgrund der zahlreichen Probleme mit den unterschiedlichen Browsern wirklich nicht empfehlenswert. Vielleicht fügen wir später ein eigenes Kapitel dafür ins Tutorial ein, derzeit ist das aber nicht geplant und eher auch unwahrscheinlich.
Dafür spielen Custom Tags, also die selbstentwickelten bzw. zugekauften Tags, eine wesentliche Rolle in der Entwicklung der JSPs. Zwar haben die Java Standard Tag Library und teilweise auch die Expression Language einige Tags überflüssig gemacht, aber es gibt dennoch genug Gründe, in Projekten eigene Tags zu schreiben. Wir widmen uns den Custom Tags später in einem eigenen Kapitel.
Tags werden immer in sogenannten Tag-Libraries zusammengefasst und zu jeder Library gehört ein eigener XML-Deployment-Deskriptor. Will man diese Tags in JSPs nutzen, so muss die passende Library vor der ersten Verwendung in der JSP, idealerweise am Kopf der JSP-Datei, eingebunden werden. Ausgenommen hiervon sind lediglich die Standardaktionen, da diese von der JSP-Spezifikation beschrieben sind und von jedem Standard-konformen Container zur Verfügung gestellt werden müssen. Diese stehen somit immer ohne jedwede sonstigen Vorbereitungen zur Verfügung.

Zum SeitenanfangZum Seitenanfang

Syntax von Tags

Wie schon erwähnt, ist die Syntax ähnlich der Syntax der XML. Ein Tag muss z.B. im Gegensatz zum klassischen HTML immer geschlossen werden. Prinzipiell sieht die Syntax also wie folgt aus:

<pre:aktion attribut1="wert1" attribut2="wert2"...>
Möglicher Body des Tags.
</pre:aktion>

Üblicherweise findet sich im Body normaler Template-Text. Also bei der wohl geläufigsten Verwendung gemischter HTML und JSP-Code. Es kann aber natürlich auch spezielle Tags geben, die nur innerhalb dieser Eltern-Tags vorkommen dürfen. Zudem gibt es selbstverständlich auch Tags, die gar keinen Body enthalten. Wie bei XML kann man diese auch einfacher schreiben:

<pre:aktion attribut1="wert1" attribut2="wert2"... />

Zu beachten ist hier der Slash vor dem schließenden Größer-Zeichen, dem Tag-Ende.
"pre" steht im Übrigen für ein Prefix, das am Kopf der JSP-Datei definiert wird. Im Falle der Standardaktionen ist dieses Prefix "jsp", auch für die Standard Tag Library gibt es vorgeschlagenen Präfixe, an die man sich auch halten sollte, damit neue Entwickler direkt erkennen, dass es sich um JST-Tags handelt. Bei allen anderen Tags kann man sich beliebige Präfixe ausdenken, die im eigenen Interesse allerdings möglichst kurz und doch prägnant sein sollten.
Im folgenden ein kleines Beispiel mit Tags aus der Java Standard Tag Library. Das Beispiel enthält aber noch keine Standardaktionen.

<%@ page import="java.util.*" %>

<%--
     Make the JSTL-core and the JSTL-fmt taglibs available
     within this page. JSTL is the Java Standard Tag Library,
     which defines a set of commonly used elements
     The prefix to be used for core-tags is "c"
     The prefix to be used for fmt-tags is "fmt"
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<html>
<head><title>JSP Tutorial - small tag example</title></head>
<body bgcolor="#FFFFFF">

<%--
     The following is a typical tag with an opening tag.
     "${not empty request.bean.value}" is the value of the
     attribute test and is an example for an
     expression language expression.
     The tag checks whether a bean named "bean" with a
     property named "value" exists within the "request"-scope
--%>
<c:if test="${not empty request.bean.value}">

   <div span style="font-family:sans-serif">
   So here could go some content that should only be seen
   if the bean with the name "bean" is present in the
   request scope and its attribute "value" exists.
   
   You will not see anything, if executing this example since
   the bean which existence was tested against does not exist
   in the request-Scope. 
   
   Sp only the date will be printed with the command below.
   </div>

</c:if>
<%-- and finally the tag body was ended using a closing tag   --%>

<%--
     Use a tag of the format library within the JSTL
     to format the current date and time in the
     standard German way.
--%>

<div span style="margin:2cm; font-family:sans-serif">
<p>Without the bean in the request scope only the current date and 
time on the server gets printed, formatted in the standard German way:</p>
<p><fmt:formatDate value="<%= new Date() %>" pattern="dd.MM.yyyy HH:mm:ss" /></p>
</div>
</body>
</html>

Code im Extrafenster ausführen

Zum SeitenanfangZum Seitenanfang

Standardaktionen

Im folgenden stellen wir kurz alle Standard-Aktionen vor, die nicht mit dem Applet-Plugin zu tun haben und die nicht bereits im Beans-Kapitel vorgestellt wurden.

<jsp:include>

Bereits bei der Vorstellung der Direktiven wurde eine Möglichkeit vorgestellt, eine Seite modular aufzubauen und Teile des Codes, der idealerweise häufiger verwandt wird (denkbar ist z.B. ein Standard-Footer auf allen Seiten einer Firmen-Präsentation), auszulagern.
Die Standard-Aktion bietet dazu eine Alternative.2 Der wesentliche Unterschied gegenüber der Page-Direktive include ist die Art der Inklusion. Während bei der Page-Direktive der Inhalt der angegebenen Datei in den JSP-Code vor der Übersetzung eingefügt wird, wird bei der <jsp:include>-Aktion der von einer Seite zurückgegebene Code eingefügt. D.h. aber auch, dass bspw. bei einer JSP-Seite diese zunächst ausgeführt wird und der generierte Code an der Stelle der Aktion eingefügt wird.
Dies hat ein paar sehr feine Implikationen, und SUN reitet bei den Prüfungen zum Sun Certified Web Component Developer auf diesen Unterschieden rum. Daher werden wir dieses Thema später detaillierter im Kapitel "Templates und Inklusion" behandeln.

<jsp:forward>

Mittels dieser Aktion ist es möglich, aus einer JSP heraus die Bearbeitung wieder zu unterbrechen und zu einer anderen Seite weiterzuleiten, die stattdessen die Bearbeitung der Http-Anfrage vornehemen soll. Es gibt lediglich das page-Attribut. Dieses legt fest, an welche Seite die Ausführung abgegeben werden soll. Die Seite ist dabei relativ zur derzeitig prozessierten Seite.
Benötigt die neue Seite zusätzliche Informationen zur Bearbeitung, so können diese mit einem <jsp:param>-Tag (s. nächster Abschnitt) mitgegeben werden. Werden keine Parameter benötigt, so darf der Tag keinerlei Body enthalten, d.h. der schließende Tag muss direkt und ohne Leerzeichen oder Leerzeilen auf den öffnenden Tag folgen. Oder der öffnende Tag wird mit "/>" anstelle des normalen ">" abgeschlossen. Solche Tags nennt man Empty Tags.
Soweit ist dieser Tag wahrlich recht einfach. Doch bei der Nutzung des Tags ist dennoch ein klein wenig Vorsicht angebracht. Denn er kann nur solange verwendet werden, wie der vom Container verwaltete Puffer für den Content noch nicht (auch nicht teilweise) weggeschrieben wurde. Was bedeutet das?
Wie schon bei den Page-Direktiven beschrieben, wird der Content zunächst stets in einen Puffer geschrieben. Dieser hat aber naturgemäß eine begrenzte Größe.3 Ist diese überschritten, oder wird explizit die Methode flush() aufgerufen, so wird der Inhalt des Puffers schon an den Client zurückgesendet. Die Verarbeitung geht danach wie gehabt weiter, mit einem nun erneut leeren Puffer.
Sobald aber bereits Teile der Antwort an den Client (also i.a.R. dem Browser des Nutzers) gesandt worden sind, kann nun nicht auf einmal die Verarbeitung an eine andere Seite umgeleitet werden. Würde man dies erlauben, käme es zu einem heillosen Durcheinander des generierten Codes. Und auch ein Redirect (s. übernächster Absatz) ist nicht mehr möglich, da dem Client bereits der Statuscode der Seite (bei normaler Verarbeitung ist dies der Code 200) zugesandt wurde. Die Header, die für einen Redirect notwendig sind, können nun vom Browser nicht mehr interpretiert werden, ein Redirect ist also auch nicht mehr möglich.
Bei Servlets gibt es zwei Möglichkeiten, die Ausführung abzugeben. Es kann ein Redirect ausgelöst werden, oder - wie hier in JSPs - zu einem anderen Servlet bzw. einer JSP-Seite weitergeleitet werden. Der Unterschied ist nicht ganz unbedeutend:
Ein Redirect bedeutet, dass eine HTTP-Antwort zurück an den Browser geschickt wird, die diesen auffordert, die ursprünglich angeforderte Seite nun von einem anderen Ort zu laden. Dazu werden ein passender Statuscode und geeignete HTTP-Header gesendet, die dem Browser die neue Adresse mitteilen. Dies klingt vielleicht ungewöhnlich, wenn man sich mit HTTP-Request noch nicht so vertraut gemacht hat, ist aber ein üblicher Vorgang. Und die Nutzerin bekommt davon glücklicherweise normalerweise auch nichts mit (sodenn sein Browser HTTP-Redirects unterstützt, was aber nahezu alle Browser machen). Der Vorteil ist, dass anschließend die Adresse der neuen Seite im Adresseingabefeld des Browsers angezeigt wird. Der Nachteil wiederum ist, dass jedwede Information, die im HttpServletRequest-Objekt vorliegt, auf der Zielseite nicht mehr zur Verfügung steht. Dies ist der übliche Nachteil der statuslosen Natur des HTTP-Protokolls. Alle Information, die auf der Zielseite vorhanden sein muss, müsste also nun mittels Parameter der Weiterleitung mitgegeben werden oder aber in der Session gespeichert werden. Letzteres dürfte aber in aller Regel kein gangbarer Weg sein.
Bei einem Forward hingegen bleibt die Ausführung komplett auf der Seite des Servers. Bisher angefallenen Teile der Antwortseite werden verworfen und eine völlig neue Aktion (neues Servlet oder neu JSP) ausgeführt. Damit ist auf der Zielseite noch die komplette Informationsmenge vorhanden, die vor dem Forward schon im HttpServletRequest (bzw. bei JSPs im impliziten request-Objekt) gespeichert war. Der Nachteil ist, dass der Browser davon nichts mitbekommt und die Adresszeile sich nicht ändert.4
In einem Modell, in dem Servlets als FrontController vor JSPs geschaltet werden (s. Architektur-Kapitel), wird zumeist bereits im Servlet auf evtl. Ausnahmesituationen regiert und entsprechend weiter geleitet. Der Tag <jsp:forward> macht also nur in Projekten Sinn, in denen größere Teile der Anwendungs-Logik auch in den JSPs selbst vorgehalten werden.

<jsp:param>

Diversen Standard-Aktionen und Custom-Tags können Parameter mitgegeben werden, die die jeweilige Ausführung beeinflussen. Diese Parameter sind key/value-Paare, die mittels der Pflicht-Attribute name und value angegeben werden.
Dieser Tag ist absolut selbsterklärend und daher soll an dieser Stelle ein kleines Beispiel eines Parameters, der einem <jsp:forward>-Tag mitgegeben wird, reichen:
<jsp:forward page="tutorial.jsp" >
   <jsp:param name="chapter" value="includes" />
</jsp:forward>

<jsp:text>

Dieser Tag kann zwar in allen JSPs verwandt werden, sinnvoll ist der aber nur dort, wo JSPs in der Form von reinen XML-Dokumenten entwickelt werden. Wir werden dem später eigenes Kapitel widmen.
Der Sinn dieses Tags ist, reinen Template-Code zu umschließen. Bei "normalen" JSPs ist die Trennung von Template-Code (also bspw. der HTML-Code, der nicht dynamisch genieriert wird) und JSP-Aktionen bzw. Skriptlets etc. offensichtlich. Dieser Tag ist somit nicht notwendig (wenngleich er verwendet werden kann). In reinen XML-Dokumenten-JSPs hingegen ist dieser Tag notwendig, um Template-Text XML-konform einbinden zu können.

<jsp:element>

Mit diesem Standard-Tag ist es möglich, dynamisch beliebige XML-Tags in das Dokument einzubauen. Dazu hat der Tag ein Attribut name, das den Element-Namen des Tags bezeichnet und mögliche <jsp:attribute>-Werte im Body, die - falls vorhanden - die Attribute des Tags angeben. Dies macht natürlich nur dadurch Sinn, dass sowohl das name-Attribut des <jsp:element>-Tags als auch der Body des <jsp:attribute>-tags dynamisch Laufzeitwerte annehmen können.
Ein Beispiel hilft, dies zu verdeutlichen:
<?xml version="1.0" encoding="ISO-8859-1" ?>

<jsp:element name="meinDynamischerTag">
   <jsp:attribute name="isXml">true</jsp:attribute>
   <jsp:attribute name="isHtml">false</jsp:attribute>
   <jsp:body>There is of course also some body of this tag possible</jsp:body>
</jsp:element>


Das Ergebnis ist folgende Zeile im generierten XML bzw. HTML-Code:
<?xml version="1.0" encoding="ISO-8859-1" ?>

<meinDynamischerTag isHtml="false" isXml="true">
There is of course also some body of this tag possible
</meinDynamischerTag>

Da die JSP, die diese Tags enthält, zum Zeitpunkt der Ausführung natürlich bereits in ein Servlet transformiert wurde, ist es auf diese Weise unmöglich, dynamischen JSP-Code zu erzeugen.

<jsp:attribute>

Wie dieser Tag genutzt wird, haben wir schon im vorherigen Abschnitt kennen gelernt. Auf die gleiche Weise wie dort kann dieser Tag auch bei allen anderen Standard-Aktionen oder bei Custom-Tags zum Setzen von Attribut-Werten genutzt werden.

<jsp:body>

Immer wenn die Standard-Aktion <jsp:attribute> genutzt wird, um Attribute zu einem Tag zu setzen, muss für den Body dieser Tag verwendet werden. Ein Tag, der in seinem Body jsp:attribute>-Elemente enthält, aber kein <jsp:body>-Element, wird behandelt wie ein Tag, der gar keinen Body hat.
Unabhängig davon kann <jsp:body> in allen Standard- oder Custom-Tags zur Angabe des Bodys verwandt werden. Nötig ist dies allerdings lediglich im oben geschilderten Fall. Insofern ist der Tag auch eher weniger bekannt und verbreitet. Gezeigt wurde er bereits im obigen Beispiel zur Standard-Aktion <jsp:element>.
Keine der Standard-Aktionen <jsp:element>, <jsp:attribute> und <jsp:body> ist Bestandteil von SUNs Prüfung zum "Sun Certified Web Component Developer". Auch darin spiegelt sich die geringe praktische Bedeutung des Tags wider.

<jsp:doBody>

Dieser Tag ist mit JSP 2.0 eingeführt worden, um eigene Tags leichter zu ermöglichen. Er darf nur innerhalb sogenannter Tagfiles genutzt werden. Diese sind besondere Seiten, die in JSP 2.0 eingeführt wurden, um auch Nicht-Java-Programmierern (wie bspw. Web-Designern) das Erzeugen von Taglibs zu ermöglichen. Wir besprechen diese Tagfiles noch ausführlich in späteren Kapiteln. Dort wird dann auch dieser Tag genau beschrieben.

<jsp:invoke>

Auch dieser Tag ist mit JSP 2.0 hinzugekommen. Wie der Tag <jsp:doBody> wird er ausführlich im Kapitel zu eigenen Taglibraries besprochen.

Zum SeitenanfangZum Seitenanfang

Standardaktionen für Applets und Beans

Wie schon erwähnt, gibt es weitere Aktionen, die hier nur noch gelistet werden, da wir sie für nicht sonderlich wichtig halten (Applet-Tags) oder schon beschrieben haben (Bean-tags).

Applet-Tags

<jsp:plugin>

Bindet das Java-Plugin zur Nutzung von Java-Applets in die Webseite ein.

<jsp:param> und <jsp:params>

Kann genutzt werden, um Parameter an das Applet zu übergeben.

<jsp:fallback>

Für Browser, die das Plugin nicht unterstützen, bietet dieser Tag die Möglichkeit, einen alternativen Content anzuzeigen.

Bean-Tags

<jsp:useBean>

Mit Hilfe dieses Tags werden JavaBeans für die Nutzung durch die folgenden Tags vorbereitet und initialisiert. Dieser Tag wurde im vorigen Kapitel ausführlich vorgestellt.

<jsp:getProperty>

Um auf die Attribute der Beans (bei diesen Properties genannt) zuzugreifen, wird dieser Tag verwandt. Auch dieser Tag wurde im vorigen Kapitel ausführlich beschrieben.

<jsp:setProperty>

Die letzte der Standard-Aktionen zur Behandlung und Nutzung von JavaBeans ist der Tag <jsp:setProperty>. Dieser dient dem Setzen von Eigenschaften. Er wird bei weitem nicht so häufig verwandt, wie der Tag zum Zugriff auf Eigenschaften. Wie die beiden anderen Tags zum Bean-Handling wurde dieser Tag mit seinen Attributen im vorigen Kapitel vorgestellt.

Zum SeitenanfangZum Seitenanfang

Anmerkungen:

1) Das ist eigentlich ziemlich ungenau. Tags kommen aus der SGML/HTML/XML-Welt und dienen dort der Markierung von Elementen bzw. der Auszeichnung von Teilen der Seite. In JSPs dienen Tags i.a.R. dagegen der Steuerung der Generierung des Contents und der Einfügung von Inhalten. Obwohl vielleicht etwas ungenau, gefällt uns die Bezeichnung Tags allerdings auch besser ;-) (zurück)

2) Es gibt mit dem Tiles-Framework noch eine weitere Alternative, die später in einem eigenen Kapitel vorgestellt wird. Das Tiles-Framework ermöglicht eine vollständige Einteilung einer Web-Präsentation in verschienden Template-Bereiche und ist häufig der include-Aktion oder der include-Direktive vorzuziehen. Dieses JSP Tutorial nutzt zur Einteilung der Seite in seine verschiedenen Bereiche ebenfalls das Tiles-Framework und dient im Kapitel dazu als Beispiel. (zurück)

3) Diese Größe kann - wie im Kapitel zu den Page-Direktiven beschrieben - mittels der Page-Direktive "buffer" frei festgelegt werden. (zurück)

4) Dass sich die Adresszeile nicht ändert, muss aber keineswegs wirklich ein Nachteil sein, ja kann sogar ein Vorteil sein. Denn so besteht nicht die Gefahr, dass eine Seite gebookmarkt wird, der - bspw. nach Ablauf der Session - notwendige Informationen zur Darstellung fehlen. (zurück)


www.jsptutorial.org
© 2005, 2006, 2007