<jsptutorial />

Implizite Objekte


Grundlagen

Im vorigen Kapitel wurde gezeigt, wie man mittels Skiptlets Javacode in JSPs einbetten kann, um so bspw. dynamisch auf Nutzereingaben reagieren zu können. Dazu benötigt man aber über die Möglichkeit, Java zu benutzen, hinaus noch den Zugriff auf Informationen, die die derzeit gültige Session, die Anwendung, den Request oder auch die zu erzeugende Response betreffen. Dazu dienen die impliziten Objekte, auf die man aus Skriptlets heraus zugreifen kann.
Insgesamt stehen neun Objekte zur Verfügung, die in den nächsten Abschnitten detailliert beschrieben werden. Die folgende Übersicht zeigt zunächst einmal die Namen der Objekte und von welchem Typ diese sind. Es lohnt sich, die verfügbaren Methoden dieser Objekte in der API der Java 2 Enterprise Edition anzusehen, da man sie häufig brauchen wird und hier nur die wichtigsten Methoden beschrieben werden. Im Übrigen braucht man Objekte dieser Interfaces/Klassen auch dann häufig, wenn man mit einem FrontController-Ansatz arbeitet.

Name Interface bzw. Klasse
request javax.servlet.http.HttpServletRequest
response javax.servlet.http.HttpServletResponse
session javax.servlet.http.HttpSession
pageContext javax.servlet.jsp.PageContext
application javax.servlet.ServletContext
config javax.servlet.ServletConfig
out javax.servlet.jsp.JspWriter
exception java.lang.Throwable


Wer sich noch nicht mit HTTP beschäftigt hat, sollte sich jetzt kurz dafür Zeit nehmen. Insbesondere die für den Umgang mit Webanwendungen grundlegenden Objekte "request" und "response" und deren Anwendung werden erst deutlich, wenn man die Arbeitsweise von HTTP versteht. Alles Wesentliche steht im Anhang I: HTTP-Grundlagen.

Zum SeitenanfangZum Seitenanfang

Das Objekt request

Der Name sagt es schon: Dieses Objekt, vermutlich das meistgenutzte implizite Objekt, kapselt alle wesentlichen Informationen über die aktuelle Anfrage, den HTTP-Request, des Clients. Das heißt, dass es zu jeder Anfrage auch immer genau ein request-Objekt gibt. Mittels Methoden kann man nun auf Informationen zu den HTTP-Headern, zu den Request-Parametern (GET-Parameter oder Formular-Eingaben), zu Cookies und ein paar weiteren Angaben zugreifen.
Die wichtigsten Methoden sind in der folgenden Übersicht zu finden.

Methode Rückgabewert Kurze Beschreibung
getCookies() Cookie[] Liefert alle Cookies des Nutzers als ein Cookie-Array - das sind immer alle Cookies dieser Domain. Daher ist Vorsicht angebracht, wenn mehrere Anwendungen unter einer Domain laufen, die auf Cookies angewiesen sind.
getHeader(String) String Gibt den benannten Header zurück. Bspw. den Browser mit "user-agent". Dies setzt voraus, dass der Client diesen Header mitsendet.
getHeaders(String) Enumeration Manche Header können mehrfach vorkommen oder per Kommata separiert werden (bspw. "accept-encoding"). Werden mehrere Header verwendet, können diese mittels dieser Methode als Enumeration geholt werden.
getHeaderNames() Enumeration Alle Header-Namen können so in Form einer Enumeration geholt werden, um dann über diese zu iterieren. Gut zum Debugging geeignet.
getMethod() String Gibt die HTTP-Methode (bspw. POST oder GET) zurück.
getQueryString() String Der Anfrage-String des Clients, der in der Adresszeile des Browsers an die URL angehängt wurde, oder der die Anfrage eines mit der GET-Methode abgesandten Formulars enthält.
getRequestedSessionId() String Gibt die Session-ID zurück, die der Client anfrägt. In aller Regel wird man aber wohl eher die Methode "getId()" des impliziten "session"-Objekts nutzen.
getRequestURL() String Die URL die für die Anfrage genutzt wurde. Etwaige Anfrage-Parameter, die an die URL im Browser angehängt wurden, müssen aber mit der oben beschriebenen Methode "getQueryString()" geholt werden.
getSession() HttpSession Gibt die Session des Nutzers zurück. In JSPs wird man eher das implizite session-Objekt nutzen, aber in Servlets muss man diese Methode des HttpRequest-Objekts nutzen, um die Nutzer-Session zu bekommen.
Außerdem finden sich v.a. Methoden zur Authentifizierung. Es lohnt sich, mit den verschiedenen gebotenen Möglichkeiten ein wenig herumzuspielen.


Erwähnenswert ist der Unterschied zwischen getHeader() und getHeaders(). Das HTTP-Protokoll sieht für ein paar Header die Möglichkeit vor, bei mehreren Informationen diese entweder durch Kommata getrennt mitzugeben oder den benannten Header mehrfach mit den jeweiligen Einzelwerten zu verwenden. Dies ist bspw. für den Accept-Header, der die Formate angibt, die der Browser versteht oder für die Sprach-Präferenz (Accept-Language-Header) der Fall. Die Methode getHeaders() liefert mehrere Werte in der Enumeration nur dann, wenn der gleich benannte Header mehrfach mit anderen Werten benutzt wurde. Ansonsten liefert "nextElement()" einfach die komplette durch Kommata getrennte Liste. Gelinde gesagt äußerst unglücklich gelöst. Es wäre sicher vernünftiger gewesen, auch bei durch Kommata getrennten Listen, die einzelnen Werte mittels der Enumeration getrennt zugänglich zu machen. Zum Glück hat man letztlich doch fast nie mit diesem Problem zu tun.
Zum Schluss noch ein kleines Beispiel für den Einsatz von ein paar der beschriebenen Methoden:

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

<html>
<head><title>JSP Tutorial - implicit objects: "request"</title></head>
<body style="font-family: Helvetica, sans-serif;">
<h3>"request"</h3>
<%--
   first iterate over all headers the client provided
--%>
<%
   Enumeration enumeration = request.getHeaderNames();
%>
<p>request headers:
<table border="0" cellspacing="0" 
   cellspacing="1" bgcolor="#000000" style="margin-top:10px; margin-bottom:10px;">
<tr><td>
   <table border="0" bgcolor="#ffffff">
   <%
      while (enumeration.hasMoreElements()) {
         String key = (String)enumeration.nextElement();
   %>
   <tr>
   <td><b><%= key %></b></td><td> </td><td><%= request.getHeader(key) %></td>
   </tr>
   <%
      }
   %>
   </table>
</td></tr>
</table>
</p>
<%--
   then iterate over all submitted parameters, if any
   if none are present, just ignore the following section
--%>
<%
   if (request.getParameterNames().hasMoreElements()) { 
      enumeration = request.getParameterNames();
%>
<p>request parameters:
<table border="0" cellspacing="0" 
   cellspacing="1" bgcolor="#000000" style="margin-top:10px; margin-bottom: 10px;">
<tr><td>
   <table border="0" bgcolor="#ffffff">
   <%
      while (enumeration.hasMoreElements()) {
         String key = (String)enumeration.nextElement();
   %>
   <tr>
   <td><b><%= key %></b></td><td> </td><td><%= request.getParameter(key) %></td>
   </tr>
   <%
      }
   %>
   </table>
</td></tr>
</table>
</p>
<%
   }
%>
<%--
   finally show some other informations the request-object provides
--%>
<p>Some additional information:<br>
<table border="0" cellspacing="0" 
   cellspacing="1" bgcolor="#000000" style="margin-top:10px; margin-bottom: 10px;">
<tr><td>
<table border="0" bgcolor="#ffffff" style="margin:0px;">
<tr>
<td><b>Preferred Locale</b></td><td> </td><td><%= request.getLocale() %></td>
</tr>
<tr>
<td><b>Your host</b></td><td> </td><td><%= request.getRemoteAddr() %></td>
</tr>
<tr>
<td><b>Your query</b></td><td> </td><td><%= request.getQueryString() %></td>
</tr>
</table>
</td></tr>
</table>
</p>
<%--
The following input will appear as "Your result" after submitting
--%>
Your input:<br>
<form action = "/examples/code_implicit_request_object.jsp" method="GET">
<input type="hidden" name="hiddenParm" value="hiddenValue">
<input type="text" name="freistil">
<input type="submit" name="form_submit" value="ok">
</form>
</body>
</html>

Code im Extrafenster ausführen

Zum SeitenanfangZum Seitenanfang

Das Objekt response

Das response-Objekt ist das genaue Gegenstück zum request-Objekt. Es enthält alle Informationen für die HTTP-Response und wird vor allem genutzt, um den Content-Type festzulegen und Response-Header oder Cookies zu setzen.
Auch hier wieder eine Übersicht der wichtigsten Methoden:

Methode Rückgabewert Kurze Beschreibung
addCookie(Cookie cookie) void Fügt den übergebenen Cookie der Response hinzu. Ob der Client diesen akzeptiert hat, lässt sich natürlich erst beim nächsten Request feststellen.
addDateHeader(String name, long date) void Formatiert einen Datums-String entsprechend der HTTP-Spezifikation und fügt diesen unter dem angegebenen Namen den Http-Headern hinzu
addHeader(String name, String value) void Fügt einen Header unter dem angegebenen Namen hinzu
addIntHeader(String name, int value) void Unter dem angegebenen Header-Namen wird ein Ganzzahl-Wert hinzugefügt
encodeURL(String url)String Bereinigt die URL von Sonderzeichen, Leerzeichen und dergleichen in einer URL nicht zugelassenen Zeichen und gibt diesen bereinigten String zurück.
encodeRedirectURL(String url)String Bereinigt die URL von Sonderzeichen, Leerzeichen und dergleichen in einer URL nicht zugelassenen Zeichen und gibt diesen bereinigten String zurück. Jede Redirect-Adresse sollte zuvor durch diese Methode gegangen sein
sendError(String sc) void Löscht den Puffer, setzt den Fehlercode und sendet die Response ab.
sendError(String sc, String message) void Löscht den Puffer, setzt den Fehlercode und sendet die Response ab. Zudem wird als Erklärung für den Client der angegebene Text mitgegeben.
setDateHeader(String name, long date) void Wie oben bei addHeader(name, date), nur dass hier ein schon zuvor gesetzter Wert überschrieben wird
setHeader(String name, Strng value) void Setzt einen Header unter dem Namen mit dem angegebenen Wert. Evtl. zuvor gesetzte header mit diesem Namen werden überschrieben
setIntHeader(String name, int value) void Der int-Wert wird unter diesem Namen in den Http-Headern gesetzt. Ggf. zuvor gesetzte header dieses Namens werden überschrieben
setStatus(int sc) void Setzt den Statuscode für die Antwort. In JSPs eine untypische Aktion, in Servlets aber durchaus geläufig, wenn die Bearbeitung vom Normalfall abweicht. Im Fehlerfall hingegen kommt eher die Methode setError zur Anwendung


Hervorzuheben sind hier v.a. die Methode setContentType(). Will man bspw. mit JSPs XML-Code erzeugen, so muss der Content-Type mittels response.setContentType("text/xml") auf "text/xml" gesetzt werden.
Die Bedeutung und Nutzung der Methoden encodeURL() und encodeRedirectURL() werden im Kapitel zum Session-Handling, Cookies und URL-Rewriting detailliert vorgestellt.
Die setIntHeader() bzw. setDateHeader() und die entsprechenden addIntHeader() bzw. addDateHeader dienen der Vereinfachung. HTTP selbst kennt keine Zahlen oder Datumsformate, sondern alle Header sind letztlich rein textuelle Informationen, die bestimmten Formatierungsregeln folgen. Die genannten Methoden nun nehmen einem die Aufgabe ab, eine HTTP-gerechte Formatierung der als Zahl- oder Datumswerte vorliegenden Informationen selbst vornehmen zu müssen.
Für die sendError(int sc)- bzw. setStatus(int sc)-Methoden befinden sich im HttpServletResponse-Interface Konstanten mit allen möglichen HTTP-Statuscodes. Da diese sehr sprechend sind, sollte man immer die Konstanten direkten int-Werten vorziehen. Auch sollte man sich den Unterschied zwischen "setStatus(int sc)" und "sendError(int sc)" in Bezug auf den Puffer (s. dazu das Kapitel Die Syntax von JSPs) klar machen. Da "sendError(int sc)" im Fehlerfall genutzt wird (und dann setStatus vorgezogen werden sollte), wird hier immer der Puffer gelöscht und der response danach abgesandt. Danach sollte man auf keinen Fall mehr in den Puffer schreiben. "setStatus(int sc)" hingegen lässt den Puffer unverändert. Diese Methode kommt lediglich bei Abweichungen vom Normalfall zum Tragen, sie bedeutet aber keinen Fehlerfall. Insofern kann danach die Verarbeitung auch noch weiter gehen (bspw. könnte es Sinn machen, noch weitere Header zu setzen - manche Statuscodes verlangen dies sogar geradezu). Genaueres dazu später im Kapitel zum Fehler- und Ausnahmenbehandlung.

Zum SeitenanfangZum Seitenanfang

Das Objekt session

Sessions werden noch ausführlich in einem eigenen Kapitel beschrieben werden. Hier sollen nur kurz die wesentlichen Grundlagen zum Verständnis des impliziten Objekts session aufgeführt werden.
Das session-Objekt hat u.a. die folgenden häufig genutzten Methoden:

Methode Rückgabewert Kurze Beschreibung
getAttribute(String name) Object Die wohl meist genutzte Methode des session-Objekts. Mit dieser kann man Objekte aus der Session auslesen, die zu einem beliebigen anderen Zeitpunkt der Session hinzugefügt wurden.
getAttributeNames() Enumeration Eigentlich nur sinnvoll für Rahmenframeworks oder zum Debuggen. Hiermit holt man sich eine Enumeration aller Attributnamen. Über diese könnte man nun iterieren, um eine Liste aller Attribute der Session auszugeben.
getCreationTime() long Wenn man wissen will, wann die Session erzeugt wurde, kann man diese Methode nutzen.
getId() String Gibt die eindeutige ID der Session zurück.
getMaxInactiveInterval() int Ermittelt die Zeit, die höchstens vergehen darf, bevor die Session verworfen wird.
getServletContext() ServletContext Der ServletContext, dem diese Session angehört, kann hier abgerufen werden. Damit ist auch klar, dass eine Session immer an eine deployte Applikation gebunden ist und sich nicht über mehrere Anwendungen erstrecken kann.
invalidate() void Beendet diese Session. Eine sehr wichtige Methode! Jede Session kostet Speicherplatz. Sind sehr viele Session gleichzeitig geöffnet, so kann dies bei umfangreicheren Objekten in der Session schnell zu Speicherproblemen führen. invalidate() kann helfen, indem man nicht mehr genutzte Session mittels eines Logout-Vorgangs beendet.
removeAttribut(String name) void Entfernt ein zuvor hinzugefügtes Objekt wieder aus der Session.
setAttribute(String name, Object object) void Legt ein Objekt in der Session ab. Zusammen mit getAttribute() die wichtigste Methode der Session.
setMaxInactiveInterval(int interval) void Legt die Zeit in Sekunden fest, bevor eine Session verworfen wird. Das heißt nur, dass danach nicht mehr erfolgreich auf die Session zugegriffen werden kann. Wann die Session wirklich freigegeben wird, ist eine Frage der Optimierungsstrategie des Containers und stark herstellerabhängig.


Das HTTP-Protokoll ist ein sogenanntes zustandloses Protokoll. Das heißt, dass der Server keine Daten über den Nutzer vorrätig hält und diesen sozusagen unmittelbar nach erfolgreicher Absendung seiner Antwort auf die Anfrage des Clients vergisst. Dies ist natürlich für die meisten Web-Anwendungen völlig inakzeptabel. Daher wurden Möglichkeiten gefunden, diese Beschränkung des HTTP-Protokolls zu umgehen und sogenannte Sessions zu ermöglichen. Sessions bilden also einen kompletten Besuch einer Nutzerin auf einer Website über alle von ihr aufgesuchten Seiten ab. Somit können bspw. Login-Informationen gespeichert werden, und die Nutzerin muss sich nicht auf jeder Seite stets erneut einloggen.
Das JSP/Servlet-Modell bietet eine umfassende Unterstützung von Sessions einer Benutzerin über eine Abfolge von Seiten. Dafür stellt der Servlet-Container das session-Objekt bereit, das vor allem zur Aufnahme von Session-relevanten Informationen genutzt wird. Beliebige Objekte kann man mittels setAttribute() speichern und mittels getAttribute() wieder abrufen. Der genaue Mechanismus und die Auswirkungen eines zu extensiven Gebrauchs dieser Möglichkeit werden im Kapitel "Session-Handling, Cookies und URL-Rewriting" beschrieben.
Wenn das Attribut session der Page-Direktive (s. dazu das Kapitel Die Syntax von JSPs) auf "false" gesetzt ist, steht das session-Objekt nicht zur Verfügung, da in dem Fall keine Session innerhalb der Seite genutzt wird.

Zum SeitenanfangZum Seitenanfang

Das Objekt pageContext

Das pageContext-Objekt bietet Zugriff auf Informationen, die die aktuelle JSP-Seite betreffen. Es bietet vor allem einige Convenience-Methoden1, die den bequemen Zugriff auf Objekte in den verschiedenen Gültigkeitsbereichen erlauben. Dies betrifft hauptsächlich Beans, wie sie bei den fortgeschritteneren Methoden der Webentwicklung mit FrontController und JSPs verwandt werden. Das Konzept der Gültigkeitsbereiche (engl. scope) wird im Kapitel "Beans in JSPs" ausführlich erläutert. Ansonsten wird das Objekt vor allem bei der Generierung des aus der JSP erzeugten Servlets genutzt, ist insofern also für den JSP-Entwickler zumeist weniger wichtig.

Zum SeitenanfangZum Seitenanfang

Das Objekt application

Das application-Objekt enthält wenig Methoden, die man von einer JSP aus nutzen würde. Am ehesten sind noch die log-Methoden sinnvoll, die zur Ausgabe von Log-Meldungen in eine vom Container vorgegebene Logging-Datei dienen.
Von einem Servlet aus dürften auch noch die Methoden getRessource() oder getRessourceAsStream() Sinn machen, die zum Zugriff auf Ressourcen, wie bspw. binärer Dateien, dienen. Man kann zwar auch von JSPs aus binären Content an den Client zurück liefern, doch ist das eine Aufgabe, die - zu Recht - nahezu immer von Servlets wahrgenommen wird. Insofern dürfte das application-Objekt nur selten genutzt werden.
Es spielt allerdings eine Rolle im Zusammenhang mit den verschiedenen Gültigkeitsbereichen, wie im Kapitel "Beans in JSPs" beschrieben.

Zum SeitenanfangZum Seitenanfang

Das Objekt config

Das config-Objekt ist vom Typ javax.servlet.ServletConfig. Es dient vor allem dazu, auf Initialisierungs-Parameter zuzugreifen. Es ist in der Praxis absolut unbedeutend. Initialisierungs-Parameter werden nahezu ausschließlich für Servlets verwandt. Dennoch ist es auch für JSPs möglich, solche Parameter in der Datei web.xml anzulegen. Die wesentliche Methoden sind daher die getInitParameter()-Methode, die einen definierten und benannten Initialisierungs-Parameter zurückgibt und die getInitParameterNames()-Methode, die eine Enumeration mit allen Namen der definierten Initialisierungs-Parameter zurückgibt.
Ein Beispiel für einen definierten Parameter in einer web.xml-Datei:

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns= ... >

   <!-- ... -->

   <servlet>
      <servlet-name>ExampleConfigJsp</servlet-name>
      <jsp-file>/examples/code_implicit_config_object.jsp</jsp-file>
      <init-param>
         <param-name>sampleParm</param-name>
         <param-value>Just a sample value.</param-value>
      </init-param>
   </servlet>
   
   <servlet-mapping>
      <servlet-name>ExampleConfigJsp</servlet-name>
      <url-pattern>/examples/code_implicit_config_object.jsp</url-pattern>
   </servlet-mapping>
   
   <!-- ... -->

</web-app>

Und so kann man diesen in einer JSP auslesen:
<html>
<head><title>JSP Tutorial - implicit objects: "config"</title></head>
<body style="font-family: Helvetica, sans-serif;">
<h3>"config"</h3>
<p>init-parameter:
<table border="0" cellspacing="0" 
   cellspacing="1" bgcolor="#000000" style="margin-top:10px; margin-bottom:10px;">
<tr><td>
   <table border="0" bgcolor="#ffffff">
   <tr>
   <td><b>sampleParm</b></td><td> </td>
   <td><%= config.getInitParameter("sampleParm") %></td>
   </tr>
   </table>
</td></tr>
</table>
</p>
</body>
</html>

Code im Extrafenster ausführen

Zum SeitenanfangZum Seitenanfang

Das Objekt out

Auch das out-Objekt wird man vergleichsweise selten brauchen. Dieses repräsentiert den in der JSP genutzten JspWriter. Will man innerhalb von Skriptlets in den Ausgaben erzeugen, so stehen einem diverse print()- und println()-Methoden zur Verfügung. Die Ausgabe wird dabei zunächst stets gepuffert, um ggf. bei Fehlern den Puffer löschen zu können und bspw. spezielle Ausgaben für den Fehlerfall ausgeben zu können. Ein Forwarding oder ein Redirect ist nur möglich, solange der Puffer oder Teile des Puffers noch nicht mittels flush() tatsächlich weggeschrieben wurde.
Insofern sind neben den diversen print()-Methoden noch die Methoden clear(), bzw. clearBuffer() und flush() wichtig. Letztere schreibt den Pufferinhalt in den Ausgabestrom, wohingegen die beiden ersten den Puffer löschen. Ist bereits ein Teil des Puffers geflusht worden, so wirft die erste Methode eine IOException,während clearBuffer() einfach den gegenwärtigen Pufferinhalt löscht. Die Größe des Puffers setzt man mittels dem Attribut buffer der Page-Direktive.

Zum SeitenanfangZum Seitenanfang

Das Objekt exception

Dieses Objekt steht nur auf speziellen Fehlerseiten zur Verfügung. Fehlerseiten sind all die Seiten, bei denen das Attribut isErrorPage der "page"-Direktive auf "true" gesetzt ist.
Diese Seiten dienen dazu, spezielle Antwortseiten für diverse mögliche Fehlerfälle bereitzustellen. Welche Seite aufgerufen wird, bestimmt sich entweder aus dem errorPage-Attribut der Page-Direktive oder aus der Konfiguration, die im Deployment-Deskriptor web.xml festgelegt wurde.
Im Falle eines Fehlers wird dann der Request zur passenden Fehler-Seite weitergeleitet und dort kann mittels des exception-Objekts auf die Informationen der Exception zugegriffen werden, die zuvor aufgetreten ist. So kann man für die Nutzerin der Seite klare Fehlermeldungen generieren und erspart ihr den ansonsten üblichen Stacktrace. Genaueres zur Fehlerbehandlung und welche Konfigurationen man dazu im Deployment-Deskriptor vornehmen kann, findet sich im Kapitel Fehler- und Ausnahmenbehandlung.
Folgende Methoden des exception-Objekts stehen auf einer Fehlerseite zur Verfügung:

Methode Rückgabewert Kurze Beschreibung
getRequestURI() String Gibt den Request-URI des abgesetzten Requests zurück. Wichtig, um festzustellen, wo der Fehler auftrat.
getServletName() String Eine nur mäßig wichtige Methode. Der Servlet-Name ist im Falle einer JSP meist unschön azuzeigen und u.U. auch zur Auswertung nicht zu gebrauchen, da er auf jedem Fall vom Container ggf. aber zudem sogar vom Zustand zur Zeit der Transformation der JSp in ein Servlet abhängt.
getStatusCode() int Wichtige Methode, um den HTTP-Statuscode zu ermitteln. Sowohl zur Anzeige an die Nutzerin, als auch zur flexiblen Reaktion auf diesen Code gut brauchbar.
getThrowable() Throwable Liefert den Fehler, der dafür verantwortlich ist, dass die Fehlerseite angezeigt wird. Damit stehen auch alle Methoden dieses Objekts der JSP zur Verfügung.

Zum SeitenanfangZum Seitenanfang

Anmerkungen:

1) So werden Hilfsmethoden bezeichnet, die einem eine Abfolge von ansonsten selbst zu programmierenden Schritten abnehmen (zurück)


www.jsptutorial.org
© 2005, 2006, 2007