Liebe Leserin, lieber Leser, ich freue mich, dass Sie sich für ein Galileo Computing-Buch entschieden haben. Unsere Einsteigertitel sind besonders für Leser geeignet, die sowohl inhaltlich als auch didaktisch professionell gemachte Fachliteratur schätzen und sich nicht mit »schnellen« Produkten zufrieden geben. Dieses Buch befasst sich mit der aktuellen Version 2.0 der JavaServer Pages. Und es hat sich Einiges getan. Das Buch schafft den Spagat zwischen der Beschreibung bisher üblicher Verfahren und der Behandlung der vollständig neuen Möglichkeiten von 2.0. Die Materie ist komplex; unser Einstieg hilft, JSP 2.0 zu verstehen und effektiv anzuwenden. Das Buch wurde sorgfältig geprüft und die Beispiele getestet. Doch kein noch so gutes EDV-Buch ist ohne Fehler. Lassen Sie uns wissen, wenn etwas nicht so funktioniert, wie Sie es erwarten. Über Anregungen und Lob freuen wir uns natürlich auch! Jetzt wünsche ich viel Freude beim Lesen! Judith Stevens-Lemoine Lektorat Galileo Computing [email protected] www.galileocomputing.de Galileo Press • Gartenstraße 24 • 53229 Bonn Auf einen Blick 1 Java Server Pages im Überblick ............... 17 2 Einrichten einer Entwicklungsumgebung 61 3 Entwicklung dynamischer Webseiten mit JSP 2.0 .............................................. 85 4 Einrichten dynamischer Webanwendungen .................................. 389 5 Erweiterungen und fortgeschrittene Lösungen ................................................. 415 6 Kurzreferenz Java Server Pages 2.0 .......... 479 Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.ddb.de abrufbar. ISBN 3-89842-360-3 © Galileo Press GmbH, Bonn 2004 1. Auflage 2004 Der Name Galileo Press geht auf den italienischen Mathematiker und Philosophen Galileo Galilei (1564–1642) zurück. Er gilt als Gründungsfigur der neuzeitlichen Wissenschaft und wurde berühmt als Verfechter des modernen, heliozentrischen Weltbilds. Legendär ist sein Ausspruch Eppur se muove (Und sie bewegt sich doch). Das Emblem von Galileo Press ist der Jupiter, umkreist von den vier Galileischen Monden. Galilei entdeckte die nach ihm benannten Monde 1610. Das vorliegende Werk ist in all seinen Teilen urheberrechtlich geschützt. Alle Rechte vorbehalten, insbesondere das Recht der Übersetzung, des Vortrags, der Reproduktion, der Vervielfältigung auf fotomechanischem oder anderen Wegen und der Speicherung in elektronischen Medien. Ungeachtet der Sorgfalt, die auf die Erstellung von Text, Abbildungen und Programmen verwendet wurde, können weder Verlag noch Autor, Herausgeber oder Übersetzer für mögliche Fehler und deren Folgen eine juristische Verantwortung oder irgendeine Haftung übernehmen. Die in diesem Werk wiedergegebenen Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. können auch ohne besondere Kennzeichnung Marken sein und als solche den gesetzlichen Bestimmungen unterliegen. Lektorat Judith Stevens-Lemoine Korrektorat Claudia Falk, Dr. Rainer Noske, Bonn Einbandgestaltung Barbara Thoben, Köln Herstellung Iris Warkus Titelbild zefa visual media Satz Typographie & Computer, Krefeld Druck und Bindung Koninklijke Wöhrmann, Zutphen, Niederlande Inhalt Vorwort 15 1 JavaServer Pages im Überblick 19 1.1 Von statischen zu dynamischen Webseiten .......................................... 19 1.2 Die Basis: das HTTP-Protokoll ............................................................... 1.2.1 Das Anfrage/Antwort-Modell ................................................... 1.2.2 Verbindungslos ........................................................................ 1.2.3 Ohne Zustand .......................................................................... 1.2.4 Aufbau von HTTP-Nachrichten ................................................. 1.2.5 Das Format der Anfrage ........................................................... 1.2.6 Das Format der Antwort .......................................................... 1.2.7 Beobachtung der HTTP-Kommunikation ................................... 20 20 21 22 22 23 26 29 1.3 JSP im Vergleich zu älteren Serveranwendungen .................................. 1.3.1 Common Gateway Interface ..................................................... 1.3.2 Servererweiterungen ................................................................ 1.3.3 Java-Servlets ............................................................................ 1.3.4 Active Server Pages .................................................................. 1.3.5 Von Servlets zu JavaServer Pages .............................................. 1.3.6 Arbeitsteilung zwischen Programmierung und Seitendesign ...... 1.3.7 Was spricht für JSP? ................................................................. 29 30 31 31 35 36 37 38 1.4 Anwendungsgebiete und -modelle ....................................................... 1.4.1 JSP oder DHTML? .................................................................... 1.4.2 Das Designmodell Model-View-Controller ............................... 39 39 39 1.5 Von JSP 1.2 nach JSP 2 ......................................................................... 1.5.1 Plattform und Servlet-API ......................................................... 1.5.2 JSTL und andere Tag-Bibliotheken ............................................ 1.5.3 Expression Language ................................................................ 1.5.4 Simple Tag-Handler .................................................................. 1.5.5 Tag-Dateien ............................................................................. 1.5.6 JSP als XML-Dokument und XML-Views ................................... 1.5.7 Neue Standardaktionen und dynamische Attribute ................... 41 42 42 42 43 43 43 44 1.6 Allgemeine Merkmale von JSP .............................................................. 1.6.1 Laufzeitumgebung für JSP ........................................................ 1.6.2 Einbindung in J2EE ................................................................... 1.6.3 Aufbau einer JSP ...................................................................... 1.6.4 Übersetzungsphase .................................................................. 1.6.5 Die JSP-Implementierungsklasse ............................................... 44 44 45 48 49 50 Inhalt 5 1.6.6 1.6.7 6 Ausführungsphase .................................................................... Quellcode des Beispiels ........................................................... 51 55 2 Einrichten einer Entwicklungsumgebung 63 2.1 Werkzeuge für Java ............................................................................... 63 2.2 Webserver und JSP-Container .............................................................. 2.2.1 Apache Tomcat 5.0 installieren ................................................ 2.2.2 Einrichten der Umgebung ........................................................ 2.2.3 Serverbetrieb ........................................................................... 2.2.4 Serverkonfigurierung: server.xml .............................................. 2.2.5 Webanwendungen .................................................................. 2.2.6 Gemeinsame Bibliotheken ....................................................... 64 65 66 68 72 77 82 2.3 Einrichten der Beispiele ........................................................................ 82 2.4 Entwicklungswerkzeuge für JSP ........................................................... 83 3 Entwicklung dynamischer Webseiten mit JSP 2.087 3.1 JSPs und JSP-Dokumente ..................................................................... 3.1.1 Standardsyntax und XML-Syntax .............................................. 87 87 3.2 Syntaktische Bestandteile einer JSP ..................................................... 3.2.1 JSP-Elemente und Template-Daten .......................................... 3.2.2 Elemente und Attribute ........................................................... 3.2.3 EL-Ausdrücke .......................................................................... 3.2.4 Kommentare ........................................................................... 3.2.5 Sonderzeichen und Escape-Sequenzen ..................................... 3.2.6 Relative URLs ........................................................................... 3.2.7 Hinweis zu den Dateinamen .................................................... 88 88 90 91 91 93 94 94 3.3 Direktiven an den JSP-Container .......................................................... 3.3.1 Die Direktive page ................................................................... 3.3.2 Die Direktive include ............................................................... 3.3.3 Alternative Import-Mechanismen ............................................. 3.3.4 Die Direktive taglib .................................................................. 3.3.5 Hinweise zur Schreibweise bei Direktiven ................................ 95 95 105 109 109 114 3.4 Skriptelemente ..................................................................................... 3.4.1 Java-Code in JSPs ..................................................................... 3.4.2 Deklarationen .......................................................................... 3.4.3 Skriptlets ................................................................................. 3.4.4 Ausdrücke ............................................................................... 3.4.5 Skriptlösung für ein Web-Tagebuch ......................................... 114 115 116 120 130 133 3.5 Zugriff auf serverseitige Objekte .......................................................... 137 3.5.1 Objekte und Variablen ............................................................. 138 3.5.2 Implizite Objekte ..................................................................... 139 Inhalt 3.6 Arbeit mit impliziten Objekten ............................................................. 3.6.1 Request .................................................................................... 3.6.2 Response ................................................................................. 3.6.3 PageContext ............................................................................ 3.6.4 Session ..................................................................................... 3.6.5 Application .............................................................................. 3.6.6 Out .......................................................................................... 3.6.7 Config ...................................................................................... 3.6.8 Page ......................................................................................... 3.6.9 Exception ................................................................................. 141 141 142 143 143 144 146 148 148 148 3.7 Expression Language ............................................................................. 3.7.1 Einfacher als Skriptausdrücke ................................................... 3.7.2 Die API-Erweiterung für EL ...................................................... 3.7.3 Einsatz von EL-Ausdrücken ....................................................... 3.7.4 Implizite Objekte in EL-Ausdrücken ......................................... 3.7.5 Hinweise zur Syntax von EL ...................................................... 3.7.6 Funktionen .............................................................................. 148 149 150 151 152 154 157 3.8 Einsatz von Standardaktionen ............................................................... 3.8.1 Allgemeine Syntax von Aktionen .............................................. 3.8.2 Attributwerte ........................................................................... 3.8.3 Typumwandlungen .................................................................. 3.8.4 Ressourcen einfügen – <jsp:include> ........................................ 3.8.5 Weiterleiten einer Anfrage – <jsp:forward> .............................. 3.8.6 Parameterübergabe – <jsp:param> ........................................... 3.8.7 Komponenten einbetten – <jsp:plugin> .................................... 3.8.8 Parametergruppen – <jsp:params> ........................................... 3.8.9 Notausgang – <jsp:fallback> ..................................................... 3.8.10 Elemente erzeugen – <jsp:element> ......................................... 3.8.11 Attribute erzeugen – <jsp:attribute> ......................................... 3.8.12 Rumpf einfügen – <jsp:body> ................................................... 3.8.13 Fragmente aufrufen – <jsp:invoke> ........................................... 3.8.14 Template-Text einfügen – <jsp:text> ......................................... 3.8.15 Rumpf ausführen – <jsp:doBody> ............................................. 3.8.16 Nutzen von JavaBean-Komponenten ........................................ 3.8.17 JavaBeans deklarieren – <jsp:useBean> ..................................... 3.8.18 Eigenschaften abfragen – <jsp:getProperty> .............................. 3.8.19 Eigenschaften setzen – <jsp:setProperty> ................................. 3.8.20 Weitere Standardaktionen ........................................................ 3.8.21 Verwandschaftsbeziehungen und Attributkombinationen ......... 160 161 162 162 162 169 172 173 178 178 178 180 182 183 185 185 186 190 196 197 200 200 3.9 Einsatz der JSP Standard Tag Library – JSTL .......................................... 3.9.1 Aktionen anstelle von Skriptelementen .................................... 3.9.2 JSTL 1.0 und 1.1 ...................................................................... 3.9.3 Abwärtskompatibilität .............................................................. 3.9.4 Zusammensetzung der Bibliothek ............................................. 3.9.5 Ablaufsteuerung mit JSTL ......................................................... 3.9.6 Verarbeitung von XML-Dokumenten ........................................ 3.9.7 Zugriff auf Datenbanken ........................................................... 3.9.8 Formatierung von Zahlen, Zeit- und Datumsangaben ............... 3.9.9 Lokalisierung und Internationalisierung .................................... 201 201 203 204 204 206 214 227 228 232 Inhalt 7 3.10 8 JSP als XML-Dokument ........................................................................ 3.10.1 Allgemeine Merkmale von XML ............................................... 3.10.2 Identifizierung von JSP-Dokumenten ....................................... 3.10.3 Aufbau von JSP-Dokumenten .................................................. 3.10.4 Verarbeitung eines JSP-Dokuments .......................................... 3.10.5 Vorteile von JSP-Dokumenten ................................................. 3.10.6 JSPs mit XML-Elementen ......................................................... 232 236 241 241 248 248 248 3.11 XML-Ansicht einer JSP .......................................................................... 249 3.12 Nebenläufigkeit und Thread-Sicherheit ................................................ 251 3.12.1 Single-Thread-Modell .............................................................. 251 3.12.2 Synchronisierung ..................................................................... 252 3.13 Verarbeitung der Ein- und Ausgabe ...................................................... 3.13.1 Formulare und Anfrage-Parameter ........................................... 3.13.2 Beispiel für ein Anmeldeformular ............................................. 3.13.3 Steuerung der Formularverarbeitung ........................................ 3.13.4 Formularauswertung ................................................................ 3.13.5 Validierung von Benutzereingaben ........................................... 253 254 254 258 264 266 3.14 Einsatz von JavaBeans .......................................................................... 3.14.1 JavaBeans als Komponenten in JSP .......................................... 3.14.2 Allgemeine Merkmale von Beans ............................................. 3.14.3 Eigenschaften und Zugriffsmethoden ....................................... 3.14.4 Andere Methoden ................................................................... 3.14.5 Zustände und Serialisierung ..................................................... 3.14.6 JavaBean-Konstruktor .............................................................. 3.14.7 JavaBean als Datenbehälter innerhalb eines Anmeldeverfahrens 3.14.8 Kompilieren und Installieren von Beans ................................... 3.14.9 Skriptvariable und JavaBean-Objekte ....................................... 271 271 271 273 274 275 275 275 284 284 3.15 Zugriff auf Servlet-Komponenten ......................................................... 285 3.15.1 Servlets kompilieren und installieren ........................................ 286 3.16 Austausch zwischen Anwendungskomponenten .................................. 289 3.17 Cookies 3.17.1 3.17.2 3.17.3 3.17.4 ................................................................................................. Cookies schreiben .................................................................... Cookies auslesen ..................................................................... Cookies ändern ........................................................................ Cookies löschen ....................................................................... 292 293 295 297 297 3.18 Sitzungsverfolgung ............................................................................... 3.18.1 Das Session-Konzept in HTTP .................................................. 3.18.2 Sitzungsverfolgung mit Cookies ................................................ 3.18.3 Umschreiben von URLs ............................................................ 3.18.4 Sitzungskennungen über versteckte Formularfelder .................. 3.18.5 SSL-Sitzungen .......................................................................... 297 298 299 299 301 302 3.19 Handhabung einer Sitzung ................................................................... 3.19.1 Start einer Sitzung .................................................................... 3.19.2 Abfrage der Sitzungsinformationen .......................................... 3.19.3 Daten an das Sitzungsobjekt anbinden ..................................... 3.19.4 Einbau von Beobachtern .......................................................... 3.19.5 Sitzungsende ........................................................................... 302 303 303 304 305 306 Inhalt 3.19.6 3.19.7 JSPs in Sitzung einfügen ........................................................... 306 Test der Sitzungsverfolgung ...................................................... 307 3.20 Filter und Filterketten ........................................................................... 309 3.21 Internationale und lokale Websites ...................................................... 3.21.1 Unicode und Zeichenkodierungen ............................................ 3.21.2 Separate Webpräsenzen für mehrere Sprachen ......................... 3.21.3 Automatische Sprachauswahl ................................................... 3.21.4 I18N – Internationale Sites ....................................................... 3.21.5 Java-Klassen für I18N ............................................................... 3.21.6 Ressourcenbündel .................................................................... 3.21.7 Zeichenkodierung für dynamische Inhalte ................................ 3.21.8 Aktionen der Standardbibliothek für die Internationalisierung .. 3.21.9 Stadt, Land, Fluss – international .............................................. 313 313 314 315 316 317 321 322 322 323 3.22 Zugriff auf Datenbanken mit JDBC ....................................................... 3.22.1 Allgemeine Merkmale von SQL ................................................ 3.22.2 Die JDBC-Architektur ............................................................... 3.22.3 Der Zugriff auf Datenbanken in der Übersicht .......................... 3.22.4 Erstes Beispiel mit MySQL ........................................................ 3.22.5 Die Arbeit mit Datenquellen .................................................... 3.22.6 Neue Daten in die Datenbank einfügen .................................... 3.22.7 Datenbankoperationen mit Hilfe von JSTL ................................ 3.22.8 Ausführen von SQL-Anweisungen ............................................ 3.22.9 Parameter für die Ergebnismenge ............................................. 3.22.10 Verarbeiten der Ergebnismenge ................................................ 3.22.11 Das Interface RowSet ............................................................... 3.22.12 Transaktionen .......................................................................... 3.22.13 Zugriff auf Metadaten .............................................................. 3.22.14 Ausnahmebehandlung und Warnungen .................................... 3.22.15 Auslagern des Zugriffscodes in Komponenten ........................... 3.22.16 Connection Pooling .................................................................. 328 328 330 338 342 347 353 357 364 370 373 378 378 381 383 383 384 3.23 Fehlersuche und Debugging ................................................................. 3.23.1 Auswerten der Fehlermeldungen .............................................. 3.23.2 Testverfahren ........................................................................... 3.23.3 Erzeugen von Fehlerseiten ....................................................... 3.23.4 Error-Handler ........................................................................... 385 385 387 387 387 4 Einrichten dynamischer Webanwendungen 391 4.1 Anwendungsdeskriptoren ..................................................................... 4.1.1 Beschreibungselemente im Überblick ....................................... 4.1.2 Übergreifende Einstellungen .................................................... 4.1.3 Einstellungen für Servlets und JSPs ........................................... 4.1.4 Listener und Filter .................................................................... 4.1.5 MIME-Zuordnungen ................................................................ 4.1.6 Startseiten ................................................................................ 4.1.7 Fehlerseiten ............................................................................. 4.1.8 Lokalisierung ............................................................................ 4.1.9 Sicherheitsmaßnahmen und Berechtigungen ............................ 391 391 394 395 397 399 400 400 401 401 Inhalt 9 Benutzerauthentifizierung ........................................................ JSP-Konfiguration .................................................................... Bezug auf JNDI-Objekte .......................................................... Beispiel für eine Deskriptor-Datei ............................................ 404 405 408 409 4.2 Veröffentlichungsverfahren .................................................................. 4.2.1 Schnüren eines WAR-Pakets .................................................... 4.2.2 Installation einer WAR-Datei unter Tomcat .............................. 4.2.3 Deployment ohne Archiv ......................................................... 4.2.4 Anwendungsmanagement ........................................................ 410 411 412 413 413 5 Erweiterungen und fortgeschrittene Lösungen417 5.1 Benutzerdefinierte Tags ........................................................................ 5.1.1 Einsatz von Tag-Bibliotheken ................................................... 5.1.2 Eine einfache Aktion ................................................................ 5.1.3 Merkmale eigener Aktionen ..................................................... 5.1.4 Das Interface IterationTag ........................................................ 5.1.5 Ein Tag, das seinen Rumpf auswertet ....................................... 5.1.6 Ausnahmebehandlung ............................................................. 5.2 Einfache Tag-Handler ............................................................................ 438 5.3 Einbindung von Tags in eine Tag-Bibliothek ........................................ 5.3.1 Aufbau eines Tag-Bibliothek-Deskriptors .................................. 5.3.2 Beschreibung der einzelnen Aktionen ...................................... 5.3.3 Erweiterungen der Taglib ......................................................... 5.3.4 Installieren der Tag-Bibliothek .................................................. 5.3.5 Einbinden einer Tag-Bibliothek in eine Anwendung ................. 5.3.6 Tags oder Beans? ..................................................................... 5.3.7 Validierung von Tag-Bibliotheken ............................................. 445 446 448 452 454 455 457 457 5.4 Tag-Dateien .......................................................................................... 5.4.1 Platzierung der Tag-Dateien ..................................................... 5.4.2 Inhalt von Tag-Dateien ............................................................ 5.4.3 Die Direktive tag ...................................................................... 5.4.4 Die Direktive attribute ............................................................. 5.4.5 Die Direktive variable .............................................................. 5.4.6 Zugriff auf implizite Objekte .................................................... 5.4.7 Synchronisierung der Variablen ................................................ 5.4.8 Ein Tag mit einem Attribut ....................................................... 5.4.9 Tags zur dynamischen Präsentation von Daten ......................... 5.4.10 Aufruf von Fragmenten ............................................................ 459 461 462 463 465 466 467 467 470 471 475 5.5 Struts-Framework ................................................................................. 476 4.1.10 4.1.11 4.1.12 4.1.13 10 Inhalt 417 418 418 426 431 432 437 6 Kurzreferenz JavaServer Pages 2.0 481 6.1 Allgemeine Regeln ................................................................................ 481 6.1.1 Maskierungen .......................................................................... 481 6.1.2 Typographische Konventionen ................................................. 482 6.2 Kommentare ......................................................................................... 482 6.3 Direktiven ............................................................................................. 6.3.1 page ......................................................................................... 6.3.2 Include ..................................................................................... 6.3.3 Taglib ....................................................................................... 483 483 485 486 6.4 Skriptelemente ...................................................................................... 6.4.1 Deklaration .............................................................................. 6.4.2 Skriptausdruck ......................................................................... 6.4.3 Skriptlets .................................................................................. 6.4.4 Implizite Objekte für Skriptlets und Ausdrücke ......................... 487 487 488 489 490 6.5 EL-Ausdrücke ........................................................................................ 6.5.1 Syntax ...................................................................................... 6.5.2 Implizite Objekte in EL-Ausdrücken ......................................... 6.5.3 Literale ..................................................................................... 6.5.4 Operatoren .............................................................................. 6.5.5 Funktionen .............................................................................. 491 492 492 492 493 495 6.6 Standardaktionen .................................................................................. 6.6.1 <jsp:root> ................................................................................ 6.6.2 <jsp:text> ................................................................................. 6.6.3 <jsp:forward> ........................................................................... 6.6.4 <jsp:include> ........................................................................... 6.6.5 <jsp:param> ............................................................................. 6.6.6 <jsp:plugin> ............................................................................. 6.6.7 <jsp:params> ............................................................................ 6.6.8 <jsp:fallback> ........................................................................... 6.6.9 <jsp:useBean> .......................................................................... 6.6.10 <jsp:getProperty> ..................................................................... 6.6.11 <jsp:setProperty> ..................................................................... 6.6.12 <jsp:element> .......................................................................... 6.6.13 <jsp:attribute> ......................................................................... 6.6.14 <jsp:body> ............................................................................... 6.6.15 <jsp:invoke> ............................................................................ 6.6.16 <jsp:doBody> ........................................................................... 6.6.17 <jsp:output> ............................................................................ 495 496 497 497 498 499 500 502 503 503 504 505 506 507 508 508 509 510 6.7 Kurzreferenz der JSTL ............................................................................ 6.7.1 Kern-Tag-Bibliothek ................................................................. 6.7.2 Tags für allgemeine Aufgaben ................................................... 6.7.3 <c:catch> ................................................................................. 6.7.4 <c:out> .................................................................................... 6.7.5 <c:set> ..................................................................................... 6.7.6 <c:remove> .............................................................................. 6.7.7 Verzweigungen ........................................................................ 510 511 511 511 511 512 513 514 Inhalt 11 6.7.8 6.7.9 6.7.10 6.7.11 6.7.12 6.7.13 6.7.14 6.7.15 6.7.16 6.7.17 6.7.18 6.7.19 6.7.20 6.7.21 6.7.22 6.7.23 6.7.24 6.7.25 6.7.26 6.7.27 6.7.28 6.7.29 6.7.30 6.7.31 6.7.32 6.7.33 6.7.34 6.7.35 6.7.36 6.7.37 6.7.38 6.7.39 6.7.40 6.7.41 6.7.42 6.7.43 6.7.44 6.7.45 6.7.46 6.7.47 6.7.48 6.7.49 6.7.50 6.7.51 6.7.52 6.7.53 6.7.54 6.7.55 6.7.56 6.7.57 6.7.58 6.7.59 12 Inhalt <c:if> ....................................................................................... <c:choose> .............................................................................. <c:when> ................................................................................ <c:otherwise> .......................................................................... Wiederholungen ...................................................................... <c:forEach> ............................................................................. <c:forTokens > ......................................................................... Import und URL-Behandlung ................................................... <c:import> .............................................................................. <c:url> ..................................................................................... <c:redirect> ............................................................................. <c:param> ............................................................................... Tags für die Verarbeitung von XML .......................................... <x:parse> ................................................................................. <x:out> .................................................................................... <x:set> .................................................................................... <x:if> ....................................................................................... <x:choose> .............................................................................. <x:when> ................................................................................ <x:otherwise> .......................................................................... <x:forEach> ............................................................................. <x:transform> .......................................................................... <x:param> ............................................................................... Tags für die Arbeit mit Datenbanken ........................................ <sql:setDataSource> ................................................................ <sql:query> ............................................................................. <sql:update> ........................................................................... <sql:param> ............................................................................. <sql:dateParam> ...................................................................... <sql:transaction> ..................................................................... Tags für die Formatierung von Werten ..................................... <fmt:formatNumber> .............................................................. <fmt:parseNumber> ................................................................ <fmt:formatDate> .................................................................... <fmt:parseDate> ...................................................................... <fmt:timeZone> ....................................................................... <fmt:setTimeZone> .................................................................. Internationalisierung von Anwendungen .................................. <fmt:bundle> .......................................................................... <fmt:setBundle> ...................................................................... <fmt:setLocale> ....................................................................... <fmt:message> ........................................................................ <fmt:param> ............................................................................ <fmt:requestEncoding> ............................................................ Standardfunktionen ................................................................. fn:contains ............................................................................... fn:containsIgnoreCase .............................................................. fn:endsWith ............................................................................. fn:escapeXml ........................................................................... fn:indexOf ............................................................................... fn:join ...................................................................................... fn:length .................................................................................. 514 515 515 516 516 516 517 518 518 519 520 521 521 522 523 523 524 524 525 525 525 526 528 529 529 530 532 533 533 534 535 535 537 539 540 542 542 543 543 544 544 545 546 546 547 547 547 548 548 549 549 550 6.7.60 6.7.61 6.7.62 6.7.63 6.7.64 6.7.65 6.7.66 6.7.67 6.7.68 6.8 fn:replace ................................................................................. fn:split ..................................................................................... fn:startsWith ............................................................................ fn:substring .............................................................................. fn:substringAfter ...................................................................... fn:substringBefore .................................................................... fn:toLowerCase ........................................................................ fn:toUpperCase ........................................................................ fn:trim ..................................................................................... 550 551 551 552 552 553 554 554 554 JSP-Ressourcen ..................................................................................... 555 Glossar 557 Index 569 Inhalt 13 Vorwort Auch der Siegeszug der Eisenbahn begann mit einem Börsencrash. Unbekannter Trostspender Längst gehört es zu unseren Lebensgewohnheiten, den Fahrplan für eine Reise, das Kinoprogramm in der Stadt, das Angebot von offenen Stellen, von gebrauchten Autos, von Büchern, CDs und DVDs über das Internet einzusehen, online unsere Bankgeschäfte zu erledigen, Tickets zu buchen und Artikel zu bestellen. Das Wissen der Welt, soweit es digital aufbereitet ist, lässt sich über Suchmaschinen anzapfen. Portale können auf die persönlichen Bedürfnisse zugeschnittene Informationspakete mit einer erstaunlichen Aktualität zur Verfügung stellen. All diese Angebote sind erst durch Verfahren möglich geworden, die über die erste Phase der Internetnutzung hinausgeführt haben. Diese erste Phase war durch die Möglichkeiten bestimmt, die auf der Basis von HTML realisiert werden konnten. Diese Technik arbeitet mit statischen Seiten, die durch Hyperlinks miteinander verkettet sind. Der Webbesucher kann über den Link zwar von Seite zu Seite springen, aber der Inhalt all dieser Seiten ist fixiert. Der nächste Schritt war, die statischen Inhalte durch solche zu erweitern, die erst auf Anfrage, also dynamisch zusammengestellt werden. In erster Linie wurde dazu eine Verzahnung von Webseiten mit Datenbanken benötigt, die das Material liefern, um aktuelle Informationen in das Gerüst einer statischen Seite einzubinden. Auf dem Terrain, das mit diesem zweiten Schritt erreicht wurde, konkurrieren eine ganze Reihe von Verfahren, und dieser Wettbewerb hat sich durchaus günstig auf die Leistungsfähigkeit der inzwischen verfügbaren Lösungen ausgewirkt. Eine dieser Technologien sind die JavaServer Pages (JSP), die Sun seit 1998 für die Erzeugung dynamischer Webinhalte in den Markt eingeführt hat. Wie HTML- oder XHTML-Seiten sind auch JSPs Textdokumente, die festlegen, wie eine Webseite in einem Browser ausgegeben werden soll. Viele JSPs enthalten Bestandteile, die denen von HTML- oder XHTML-Seiten entsprechen. (Eine JSP kann sogar ausschließlich aus HTML oder XHTML bestehen.) Andere Elemente in einer JSP können aber mehr als nur gegebene Texte, Bilder und sonstige Medien von einem Webserver auf den Bildschirm laden. Sie sind imstande, auf dem Server Verarbeitungsprozesse in Gang zu setzen, die die Antwort des Ser- Vorwort 15 vers durch den Inhalt der Anfrage bestimmen. Diese Antwort wird in der Regel in Form von HTML- oder XHTML-Seiten an den Client geschickt, was nebenbei den Vorteil hat, dass Firewalls nicht im Wege stehen. Aufgerufen werden können JSPs entweder direkt oder über Formulare, Links oder spezielle Aktionen zum Inkludieren oder zur Weiterleitung von Anfragen. Dabei können Parameter in Form von Name/Wert-Paaren übergeben werden. JSPs können sich auch selbst aufrufen. Der Zuspruch zu dieser Lösung ist in den letzten Jahren ständig gewachsen. Das hat sicher mit dem Erfolg von Java als plattformunabhängiger Programmiersprache zu tun, zum anderen auch damit, dass JSP ganz in eine Architektur eingebettet ist, die die notwendigen Dienstleistungen für anspruchsvolle Anwendungen in Form entsprechender Bibliotheken wie JDBC, JNDI oder EJB schon mitbringt. Gemeint ist J2EE, die Edition der Java 2-Plattform für unternehmensweite Anwendungen. In schneller Folge wurden mehrere Versionen der JSP-Spezifikation bereitgestellt. Im Juni 1999 lag die Spezifizierung von JSP 1.0 vor, JSP 1.1 folgte schon im Dezember. JSP 1.2 wurde 2001 verabschiedet. Dieses Buch befasst sich insbesondere mit der neuen JSP-Version 2.0. Diese Version baut auf der ServletAPI-Spezifikation 2.4 auf. JSP 2 erfordert die Java 2-Plattform in der Standard Edition Version 1.3 für Standalone-Container bzw. 1.4 für Container, die Teil der Umgebung Java 2 Enterprise Edition 1.4 sind. Diese Edition ist seit November 2003 verfügbar. Als Referenzimplementierung für JSP 2.0 wird der Open Source Tomcat-Container in der Version 5.0 verwendet. Dieses Buch gibt Ihnen einen kompakten Einstieg in die aktuelle Version von JSP, die vermutlich die Art und Weise, wie solche Projekte in Zukunft realisiert werden, stark verändern wird. JSP 2.0 unterstützt zwar weiterhin eine Reihe von Verfahren, die in diesem Bereich bisher üblich waren, gemeint sind insbesondere die verschiedenen Formen von Skriptelementen. Es bietet aber zugleich deren weitgehenden oder sogar vollständigen Ersatz durch den Einsatz von Elementen an, die klar an den inzwischen allgemein anerkannten XMLStandards orientiert sind. In gewissem Sinne befindet sich JSP also in einer Art Übergangsstadium, sodass gelegentlich konkurrierende Verfahren für den gleichen Zweck beschrieben werden. Die beiliegende CD enthält neben den im Buch beschriebenen Beispielen die aktuellen Spezifikationen zu JSP 2, JSTL 1.1, Servlet 2.4 und die API-Dokumentation für J2EE 1.4, J2SE 1.4 und JSP 2.0. Auch das J2SE-SDK und die aktuellen Tomcat 5.0-Binaries für Windows und UNIX liegen bei. Helmut Vonhoegen 16 Vorwort Köln, im Januar 2004 1 2 1 JavaServer Pages im Überblick 3 4 5 1.1 Von statischen zu dynamischen Webseiten....... 19 6 1.2 Die Basis: das HTTP-Protokoll ........................... 20 7 1.3 JSP im Vergleich zu älteren Serveranwendungen 29 8 1.4 Anwendungsgebiete und -modelle.................... 39 9 1.5 Von JSP 1.2 nach JSP 2 ...................................... 41 10 1.6 Allgemeine Merkmale von JSP .......................... 44 11 12 13 14 17 1 Java Server Pages im Überblick 2 Einrichten einer Entwicklungsumgebung 3 Entwicklung dynamischer Webseiten mit JSP 2.0 4 Einrichten dynamischer Webanwendungen 5 Erweiterungen und fortgeschrittene Lösungen 6 Kurzreferenz Java Server Pages 2.0 1 2 1 JavaServer Pages im Überblick 3 Online-Dienstleistungen taugen nur etwas, wenn sie den Bedürfnissen der Besucher entsprechen. Dazu reichen statische Angebote nicht aus. 4 5 6 Das Web wird gern als interaktives Medium betrachtet. Tatsächlich ist HTML ein wunderbares Mittel, um bunte Seiten vom Server zum Anwender zu schicken. Mittels Hyperlinks hangelt sich der Besucher mühelos von Seite zu Seite, und mit Hilfe von eingebauten Komponenten lassen sich Medien jeder Art auf dem Bildschirm wiedergeben. 7 8 Dennoch bleibt das Web mit den Mitteln von HTML allein eine Einbahnstraße, es gibt für den Besucher keine Möglichkeit – abgesehen von der Eingabe von Webadressen –, selbst Informationen an das Web abzugeben und so seine Interessen besser ins Spiel zu bringen. 10 1.1 11 9 Von statischen zu dynamischen Webseiten Es gibt ganz unterschiedliche Gründe für mehr Interaktion. Häufig ist es beispielsweise für die Besucher der Sites großer Medien angenehm, wenn sie eine Vorauswahl der Themen treffen können, zu denen Inhalte angeboten werden. Umgekehrt werden Informationsangebote oft nur dann freigegeben, wenn der Benutzer sich beim Anbieter anmeldet und seine Berechtigung nachweist, etwa bei abonnierten Diensten wie MedLine. Online-Anbieter möchten die Kundenbindung verstärken, indem sie den Besucher nicht nur mit seinem Namen ansprechen, sondern ihm auch Spezialangebote vorschlagen, die zu dem passen könnten, was er bisher schon gekauft hat. E-Commerce und Online-Banking sind nicht möglich, ohne den Zugriff auf Datenbanken auf der Seite des Servers. 12 13 14 Die Technologien, die in diesem Buch vorgestellt werden, erlauben solche Lösungen oder sind zumindest ein bedeutender Teil davon. Die Besonderheiten dieser Verhahren ergeben sich zu einem großen Teil aus den Gegebenheiten, die durch die technische Strukur des Internets bedingt sind. Um den in den folgenden Kapiteln beschriebenen Details ein Fundament zu geben, wird zunächst das Kommunikationsmodell vorgestellt, das den JavaServer Pages zugrunde liegt. JavaServer Pages im Überblick 19 1.2 Die Basis: das HTTP-Protokoll Die Webanwendungen, von denen in diesem Buch die Rede sein wird, können ganz allgemein als Programme gekennzeichnet werden, die auf einem Webserver ablaufen und von Clients, in der Regel in Form von Webbrowsern, aufgerufen werden. Während dies heute noch hauptsächlich von PCs aus stattfindet, sind schon die verschiedenartigsten Geräte auf dem Vormarsch, die den Zugriff auf Webserver-Anwendungen auch für unterwegs erlauben: PDAs, Handys, intelligente Armbanduhren, vielleicht demnächst auch Brillen von der Art, wie sie in der Werbung eines bekannten Kreditkartenanbieters auftauchten. 1.2.1 Das Anfrage/Antwort-Modell Die Basis für all diese Erweiterungen der menschlichen und maschinellen Kommunikation ist das HTTP-Protokoll, und jeder, der mit der Entwicklung von Anwendungen zu tun hat, die dieses Protokoll als Fundament nutzen, sollte ein paar Hintergrundinformationen dazu nicht verschmähen. Die Besonderheiten von HTTP bestimmen nämlich sehr ausdrücklich die Art und Weise, wie Webanwendungen gestaltet werden können. Abbildung 1.1 Schema des Anfrage/Antwort-Modells in HTTP Das Hypertext Transfer Protocol (HTTP) ist ein bewusst einfaches Protokoll auf der Basis des TCP/IP-Protokolls. Es wurde spezifiziert durch die Internet Engineering Task Force (IETF) in einem Request for Comments (RFC), und zwar zunächst in RFC 1945. Jeder HTTP-Server muss die Version HTTP/1.0 unterstützen, die meisten erlauben aber auch die erweiterte Version HTTP/1.1 (RFC 2616), die insbesondere auch persistente Verbindungen erlaubt. 20 JavaServer Pages im Überblick 1 2 Der Kern des Kommunikationsmodells, das durch HTTP geregelt wird, lässt sich vereinfacht als Schrittfolge beschreiben: 3 1. Ein Client öffnet eine Verbindung zum HTTP-Port eines Servers (Vorgabe ist Port 80). Er benutzt dazu ein TCP/IP-Socket. 4 2. Er sendet über diese Verbindung eine Anfrage (Request). Ziel ist eine Ressource auf diesem Server. 5 3. Der Server lauscht auf eingehende Anfragen an dem dafür bestimmten Port. Geht eine Anfrage darüber ein, sendet er eine Antwort (Response) an den Socket des Clients: entweder die angeforderte Ressource oder eine Fehlermeldung, wenn die Adresse nicht stimmt. 6 4. Die Verbindung wird wieder geschlossen. 8 7 In der Regel ist der Client ein Programm, das in der Lage ist, Anfragen abzusenden, meist ein Browser. Die Anfrage kann direkt durch die manuelle Eingabe einer Webadresse gestartet werden oder durch Anklicken eines Links oder auch durch das Abschicken eines Formulars. Es kann aber auch z.B. eine Suchmaschine sein, die automatisch Anfragen generiert. 9 10 11 In der Rolle des Servers kann im Prinzip jedes Programm agieren, das in der Lage ist, solche Client-Anfragen zu verstehen und mit einer entsprechenden Antwort zu reagieren. Durch Zwischenschaltung von Proxies, Tunnels oder Gateways kann der Ablauf der Kommunikation auch komplexere Formen annehmen, aber davon soll hier nicht die Rede sein. 12 13 Das HTTP-Protokoll legt dabei insbesondere fest, in welchem Format diese Nachrichten zwischen Client und Server ausgetauscht werden. 14 Bevor auf die Einzelheiten der beiden Seiten der Kommunikation eingegangen wird, sollen noch einige wesentliche Merkmale von HTTP betont werden, die gerade für die Webentwicklung von Bedeutung sind. 1.2.2 Verbindungslos Aufgrund der Tatsache, dass für jedes Anfrage/Antwort-Paar eine eigene Verbindung auf- und wieder abgebaut wird, kann HTTP auch als ein verbindungsloses Protokoll bezeichnet werden. Dieses Merkmal hat seine Vor- und Nachteile. Zunächst spart der sofortige Abbau einer Verbindung, sobald der Server seine Antwort losgeworden ist, viele Ressourcen auf der Serverseite, falls der Server von zahlreichen Clients adressiert wird. Andererseits erhöht sich durch die zahlreichen Verbindungsaufnahmen der Netzverkehr. Die Basis: das HTTP-Protokoll 21 1.2.3 Ohne Zustand HTTP ist zugleich ein zustandsloses Protokoll. Der Server behält keinerlei Informationen über den Client, sobald eine Verbindung nach dem Zusenden der Antwort abgeschlossen ist. Die Folge davon ist, dass das Protokoll nicht merkt, wenn ein Client A zum wiederholten Male eine Verbindung zu Server B aufbaut. Auch über die Art des Zugangs gibt HTTP dem Server keinen Aufschluss, der Server kann also nicht unterscheiden, ob eine Anfrage durch Anklicken eines Links, durch Abschicken eines Formulars oder durch Klick auf die Schaltfläche Zurück erfolgt ist. Für HTTP sind alle Verbindungen gleich, und nach ihrer Beendigung gibt es keine »Erinnerung« an das, was früher geschehen ist. Hier unterscheidet sich HTTP deutlich von FTP, bei dem Verbindungen aufgebaut werden können, die für mehrere Anfragen bestehen bleiben. Dass HTTP ein zustandsloses Protokoll ist, hat den Vorteil, dass weniger Ressourcen auf dem Server verbraucht werden und so mehr gleichzeitige Zugriffe möglich sind. Wo es aber notwendig ist, HTTP-Verbindungen mit einer Art Erinnerungsvermögen auszustatten, müssen besondere Maßnahmen ergriffen werden, wie sie in Abschnitt 3.18 beschrieben werden. 1.2.4 Aufbau von HTTP-Nachrichten Wie die Anfrage eines Clients und die Antwort eines Servers aussehen können, ist durch das HTTP-Protokoll genau beschrieben. Beide Nachrichtentypen haben einen gemeinsamen Aufbau, der aber unterschiedlich ausgefüllt wird. Jede Nachricht setzt sich aus folgenden Komponenten zusammen: 왘 Startzeile 왘 Nachrichten-Header* 왘 CRLF 왘 [Nachrichtenrumpf] Die erste Zeile ist erforderlich, die Anzahl der Header-Zeilen kann ganz unterschiedlich sein, je nachdem, welche Informationen an die jeweils andere Seite übergeben werden sollen. Dabei wird zwischen allgemeinen Headern, Anfragebzw. Antwort-Headern und solchen unterschieden, die sich speziell auf die Nachrichten beziehen, die im Nachrichtenrumpf enthalten sind, falls ein solcher verwendet wird. Dieser Teil wird von den Headern jeweils durch eine 22 JavaServer Pages im Überblick 1 2 Leerzeile abgetrennt. Die Header werden in Form von Name/Wert-Paaren angegeben. 3 1.2.5 4 Das Format der Anfrage Bei jeder Anfrage eines Clients an einen Webserver wird ein URL verwendet, der zunächst das Protokoll und den gewünschten Server und dann die Ressource angibt, auf die auf diesem Server zugegriffen werden soll. Der Webserver lauscht auf eingehende Anfragen über einen bestimmten Port, Vorgabe ist der Port 80. Diese Vorgabe kann geändert werden, indem die gewünschte Portnummer hinter der Angabe des Servers, getrennt durch einen Doppelpunkt, angehängt wird: 5 6 7 8 http://www.helmut-vonhoegen.de:8080/index.html 9 Die erste Zeile bei einer Anfrage ist eine Anfragezeile (request-line), bei der Antwort eine Statuszeile (status-line). 10 Wird beispielsweise ein URL wie http://www.helmut-vonhoegen.de/index.html 11 eingegeben, besteht die Anfragezeile aus: 12 GET /index.html HTTP/1.1 13 Die erste Zeile einer Anfrage gibt zunächst die Anfragemethode an und benennt die Ressource, die angefordert wird. Dann folgt die vom Browser verwendete HTTP-Version. 14 Anfragemethoden GET ist die vorgegebene Methode, die für normale Aufrufe von HTML-Seiten und JSPs verwendet wird. Sie fordert einfach vom Webserver die angegebene Ressource an. Ein Nachrichtenrumpf wird nicht verwendet. Die POST-Methode, die ebenfalls im Zusammenhang mit JSP eingesetzt wird, erlaubt es, mit der Anfrage auch größere Datenmengen zu übertragen, die jeweils im Nachrichtenrumpf zusammengestellt werden. Die anderen hier möglichen Methoden – HEAD, CONNECT, DELETE, OPTIONS, PUT und TRACE – spielen im Zusammenhang mit JSP normalerweise keine Rolle. Header Die Liste der möglichen Header ist ziemlich lang und kann unter www.w3.org/Protocols/rfc2616/rfc2616-sec14.html nachgesehen werden. Die Basis: das HTTP-Protokoll 23 Beschrieben werden hier nur einige der am häufigsten verwendeten Header in der Anfrage. Host – Dieses Feld ist das einzige, das in jeder Anfrage enthalten sein muss. Angegeben wird der Name des Webservers und eventuell die Portnummer, wie sie aus dem verwendeten URL ausgelesen werden kann. Falls der IP-Adresse eines Servers mehrere Servernamen zugeordnet sind, kann so zwischen den verschiedenen virtuellen Hosts unterschieden werden. Host: www.w3.org Connection – Mit dem Wert close wird der Server angewiesen, die Verbindung zu schließen, sobald die Übertragung der Antwort abgeschlossen ist. Die Alternative ist keep-alive, wenn die Verbindung aufrechterhalten bleiben soll. Connection: close User-Agent – übergibt Informationen zu dem verwendeten Browser. Die Abfrage dieser Information erlaubt dem Server beispielsweise, unterschiedliche Seiten zurückzugeben, je nachdem, welcher Browser im Einsatz ist. Dieser Header kann auch darauf hinweisen, dass ein Browser auf einem PDA oder Handy genutzt wird. User-Agent: Mozilla/4.51 [en] (WinNT; I] Eine Gruppe von Headern liefert dem Server Hinweise, wie die Antwort an den Browser an dessen Möglichkeiten angepasst werden kann: Accept – wird verwendet, um die Medientypen (also die MIME-Typen) aufzulisten, die der Browser akzeptieren kann. Accept: audio/*, text/html, image/gif, image/jpeg Accept-Charset – gibt die Zeichensätze an, mit denen der Browser etwas anfangen kann. Accept-Charset: iso-8859–5 Accept-Encoding – informiert über die möglichen Kodierungen, die für den Inhalt der Antwort verwendet werden können. Accept-Encoding: compress, gzip Accept-Language – gibt die in der Antwort bevorzugten Sprachen an. Accept-Language: de, en 24 JavaServer Pages im Überblick 1 2 Anfrageparameter 3 Wenn bei einer Anfrage die GET-Methode verwendet wird, lassen sich an den URL Parameter anhängen, die der Server zur Generierung der Antwort verwenden kann, etwa bei der Abfrage einer Datenbank. Soll beispielsweise eine Liste mit Artikeln einer bestimmten Modellgruppe angefordert werden, kann der Name der Modellgruppe als Parameter übergeben werden. Parameter werden nach einem trennenden Fragezeichen hinter den URL in Form von Name/WertPaaren angehängt, die selbst wieder durch &-Zeichen getrennt werden, wie in dem folgenden Beispiel: 4 5 6 7 http://www.lichtlager.de/deckenlampen?modellgruppe=halogen&preisgruppe=A 8 Dabei muss eine bestimmte Kodierung beachtet werden, die Zeichen maskiert, die innerhalb eines URL nicht in der Bedeutung verwendet werden sollen, wie sie nach der URL-Syntax vorgesehen sind. Die untenstehende Tabelle listet die Escape-Codes für diese Zeichen auf. 10 Anfragerumpf 11 Bei der HTTP-Methode POST werden die Daten, die an den Server übergeben werden sollen, etwa die Eingaben in einem Formular, nicht als Parameter an den URL, sondern hinter den Headern als Rumpf 12 9 13 Zeichen Escape-Code Leerzeichen %20 » %22 ~ %7E . %2E , %2C < %3C > %3E # %23 % %25 { %7B } %7D | %7C \ %74 14 Die Basis: das HTTP-Protokoll 25 Zeichen Escape-Code ^ %5E ~ %7E [ %5B ] %5D ' %60 ; %3B / %2F ? %3F : %3A @ %40 = %3D & %26 Diese Parameter lassen sich entweder manuell an den URL anfügen oder über ein Formular, das die jeweiligen Werte abfragt. Sobald die Submit-Schaltfläche benutzt wird, werden die Parameter gesetzt. Anfragerumpf Bei der HTTP-Methode POST werden die Daten, die an den Server übergeben werden sollen, etwa die Eingaben in einem Formular, nicht als Parameter an den URL, sondern hinter den Headern als Rumpf der Nachricht angehängt. Auf diese Weise können bei einer Anfrage auch größere Datenmengen übertragen werden. Mehr dazu im Abschnitt zu den HTML-Formularen. 1.2.6 Das Format der Antwort Die Antwort des Servers folgt immer unmittelbar auf die Anfrage des Clients. Der Server versucht, die in der Anfrage angegebene Ressource zu finden, sei dies nun eine einfache Webseite oder ein Programm wie etwa ein CGI-Skript. Die Antwort ergibt sich folglich aus dem, was dem Server durch die Abfrage abverlangt wird. Das Format der Antwort entspricht in der Grundstruktur dem der Anfrage. Sie ist zusammengesetzt aus einer Reihe von Antwort-Headern und einem Antwort-Rumpf. Die Antwort-Header sind insbesondere dazu da, dem Browser Informationen zu liefern. Diese benötigt er, um mit dem Antwort-Rumpf etwas anfangen zu können, um Cookies zu setzen oder um zu 26 JavaServer Pages im Überblick 1 2 einer anderen Seite umzuleiten. Grundsätzlich werden immer erst die Header an den Browser geschickt, bevor der Rumpf übermittelt wird. 3 Statuszeile 4 Die erste Zeile ist immer eine Statuszeile, die sofort erkennen lässt, ob die Anfrage erfolgreich bearbeitet werden konnte oder nicht. Die Statuszeile benennt das verwendete Protokoll, gibt dann einen Statuscode in Form einer dreistelligen Zahl und danach eine Kurzbeschreibung der durch den Statuscode identifizierten Situation an. Eine erfreuliche Statuszeile sieht deshalb so aus: 5 6 7 HTTP/1.1 200 OK Die Anfrage wurde vom Server entgegengenommen, verstanden und akzeptiert. Wird die Ressource nicht gefunden, gibt es den weniger erfreulichen Code 400 bad request. Wird der Zugriff auf eine Seite verweigert, weil der Benutzer sich nicht identifizieren kann, ist der Code 401 unauthorized. 8 Die Statuscodes sind nach der ersten Zahl in fünf Klassen eingeteilt, die in der Tabelle beschrieben sind: 10 9 11 Code-Bereich Kategorie Bedeutung 1xx Information provisorischer Code für experiementelle Anwendungen, wird nur von HTTP/1.1 verwendet 2xx Erfolgreich gibt an, dass eine Anfrage erfolgreich bearbeitet wurde 3xx Umleitung Der Server fordert die Weiterleitung der Anfrage an eine andere Stelle an. 4xx Client-Fehler Codes für Fehler auf der Client-Seite, z.B. ein falsch eingegebener URL für eine Ressource, die deshalb nicht gefunden werden kann 5xx Server-Fehler Codes für Fehler auf der Serverseite. Der Server kann beispielsweise eine Anfrage nicht ausführen, obwohl der URL in Ordnung ist, etwa wegen Überlastung der Verbindungen. 12 13 14 Die vollständige Liste der Codes ist unter www.w3.org/Protocols/rfc2616/ rfc2616-sec10.html zu finden. Antwort-Header Hinter der Statuszeile folgen üblicherweise einige Header, wie in dem folgenden Beispiel: Die Basis: das HTTP-Protokoll 27 HTTP/1.1 200 OK Date: Sat, 04 Mar 2003 13:39:02 GMT Accept-Ranges: bytes Server: Apache/1.3.1 Content-Length: 1280 Content-Type: text/html Last-Modified: Fri, 03 Mar 2003 06:54:40 GMT <html> <head> ... Auch in der Antwort kommen unterschiedliche Typen von Headern vor. Einige enthalten allgemeine Informationen im Zusammenhang mit der Antwort, z.B.: 왘 Date – gibt das Datum der Antwort an. 왘 Andere Header betreffen Informationen über die Antwort selbst: 왘 Server – gibt den Namen des verwendeten Servers bzw. des Serverprogramms und der verwendeten Version an. 왘 Accept-Ranges – zeigt an, dass auch Anfragen zu einzelnen Bereichen der Ressource möglich sind, und gibt die Einheit an, die dabei verwendet werden kann. Eine Reihe von Headern beziehen sich auf den Inhalt des Nachrichtenrumpfes in der Antwort: 왘 Content-Length – gibt die Länge des nach der Leerzeile angehängten Nachrichtenrumpfes an. 왘 Content-Type – gibt den Inhaltstyp des Nachrichtenrumpfes an, also ob es sich z.B. um HTML- oder XML-Code oder um einfachen Text handelt. Hier wird der entsprechende MIME-Typ eingetragen, an dem der Browser erkennen kann, ob er für die Darstellung der Daten möglicherweise auf ein Plugin zurückgreifen muss. 왘 Last-Modified – liefert das Datum der letzten Änderung an dem Nachrichtenrumpf oder an der wiedergegebenen Ressource. Der Browser kann diese Information in einem lokalen Cache als Zeitstempel verwenden, sodass Ressourcen nur dann neu angefordert werden müssen, wenn sie sich seit der letzten Anfrage geändert haben. Antwortrumpf Der Rumpf der Antwort kann einfache HTML-Seiten enthalten oder auch andere Inhaltstypen wie XML etc. Sind im Rumpf Tags enthalten, die selbst 28 JavaServer Pages im Überblick 1 2 wieder auf andere Ressourcen verweisen, etwa ein <img>-Tag für ein Bild, erzeugt der Browser bei der Entgegennahme der Antwort daraus automatisch eine erneute, spezielle Anfrage an den Server, diese Ressource ebenfalls zu liefern. Das Laden einer großen Seite mit vielen Bildern und sonstigen eingeschlossenen Ressourcen – Videos, Audiostreams etc. – kann sich also zu einem munteren Anfrage/Antwort-Spiel auffächern, bis eine Seite endlich vollständig zu sehen ist. Das führt bei langsamen Modemverbindungen zu den gefürchteten Wartezeiten. 1.2.7 3 4 5 6 Beobachtung der HTTP-Kommunikation 7 Wenn Sie die Client/Server-Kommunikation im Detail überprüfen wollen, können Sie eines der Tools verwenden, das die HTTP-Nachrichten sichtbar macht. Die Abbildung zeigt ein Dialogfenster des ProtocolExplorers, der auf der Seite www.sourcestream.com von Dustin R. Callaway angeboten wird. 8 9 10 11 12 13 14 Abbildung 1.2 HTTP-Nachrichten bei einer Anfrage 1.3 JSP im Vergleich zu älteren Serveranwendungen Der erste Lösungsansatz für dynamische Webseiten, der auch heute noch bei vielen Formularseiten verwendet wird, benutzt das so genannte Common Gateway Interface (CGI). Diese »Allgemeine Übergangsschnittstelle« bot zum JSP im Vergleich zu älteren Serveranwendungen 29 ersten Mal die Möglichkeit, Daten vom Anwender zum Server zu schicken und auf diesem Weg an den Anbieter einer Website weiterzuleiten. Die Schnittstelle regelt, wie der Browser dabei mit Programmen auf der Serverseite kommuniziert. 1.3.1 Common Gateway Interface Der Ansatz des CGI ist relativ einfach. Bei normalen Webseiten wird von einem Browser aus ein URL an den Webserver geschickt. Findet der Server die adressierte Seite, wird sie unverändert an den Browser geschickt und darin angezeigt. Bei einem CGI-Aufruf dagegen lokalisiert der aufrufende URL keine HTML-Seite, sondern ein Programm oder Skript auf dem Webserver. Wenn der Server die Anfrage empfängt, setzt er eine Reihe von Umgebungsvariablen, auf die die CGI-Anwendung zugreifen kann. Dazu gehören etwa die Portnummer, der Skriptname, der Abfragestring, der Inhaltstyp und die Länge der Daten, die dem Skript übergeben werden, um nur einige zu nennen. Der Server startet nach diesen Vorbereitungen die Anwendung. Vom Besucher eingegebene Daten werden entweder als Parameter, die an den URL angehängt sind, übergeben oder im Nachrichtenrumpf der Anfrage. Diese Daten werden über die Standardeingabe an das CGI weitergereicht. Das Programm verwendet die übergebenen Daten, um damit etwas mehr oder weniger Sinnvolles zu tun, und schickt eine Antwortseite zurück. Das kann eine einfache Bestätigung sein, dass ein Formular empfangen wurde, oder auch das Ergebnis einer Datenbankabfrage, die von dem CGI-Skript ausgeführt wird. Das Skript schreibt dazu diese Antwort einfach in die Standardausgabe, und der Server schickt sie an den Client. Die weite Verbreitung von CGI-Lösungen hat sicher auch damit zu tun, dass CGI-Programme in zahlreichen Sprachen geschrieben werden können. Provider stellen häufig Bibliotheken mit verwendbaren CGI-Anwendungen zur Verfügung, um Standardfunktionen anzubieten. Typische Aufgaben sind: 왘 Formmailer – Weiterleiten von ausgefüllten Formularen per E-Mail an den Anbieter 왘 Suchfunktionen – Auffinden von Informationen innerhalb umfangreicher Websites 왘 Besucherzähler – Messung der Zugriffe auf einzelne Webseiten Die CGI-Lösung bringt aber eine Reihe von Nachteilen, die sehr bald die Suche nach Alternativen angestoßen hat. Der gravierendste Nachteil ist, dass der 30 JavaServer Pages im Überblick 1 2 Webserver für jede Anfrage einen eigenen Systemprozess starten und einen Sprach-Interpreter laden muss, der dann das Skript ausführt. Kommen zahlreiche Anfragen gleichzeitig an, geht die Performanz leicht in die Knie. Da jeder CGI-Prozess separat ausgeführt wird, ist es auch schwierig, Daten zwischen verschiedenen CGI-Anwendungen auszutauschen, etwa um eine Sitzungsverfolgung zu realisieren. Zwar hat hier die Erweiterung FastCGI, die von der Firma Open Market entwickelt wurde, insofern eine Verbesserung erlaubt, als dass mehrere Anfragen in einem permananten Prozess abgearbeitet werden können. Diese Lösung wird aber nur von einigen Servern unterstützt. 3 4 5 6 7 1.3.2 Servererweiterungen 8 Die Einschränkungen der CGI-Lösung führten zu einer Reihe von Alternativen in Form von speziellen Servererweiterungen. Webserver-APIs sorgen dafür, dass nicht für jede Anfrage ein neuer Prozess gestartet werden muss. Die Anwendungen werden nach der ersten Anfrage im Speicher gehalten und über Funktionsaufrufe für alle folgenden Anfragen genutzt. Dazu zählen das NSAPI auf dem Webserver von Netscape/iPlanet, das ISAPI auf dem Internet Information Server (IIS) von Microsoft und das Apache-API auf dem bekannten Apache Webserver. 9 10 11 12 Webserver-APIs bringen insbesondere Geschwindigkeitsvorteile gegenüber den CGI-Lösungen. Zugleich werden aber auch die Funktionsmöglichkeiten erweitert, weil diese Interfaces Zugriff auf die internen Strukturen des jeweiligen Servers haben. Der Nachteil ist allerdings, dass Anwendungen, die diese APIs nutzen, nicht ohne weiteres auf andere Server übertragen werden können und dass sie an bestimmte Sprachen gebunden sind. 1.3.3 13 14 Java-Servlets In der Java-Welt – Start 1994 – führte Sun 1996 eine ähnliche Lösung ein: Servlets als Komponenten auf der Serverseite. Dazu wurde die Spezifikation für ein Servlet-API entwickelt, die inzwischen bis zu der Version 2.4 fortgeschritten ist. Sie beschreibt die Interfaces und Klassen, die Servlets nutzen, um Webanwendungen mit dynamischen Inhalten generieren zu können. Allerdings geschieht dies gewissermaßen im Hintergrund, denn Servlets haben anders als Java-Applets, die sich direkt in einem Browser zeigen und ihre Steuerelemente anbieten, keine grafische Schnittstelle. Dafür haben sie den Vorteil, dass sie auf einer virtuellen Maschine in einer kontrollierten Serverumgebung ablaufen und für die Kommunikation mit den Clients nur auf HTTP angewiesen sind. Deshalb sind Servlets auch nicht von den Einschränkungen betroffen, die einem Applet durch die Umgebung, in der es innerhalb eines Browsers laufen JSP im Vergleich zu älteren Serveranwendungen 31 soll, gesetzt sind. Das Ergebnis eines Servlets wird auf dem Client einfach in HTML ausgegeben, was selbst für ältere Browser keine Probleme aufwirft. Auf dem Client muss also keine zusätzliche Software installiert sein. Klassen für die HTTP-Kommunikation Zunächst einmal sind Servlets reguläre Java-Klassen. Sie unterscheiden sich aber von anderen Java-Anwendungen dadurch, dass sie nur in einer bestimmten Umgebung ausgeführt werden können. Diese gibt vor, was ein Servlet kann und was nicht. Deshalb werden Servlets auch als Erweiterung von zwei speziellen Klassen realisiert, die es erlauben, die durch das HTTP-Protokoll gegebenen Formen der Kommunikation zwischen Webbrowser und Webserver zu nutzen. Dies sind die Klassen GenericServlet und HTTPServlet. Diese Klassen bieten zahlreiche vordefinierte Methoden an, und die Aufgabe der Entwicklung besteht im Wesentlichen darin, entsprechende Unterklassen daraus zu bilden und die Methoden passend zu überschreiben, die für eine bestimmte Anwendung benötigt werden. Servlets erlauben es, auf eine Anfrage an den Webserver nicht einfach statische Inhalte, die in Form von Webseiten auf dem Server vorliegen, zurückzugegeben, sondern Informationen, die das Servlet aktuell durch Verarbeitung der vorliegenden Daten generiert. Ein Servlet stellt also auf der Basis von Daten, die im Zuge einer Anfrage übergeben werden, etwas Bestimmtes an, und erst die Ergebnisse dieser Aktivitäten werden in Form einer Antwortseite im Browser wieder sichtbar. Komponenten und Container Webanwendungen, die mit Hilfe von Servlets realisiert werden, sind Softwarekomponenten, die zur Ausführung eine spezielle Laufzeitumgebung benötigen. Diese Umgebung wird in der Java-Welt durch Container hergestellt. Während für Applets auf der Client-Seite ein Applet-Container benötigt wird, benötigen Servlets auf der Serverseite einen Servlet-Container. Alle Servlet-Container müssen den Servlets bestimmte Dienste anbieten, die jedes Servlet braucht, wenn es eingesetzt werden soll. Und sie müssen diese Dienste in derselben Weise anbieten, damit Servlets, die auf einem bestimmten Container entwickelt wurden, auch auf jeden anderen Servlet-Container übertragen werden können. Diese Einheitlichkeit wird dadurch gewährleistet, dass die Container der Servlet-Spezifikation entsprechen müssen. Container stellen außerdem bestimmte Werkzeuge – Deployment Tools – zur Verfügung, mit denen Komponenten innerhalb des Containers eingerichtet und konfiguriert 32 JavaServer Pages im Überblick 1 2 werden können. Dabei werden Deskriptoren in Form von XML-Dokumenten verwendet. 3 4 5 6 7 8 9 10 11 Abbildung 1.3 Server, Servlet-Container und Servlets 12 Die Hauptaufgabe des Servlet-Containers ist, den so genannten Lebenszyklus der Servlets zu managen. Der Container lädt meist die Klasse eines Servlets, wenn die erste Anfrage danach von einem Browser eingeht, legt die Eingangswerte fest und ermöglicht dann die Abarbeitung der Anfrage. Weitere Anfragen können das bereits initialisierte Servlet erneut verwenden, bis der Server schließlich heruntergefahren wird. Der Container gibt dem Servlet die Möglichkeit, genutzte Ressourcen wieder freizugeben und Zustandsinformationen, die während des Lebenszyklus erworben wurden, zu sichern. 13 14 Serverprozess und Threads Dabei benutzen Servlets denselben Prozessraum wie der Webserver selbst, dessen Wirkungsmöglichkeiten sie erweitern. Sie werden wie gesagt nur einmal geladen, entweder bei der ersten Anfrage oder auch gleich beim Start des Servers. Jede einzelne Anfrage kann dann als ein separater Ausführungspfad, als Thread, innerhalb dieses permanenten Prozesses behandelt werden. Das wiederum eröffnet die Möglichkeit, in einem einzigen Prozess auch mehrere Threads parallel zu handhaben. Ist ein Servlet einmal geladen, können alle Anfragen an dieses Servlet, die gleichzeitig eingehen, auf mehrere Threads verteilt werden. JSP im Vergleich zu älteren Serveranwendungen 33 Servlets haben dabei Zugriff auf die Dienste, die der Webserver zur Verfügung stellt, z.B. Logbuchfunktionen, Benutzeridentifizierung etc. Außerdem kann auf Ressourcen zugegriffen werden, die zwischen verschiedenen Anfragen im Speicher verbleiben, etwa geöffnete Datenbankverbindungen. Automatische Kompilierung Weitere Vorteile ergeben sich daraus, dass Servlets beim ersten Aufruf kompiliert werden und nur bei einer Änderung erneut kompiliert werden müssen. Insofern sind diese Komponenten wesentlich schneller als Skriptlösungen, die jedes Mal neu interpretiert werden. Da es sich um Java-Klassen handelt, ist auch die Überprüfung der verwendeten Datentypen immer streng, sodass Fehler in diesem Bereich schon bei der Kompilierung entdeckt werden und nicht erst bei der Ausführung auffallen. Java Virtual Machine – JVM Wie bei den Java-Applets werden auch Java-Servlets von einer virtuellen JavaMaschine (JVM) ausgeführt. Auf diese Weise wird der direkte Zugriff auf den Speicher vermieden und somit werden Möglichkeiten für einem Systemcrash minimiert. Bei Problemen werden Ausnahmen erzeugt, die von den Anwendungen behandelt oder abgefangen werden können. Plattformunabhängigkeit Da Servlets als Java-Klassen realisiert werden, gelten natürlich auch für Servlets die allgemeinen Vorzüge der Sprache bezüglich der Übertragbarkeit auf verschiedene Plattformen und Serverumgebungen. Servlets können inzwischen auf fast allen marktgängigen Webservern eingesetzt werden. Entweder unterstützen die Server den Einsatz von Servlets direkt oder mit Hilfe von entsprechenden Add-Ons. Seitengenerierung über Servlets Was bisher zu Servlets gesagt wurde, zeigt diese Technik als mächtiges Instrument für die Generierung von dynamischen Webinhalten. Die Art und Weise, wie ein Servlet schließlich die sichtbare Antwort auf eine Anfrage erzeugt, kann aber nicht überzeugen. Der HTML-Code, der schließlich für die Anzeige der Antwort auf dem Browser benötigt wird, muss durch häufig unübersichtliche Folgen von Ausgabeanweisungen generiert werden, wie schon das folgende kleine Beispiel zeigt (Anrede.java): 34 JavaServer Pages im Überblick 1 2 import javax.servlet.*; import javax.servlet.http.*; public class anrede extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 3 4 5 6 response.setContentType("text/html"); PrintWriter out = response.getWriter(); String name = request.getParameter("gast"); out.println("<HTML>"); out.println("<HEAD><TITLE>Gruss</TITLE></HEAD>"); out.println("<BODY>"); out.println("Guten Tag " + name); out.println("</BODY></HTML>"); 7 8 9 } 10 } Der entscheidende Nachteil von Servlets ist offensichtlich: Eine klare Trennung von Anwendungslogik und Präsentation bei der Entwicklung von Webanwendungen ist unmöglich. Selbst kleine Änderungen an der Darstellung einer Seite erfordern, dass das Servlet neu kompiliert wird. Für die Entwicklung von Servlets werden zudem Programmierer benötigt, die mit Java umgehen können. Die Webdesigner können mit dieser Form der Seitengestaltung in der Regel aber nicht glücklich werden. Alternativen waren also gefragt. 1.3.4 11 12 13 14 Active Server Pages Um die Entwicklung von dynamischen Webanwendungen zu vereinfachen, führte Microsoft auf der Basis seines Internet Information Servers (IIS) die Active Server Pages (ASP) ein. Dabei handelt es sich um Webseiten, bei denen der normale HTML-Code mit Einschüben aus Skriptelementen gemischt ist. Anders als bei Lösungen mit Skriptelementen, die direkt im Browser aktiviert werden, etwa mit JavaScript oder VBScript, geht es hier aber um Skripte, die auf dem Server ausgeführt werden, um auf der Basis des HTTP-Protokolls dynamische Antwortseiten zu erzeugen, die an den Webbrowser zurückgegeben werden. Webentwickler bewegen sich dabei über weite Strecken in ihrer vertrauten HTML- oder auch DHTMLWelt. Nur an den Stellen, an denen dynamische Inhalte verlangt werden, sind spezielle Blöcke mit Skriptcode nötig. Sie werden JSP im Vergleich zu älteren Serveranwendungen 35 jeweils durch die Begrenzer <% und %> von den HTML-Elementen abgesondert. Das kleine Beispiel zeigt, wie dies aussehen kann: <%@ LANGUAGE="VBSCRIPT" %> <% Response.Expires=0 %> <html> <head> <title>Zeitansage</title> </head> <body> <h2>Die aktuelle Zeit ist: <%= Now%></h2> </body> </html> Als Skriptsprache wird meistens VBScript oder JScript verwendet, obwohl die Laufzeitumgebung im Prinzip auch von anderen Sprachen wie Perl oder Python genutzt werden kann. Der Webserver reicht die Aufrufe von ASP-Seiten an eine ISAPI-Servererweiterung weiter, die dafür sorgt, dass das ASP-Dokument von der ASP.DLL interpretiert wird. COM-Komponenten können über die Skriptelemente eingebunden werden, um komplexere Aufgaben zu erledigen. Diese Technik führte zu einer spürbaren Vereinfachung, wenn es darum ging, Websites mit dynamischen Inhalten zu erzeugen. Wesentlichster Nachteil war aber die Einschränkung durch die Bindung an die Windows-Plattform, auch wenn es mit Produkten wie Chili!Soft ASP von Sun und InstantASP von Halcyon Software eine begrenzte Unterstützung für andere Plattformen gab. 1.3.5 Von Servlets zu JavaServer Pages Auf der Basis des Java Servlet-APIs führte schließlich auch Sun 1998 eine Lösung ein, die eine bessere Trennung von Webseitendesign und Programmierung von Anwendungslogik erlaubt: die JavaServer Pages, abgekürzt JSP. Dabei werden die Vorteile der Servlet-Lösung insofern beibehalten, als JSPs auf dem Webserver automatisch in Servlets übersetzt und als Servlets ausgeführt werden. Zudem können Webanwendungen Servlets und JSPs auch mischen. Dies wird in neuen Anwendungsarchitekturen wie Struts genutzt, die eine strenge Trennung zwischen der Anwendungslogik, der Steuerung der Aufgabenverteilung und der eigentlichen Datenpräsentation vornehmen, wobei Servlets für die beiden ersten Bereiche und JSP für die Darstellung auf dem Client eingesetzt werden. Dies ist insbesondere bei großen Unternehmensanwendungen sinnvoll, die von Entwicklerteams realisiert und gepflegt werden. Mehr dazu in Abschnitt 1.4 und 5.6. 36 JavaServer Pages im Überblick 1 2 3 4 5 6 7 8 9 Abbildung 1.4 Von der JSP über das Servlet zur HTML-Ausgabe 10 Der Schwerpunkt dieses Einstiegs liegt auf der JSP-Technologie. Das ServletAPI, das ja bei der Ausführung von JSPs direkt zum Einsatz kommt, wird also hier im Wesentlichen nur im Zusammenhang mit JSP behandelt. 11 Es ist kein Geheimnis, dass die »aktiven Seiten auf dem Server« in vielen ihrer Merkmale auch für die JavaServer Pages Pate gestanden haben. Das voneinander Lernen ist schließlich die Basis jeden Fortschritts. Ähnlich wie bei einer ASP-Seite wird der normale HTML- oder XHTML-Code, der für das Äußere der Seite sorgt, durch abgesonderte Inseln mit JSP-Elementen erweitert. Diese sorgen dafür, dass auf der Seite des Servers eine bestimmte Verarbeitung ausgeführt wird, die in die statische HTML-Seite den Inhalt von dynamischen Elementen einfügt. 1.3.6 12 13 14 Arbeitsteilung zwischen Programmierung und Seitendesign Während die HTML-Elemente in einer JSP so, wie sie sind, in der Ausgabe wiedergegeben werden, stoßen die JSP-Elemente auf dem Webserver Verarbeitungsprozesse an, von deren Ergebnis dann abhängt, was an der Stelle erscheint, an der die Elemente stehen. Wenn also beispielsweise ein JSP-Element eine Datenbank auf dem Server mit einem bestimmten Kriterium abfragt, erscheinen die bei dieser Abfrage gefundenen Datensätze an der entsprechenden Stelle. Um solche dynamischen Lösungen zu ermöglichen, stellt JSP zunächst eine Reihe von Standardelementen zur Verfügung, Aktionen für typische Aufgaben, Direktiven oder Skriptelemente. Seit der JSP-Version 1.1 wird zusätzlich ein JSP im Vergleich zu älteren Serveranwendungen 37 Erweiterungsmechanismus angeboten, der mit Hilfe von benutzerdefinierten Aktionen und von JavaBeans oder Enterprise JavaBeans den Entwicklern ein weites Feld öffnet. Durch solche Komponenten lassen sich auch komplexe Abläufe so kapseln, dass Designer, die diese in ihre Seite einbauen, über die Details nicht viel wissen müssen. All dies erleichtert die Arbeitsteilung, wenn große Sites in Teams aus Designern und Programmierern zu realisieren sind. Es soll aber nicht unerwähnt bleiben, dass die Mischung von HTML- und JSPElementen in umfangreichen JSP-Anwendungen auch leicht zu einer unübersichtlichen Situation führen kann. Die Anordnung der verschiedenen Elemente ist in keiner Weise vorgeschrieben, kann also auch weniger gelungen sein. In solchen Fällen wird vor allem die Fehlersuche zu einem harten Job. Auch die Pflege solcher Sites kann Kopfschmerzen bereiten. Oft ist es deshalb ratsam, eine Anwendung modular aus kleineren Komponenten aufzubauen, die sich einzeln testen lassen. Hier kann insbesondere das Model-View-ControllerModell helfen, das im nächsten Abschnitt beschrieben wird. 1.3.7 Was spricht für JSP? Zu den Vorteilen, die JSP gegenüber ASP vorweisen kann, gehört gewiss die Verwendung von Java, wodurch die Implementierung von Webanwendungen auf unterschiedlichen Plattformen entscheidend vereinfacht wird. Die meisten populären Webserver sind in der Lage, entweder direkt oder indirekt durch entsprechende Add-Ons JSP-Lösungen zu beherbergen. Virtuelle Java-Maschinen stehen auf allen Plattformen zur Verfügung. Außerdem ist Java eine komplette Programmiersprache, unterliegt also nicht den Einschränkungen, die für Skriptsprachen typisch sind. Ein wesentliches Merkmal von JSP ist die Erweiterbarkeit. Die Erweiterungsmechanismen sind gerade in der neuen JSP-Version noch einmal ausgebaut und zugleich vereinfacht worden. Dabei werden insbesondere auch die Vorteile der allgemein anerkannten XML-Standards genutzt. Eine Besonderheit von JSP ist sicher auch, dass es sich um eine Spezifikation handelt und nicht um ein fertiges Produkt. Es gibt zwar eine Referenzimplementierung für jede JSP-Version, deren Zweck es ist, am praktischen Beispiel zu klären, wie spezielle Merkmale der Spezifikation in der Praxis anzuwenden sind. Unabhängig davon aber können Anbieter eigene Implementierungen der Spezifikation entwickeln und dem Sturm der Konkurrenz aussetzen. Die Auseinandersetzung um die beste Lösung für die angesprochenen Probleme ist natürlich überhaupt nicht abgeschlossen. In mancher Hinsicht ist ASP.NET – der Nachfolger von ASP – wiederum als Antwort auf die Merkmale 38 JavaServer Pages im Überblick 1 2 zu verstehen, die JSP über ASP hinausgeführt haben. Beispielsweise werden ASP.NET-Seiten nun auch vor der Ausführung kompiliert, was deutliche Geschwindigkeitsgewinne gegenüber interpretierten Skripten erlaubt. Beide Technologien konkurrieren auf einem hohen Level miteinander, der Sache kann das nur gut tun. 3 4 5 1.4 Anwendungsgebiete und -modelle 6 Um in statische Webseiten dynamische Elemente einzubauen, stehen eine Reihe von Verfahren auf der Client-Seite und auf der Serverseite zur Verfügung. Manche Aufgabe kann sowohl auf der einen als auch auf der anderen Seite gelöst werden. 1.4.1 7 8 JSP oder DHTML? 9 Anwendungen auf der Serverseite sind sicher immer dann zu bevorzugen, wenn es um Seiten geht, die auf umfangreiche Datenbestände zugreifen. Solche JSP-Lösungen sind auch innerhalb von Intranets effektiv. 10 Natürlich könnte ein Versandhaus seinen digitalen Katalog im Prinzip auch zum Download anbieten, so wie es ja auch gedruckte Kataloge an den Kundenstamm verschickt. Das hat aber, abgesehen von den Übertragungskosten, den Nachteil, dass diese Kataloge nur durch ständige Updates aktuell gehalten werden. Wird dagegen ein Katalog auf dem Server gepflegt, greifen alle Clients immer auf den aktuellen Katalog zu. 11 Es gibt aber viele weniger umfangreiche Funktionen, die sich sowohl auf der Client-Seite als auch auf der Serverseite bereitstellen lassen. Auch bei Funktionen, die sich ohne jeden Nachteil etwa mit Skripten beim Client realisieren lassen, kann es trotzdem sinnvoll sein, sie über Webanwendungen auf dem Server zu realisieren. Dadurch wird beispielsweise vermieden, dass eine solche Funktion für den Webbesucher nicht verfügbar ist, wenn er in seinem Browser die Ausführung etwa von JavaScripts aufgrund von Sicherheitsbedenken unterbindet. 14 1.4.2 12 13 Das Designmodell Model-View-Controller Umfangreichere Webanwendungen enthalten fast immer eine Formularkomponente, in die der Besucher Eingaben macht, die anschließend auf der Serverseite geprüft werden, bestimmte Verarbeitungsschritte einleiten – wie die Abfrage einer Datenbank – und schließlich in einer von diesen Schritten bestimmten Antwort des Servers an den Client enden. Solche typischen Abläufe lassen sich gut in einem Designmodell gruppieren, das mit der Abkürzung MVC für Model-View-Controller benannt wird. Das Anwendungsgebiete und -modelle 39 Modell wurde schon in den spätern 80ern im Zusammenhang mit der Programmiersprache Smalltalk vorgestellt. Die Grundidee ist eine saubere Trennung von drei Aufgabenbereichen, die sich bei jeder Anwendung, die mit einer Benutzerschnittstelle arbeitet, unterscheiden lassen. Jeder Bereich wird dabei in einem Objekt zusammengefasst: 왘 Das Model-Objekt liefert das Datenmodell für die Vorgänge, um die es geht, und die Regeln dafür, wie diese Daten verwendet werden sollen. Dieses Objekt vereint die logische Seite der Anwendung in sich, wobei von der Frage, wie Daten vom Benutzer eingegeben werden und wie die Ergebnisse der Datenverarbeitung präsentiert werden sollen, zunächst ganz abgesehen wird. 왘 Das View-Objekt ist für die visuelle Präsentation der Daten zuständig. Dazu muss ihm bekannt sein, mit welchen Methoden die Daten des ModelObjekts ausgelesen werden und wie diese Daten durch das ControllerObjekt geändert werden können. 왘 Das Controller-Objekt ist für die Verarbeitung der vom Benutzer vorgenom- menen Eingaben zuständig. Es sitzt gewissermaßen zwischen dem Viewund dem Model-Objekt. Wenn auf der Benutzerebene über ein Steuerelement z.B. ein angezeigter Wert verändert wird, sorgt das Controller-Objekt dafür, dass diese Änderung an den Daten des Model-Objekts vorgenommen wird. Umgekehrt werden innerhalb des Model-Objekts neu berechnete Daten über das Controller-Objekt wieder an das View-Objekt zurückgegeben, sodass sich die angezeigten Daten entsprechend ändern. Bei unternehmensweiten Anwendungen ist es in der Regel sinnvoll, sie als Zusammenspiel von mehreren Komponenten zu realisieren, die sich dem Modell entsprechend auf eine der Aufgaben konzentrieren. Abbildung 1.5 MVC in der Übersicht 40 JavaServer Pages im Überblick 1 2 Durch eine klare Trennung der verschiedenen Rollen wird es möglich, eine Veränderung an der Benutzeroberfläche vorzunehmen, ohne dass sich an dem Model-Objekt etwas ändern muss. Einem Model-Objekt können mehrere View-Objekte zugeordnet werden, die beispielsweise die Dateneingabe über unterschiedliche Instrumente abwickeln. 3 4 5 Umgekehrt bleibt die Präsentation der Daten durch das View-Objekt von Änderungen in den Berechnungsverfahren des Model-Objekts unberührt. Dagegen sind die View- und Controller-Objekte in der Regel enger verzahnt. Zu jedem View-Objekt muss es ein Controller-Objekt geben. Dieses Paar stellt die Benutzeroberfläche der Anwendung dar, also das, was auch »look and feel« genannt wird. 6 7 8 Hilfreich ist zudem die Auslagerung von Funktionen, die in mehreren JSPs benötigt werden, etwa Suchfunktionen oder Login-Verfahren, die in separaten Komponenten eingeschlossen werden können. 9 Welche Komponenten einer Webanwendung jeweils eine der drei Rollen innerhalb dieses Modells übernehmen, kann je nach den Anforderungen ganz unterschiedlich sein. Der Entwicklung steht hier jedenfalls eine große Bandbreite von Lösungen offen, weil JSP 2.0 mit der Unterstützung von JavaBeans, Tag-Bibliotheken und Tag-Dateien mehrere Methoden anbietet, Funktionen in Komponenten zu kapseln. Außerdem besteht immer die Möglichkeit, JSPLösungen und originäre Servlets miteinander zu verknüpfen. 10 11 12 13 In unternehmensweiten Anwendungen wird es häufig sinnvoll sein, JSP in erster Linie für die View-Rolle, also für die Präsentation und Eingabe von Daten an der Benutzeroberfläche zu verwenden, für die Model-Rolle mit JavaBeans oder Enterprise JavaBeans zu arbeiten und als Controller Servlets zu nutzen. Dabei kann die View-Rolle beispielsweise auch durch eine bestimmte Abfolge von JSPs realisiert werden. 14 Da es in vielen Webanwendungen eine ganze Reihe von immer wiederkehrenden Aufgabenstellungen gibt, entwickelt sich hier ein Markt für Komponenten, der nicht nur Sammlungen von benutzerdefinierten Aktionen anbietet, sondern Frameworks wie Struts, die gleich ein Grundgerüst liefern, das für den konkreten Bedarf aufgefüllt werden kann. Wenigstens einen Blick darauf finden Sie in Abschnitt 5.6. 1.5 Von JSP 1.2 nach JSP 2 Ursprünglich sollte auf JSP 1.2 eine Spezifikation mit der Nummer 1.3 folgen, doch im Laufe des Verfahrens entschied sich die verantwortliche JSR 152Expertengruppe, Teil von JCP (die Abkürzung steht für Java Community Pro- Von JSP 1.2 nach JSP 2 41 cess), für die Nummer 2.0, um deutlich zu machen, dass die neue Version ganz maßgebliche Veränderungen gegenüber den bisherigen Verfahren der Erstellung von dynamischen Webinhalten erlaubt. Wen die Arbeit der Gruppe interessiert, der findet über www.jcp.org Näheres. Wie schon so oft in der Software-Industrie steht die neue Version unter der Hauptforderung, es den Anwendern leichter machen zu sollen als bisher. In diesem Fall insbesondere den Webdesignern, die die Java-Programmierung nicht als ihre Sache betrachten. Inwieweit dies allerdings gelungen ist, muss sich erst noch in der Praxis erweisen. 1.5.1 Plattform und Servlet-API JSP 2.0 erweitert die bisherige Spezifikation, um die Funktionalität der Java 2Plattform in der Standard Edition 1.4 und in der Enterprise Edition 1.4 voll ausnutzen zu können. Außerdem wird das Servlet-API genutzt, das der ServletSpezifikation 2.4 entspricht. Diese Version ist eine konservative Erweiterung der Version 2.3. Sie erlaubt die Verwendung von Filtern nun auch in Zusammenhang mit Request-Dispatchern. Die Unterstützung von HTTP/1.1 ist jetzt vorgeschrieben. Für Deployment-Deskriptoren wurde ein XML-Schema definiert. 1.5.2 JSTL und andere Tag-Bibliotheken Das Hauptmotiv für den Entwurf der JSP 2.0-Spezifikation war der Wunsch, die Entwicklung von dynamischen Webseiten zu vereinfachen. Die Notwendigkeit für Webdesigner, sich mit dem Schreiben von Skripten in Java-Code zu quälen, sollte weitgehend entfallen, auch wenn die Möglichkeit dazu weiter unterstützt wird. Die entsprechende Funktionalität wird dazu in Tags verpackt, die ihm von der Arbeit mit HTML oder XHTML vertraut sind. Die Innereien von Java können dem Designer auf diese Weise verborgen bleiben. Eine wesentliche Rolle spielt hier die im Rahmen des Jakarta-Projekts entstandene JavaServer Pages Standard Tag Library (JSTL), die inzwischen vom JCP spezifiziert und als verbindliche Lösung für viele typische Standardaufgaben in dynamischen Webseiten eingesetzt werden kann. Gleichzeitig ist die Erweiterbarkeit von JSP durch eigene oder auf dem Markt verfügbare zusätzliche Tag-Sammlungen weiter ausgebaut worden. 1.5.3 Expression Language Die zunächst im Rahmen des JSTL-Projekts entwickelte Expression Language (EL) wurde aus der neuen Version 1.1 der JSTL-Spezifikation ausgekoppelt, um 42 JavaServer Pages im Überblick 1 2 sie auch unabhängig von der Tag-Bibliothek verwenden zu können. EL wurde nun direkt in die JSP 2.0-Spezifikation integriert, ein entsprechendes EL-API wurde dem JSP-API hinzugefügt. 3 4 Die Sprache wurde für JSP 2.0 um die Unterstützung von Funktionen erweitert. EL ist in Anlehnung an JavaScript und XPath entstanden und dazu gedacht, die bisher in Form von Skriptelementen verwendeten Ausdrücke zu ersetzen. EL-Ausdrücke in der Form ${ausdruck} können jetzt auch direkt innerhalb des Template-Textes einer JSP vorkommen. Besonders komfortabel ist, dass sich Attributwerte in Aktionen – seien es Standardaktionen oder Aktionen aus zusätzlichen Bibliotheken –, die erst bei der Ausführung der Seite bestimmt werden, über solche Ausdrücke definieren lassen. Die Sprache erlaubt insbesondere auch einen einfachen Zugriff auf die Eigenschaften von JavaBeans. 1.5.4 5 6 7 8 9 Simple Tag-Handler Zusätzlich zu dem bisher verwendeten Aufrufprotokoll für Tag-Handler, das auf die Verwendung von Java-Code zugeschnitten ist, führt JSP 2.0 ein vereinfachtes Protokoll für Tag-Erweiterungen ein, das Simple Tag Extension genannt wird. 10 11 Dieses Protokoll ist in der Erwartung entwickelt, dass in Zukunft bei der Gestaltung von dynamischen Webinhalten ganz auf Skriptelemente in JSPs verzichtet werden kann. Dabei wird es den Autoren solcher Erweiterungen freigestellt, diese auf der Basis von Java-Klassen oder auch direkt in JSP zu definieren. Dafür wird das Konzept der JSP-Fragmente verwendet, die Teilfunktionen in einer Form kapseln, die sie wiederverwendbar macht. 1.5.5 12 13 14 Tag-Dateien Neben dem schon bekannten Erweiterungsmodell auf der Basis von Tag-Bibliotheken wird in JSP 2.0 deshalb parallel eine vereinfachte Form, eigene Tags in die JSP einzubringen, eröffnet, die spezielle Tag-Dateien verwendet. Diese bestehen ausschließlich aus JSP-Elementen, enthalten also keinen Java-Code, sodass auch Designer, die keine Java-Kenntnisse mitbringen, eigene Tags für wiederholt benötigte Funktionen definieren können. 1.5.6 JSP als XML-Dokument und XML-Views Ein allgemeiner Zug der neuen Version ist die deutliche Ausrichtung an XML als Basistechnologie. Die Autoren von JSP-Anwendungen werden dazu ermuntert, JSPs direkt als vollwertige XML-Dokumente zu editieren, um die Vorteile von Werkzeugen nutzen zu können, die XML unterstützen. Gleichzeitig wird intern Von JSP 1.2 nach JSP 2 43 bei der Verarbeitung von JSPs mit einer automatisch generierten XML-Sicht auch der JSPs gearbeitet, die in der älteren Standardsyntax geschrieben sind, wenn Validatoren für die verwendeten Tag-Bibliotheken eingesetzt werden. 1.5.7 Neue Standardaktionen und dynamische Attribute JSP 2.0 erweitert auch die Liste der Standardaktionen, insbesondere um die Elemente <jsp:attribute> und <jsp:body>. Mit Hilfe dieser Elemente lassen sich Werte im Rumpf einer Aktion definieren, anstatt sie im Start-Tag der Aktion unterzubringen. Das ist besonders in Zusammenhang mit Attributen von Bedeutung, deren Name erst während der Ausführung der Seite dynamisch zugewiesen wird. Dynamische Attribute sind ebenfalls eine wichtige Erweiterung von JSP. Dafür wurde in dem Paket javax.servlet.jsp.tagext ein spezielles DynamicAttributes-Interface eingeführt. 1.6 Allgemeine Merkmale von JSP JSP-Anwendungen sind Webanwendungen auf der Basis des HTTP-Protokolls. Um eine solche Webanwendung auszuführen, ist eine wesentlich komplexere Umgebung notwendig als bei einem Programm, das für einen lokalen Rechner geschrieben ist. Bevor die syntaktischen Details der JSP-Programmierung zum Thema werden, soll deshalb ein kurzer Überblick darüber gegeben werden, was überhaupt beim Aufruf von JSP-Anwendungen geschieht. 1.6.1 Laufzeitumgebung für JSP Wenn Autoren eine einfache Webseite in HTML oder XHTML veröffentlichen, legen sie diese Seite auf einem Webserver ab. Wird von irgendeinem Browser die Adresse dieser Seite eingegeben, liefert der Server als Antwort auf die Anfrage die gewünschte Seite genau so an den Client aus, wie die Autoren sie auf den Server gelegt haben. Bei den JavaServer Pages ist auf der Seite des Servers mehr zu tun, als nur die angeforderte Seite abzuliefern. Zunächst wird auch die JSP von den Autoren auf dem Webserver abgelegt. Damit eine JSP ausgeführt werden kann, reichen die Funktionen, die ein Webserver beim Aufruf von statischen HTML-Seiten anbietet, aber nicht aus. Es wird eine Laufzeitumgebung benötigt, die mit JSPs etwas anfangen kann. Auf dem Server wird dazu ein JSP-Container benötigt, eine Servererweiterung für den Umgang mit JSP. Dieser Container sorgt dafür, dass eine JSP in ein Servlet übersetzt wird, das dann wie ein originäres Servlet ausgeführt werden kann. Der JSP-Container wird häufig selbst als ein spezielles Servlet implementiert, 44 JavaServer Pages im Überblick 1 2 das für die Ausführung von JSPs konfiguriert ist und innerhalb eines ServletContainers ausgeführt wird. In anderen Fällen werden ein Servlet-Container und ein JSP-Container auch zu einem Paket kombiniert, das dann insgesamt als Web-Container bezeichnet wird, so wie es auch die JSP 2.0-Spezifikation tut. 3 4 Die JSP-Technologie ist in diesem Sinne also als eine Erweiterung der ServletTechnologie zu verstehen, weshalb es zwischen Servlets und JSP-Lösungen auch grundlegende Gemeinsamkeiten gibt, auch wenn der Quellcode eines Servlets und der Text einer JSP ziemlich verschieden aussehen. 5 6 Ein solcher Servlet-Container kann in verschiedenen Formen realisiert werden. Er kann Teil eines Webservers oder Teil eines Applikationsservers sein. Im ersten Fall ist er entweder direkt in den Webserver integriert oder er wird durch eine Add-onKomponente eingebunden, wenn der Webserver selbst keine genuine Unterstützung für Servlets zur Verfügung stellt. Das ist z.B. bei Apache und bei IIS der Fall. 7 8 9 Ein Container kann aber auch, wie es beispielsweise für Tomcat gilt, als Standalone-Server betrieben werden, der neben normalen HTTP-Funktionen eine Laufzeitumgebung für Servlets und JSPs zur Verfügung stellt. Der Server kann ohne Probleme parallel zu anderen Webservern betrieben werden, solange mit unterschiedlichen Parts gearbeitet wird. 10 11 12 In jedem Fall muss ein JSP-Container das HTTP-Protokoll unterstützen, wobei die Versionen HTTP/1.0 und 1.1 verlangt werden. HTTPS kann hinzukommen. 13 1.6.2 Einbindung in J2EE 14 Wie die schon kurz angesprochene Servlet-Technologie sind auch die JavaServer Pages Teil der Software-Architektur Java 2 Enterprise Edition. Sun Microsystems hat die Java-Welt 1999 neu geordnet, und die gesamte Masse der dazugehörenden Klassenbibliotheken und Pakete in drei Editionen gruppiert: 왘 J2SE ist die Standard-Edition mit den Standard-APIs, die in erster Linie für lokale Desktop-Anwendungen und für Applets, also Komponenten auf der Client-Seite benötigt werden. 왘 J2EE fügt auf der Basis von J2SE zahlreiche Erweiterungen für die Serverseite hinzu, um webbasierte, mehrschichtige unternehmensweite Anwendungen auf der Basis des HTTP-Protokolls zu ermöglichen. Dazu gehört in erster Linie die Einführung von Enterprise JavaBeans (EJB), einer Architekturspezifikation für Serverkomponenten, die mehrschichtige Anwendungen in Java vereinfachen, indem grundlegende technische Aspekte wie Transaktions- und Zustandsverwaltung, Persistenz, Sicherheit, Nebenläufigkeit und Ressourcenverwaltung bereits durch den EJB-Container gewährleistet werden. Allgemeine Merkmale von JSP 45 왘 J2ME, die Micro-Edition ist eine für den Einsatz auf mobilen Geräten wie PDAs, Handys und Pager und in Embedded Systems wie Navigationssystemen abgespeckte Version, deren Kern ein spezielle Variante der Java Virtual Machine, die Kilobyte Virtual Machine (KVM) ist. Die J2EE-Spezifikation, die hier vor allem interessiert, definiert einen Standard, der sich aus einer Anzahl notwendiger APIs und allgemeiner Richtlinien ergibt, die durch einen Applikationsserver unterstützt werden müssen, wenn er die Einstufung »J2EE-kompatibel« erhalten will. J2EE ist kein abgeschlossenes Produkt, sondern die Definition eines Rahmens für Anwendungen auf der Basis eines Komponentenmodells im Sprachraum von Java. Wesentliches Merkmal von J2EE ist, dass die für konkrete Lösungen benötigten Komponenten durch beschreibende Konfigurationsdateien in vielfältiger Weise angepasst werden können, ohne eine Zeile des Quellcodes ändern zu müssen. Diese so genannten Deployment-Deskriptoren werden in Form von XML-Dokumenten gepflegt, für die verbindliche XML-Schemas definiert sind. Auch die Übertragung von Lösungen auf einen anderen J2EE-Server kann im Prinzip ohne Anfassen des Quellcodes allein durch Anpassungen der Deskriptoren vorgenommen werden. Als Laufzeitumgebung für J2EE-Anwendungen werden Container verwendet – Servlet- und JSP-Container beispielsweise –, die den Lebenszyklus der darin angesiedelten Webkomponenten steuern und ihnen standardisierte Dienste zur Verfügung stellen. Die Arbeitsaufteilung zwischen Container und Komponente, die auch Kontrakt genannt wird, ist durch entsprechende Interfaces spezifiziert, etwa das Interface Servlet, das festlegt, in welcher Abfolge der Server in eigener Regie und nicht durch den Anwendungscode die benötigten Methoden aufruft. Jede J2EE-Implementierung muss also den einzelnen Webanwendungen die gleichen Dienste zur Verfügung stellen. Dabei werden die in den Konfigurationsdateien abgelegten Informationen automatisch umgesetzt. Ergänzt wird die J2EE-Spezifikation durch die J2EE-Blueprints (Rezepte und Designmuster für J2EE-Anwendungen), siehe java.sun.com/blueprints/ enterprise, ein J2EE-Server als Referenzimplementierung, der für nichtkommerzielle Tests genutzt werden kann (java.sun.com/j2ee/download.html) und eine J2EE-Testsuite, mit der die Kompatibilität von neuen Anwendungen überprüft werden kann. Unter java.sun.com/j2ee/compatibility.html werden alle Produkte gelistet, die diesen Test bestanden haben. Da JSP vollständig in J2EE eingebunden ist, stehen zahlreiche Dienste der Plattform und die dazugehörigen APIs den Webanwendungen zur Verfügung. Die 46 JavaServer Pages im Überblick 1 2 folgende Tabelle gibt einen kurzen Überblick über wichtige Programmierschnittstellen, die zu J2EE 1.4 gehören bzw. bereits durch J2SE 1.4 zur Verfügung stehen: 3 4 API Beschreibung JDBC 3.0 Standardschnittstelle für den Zugriff auf Datenbanken mit Hilfe von Datenbanktreibern Servlet-API 2.4 Schnittstelle, die von allen Servlets implementiert und die auch für die Ausführung von JavaServer Pages verwendet wird JSP 2.0 Schnittstelle, um JSP-Elemente in eine Webseite zu integrieren, die dynamische Inhalte ermöglicht Enterprise JavaBeans (EJB) 2.1 Erweiterung der JavaBean-Komponententechnik für unternehmensweite, mehrschichtige Anwendungen Java Naming and Directory Interface (JNDI) 1.2 Gemeinsame Schnittstelle, über die Java-Programme J2EENamens- und Verzeichnisdienste nutzen können oder auch LDAP oder NDS. Dadurch kann auf Objekte und Ressourcen jeder Art mit Hilfe von logischen Namen zugegriffen werden. Java Message Service (JMS) 1.1 Ein offener Standard, der den Zugriff auf Message Oriented Middleware (MOM) in Java-Anwendungen erlaubt Java Transaction API (JTA) 1.0 Schnittstelle zur Interaktion mit einem Transaktionsmanager Java Connector Architecture (JCA) 1.5 Schnittstelle für die Anbindung von Enterprise Information Systems (EIS) an J2EE-Anwendungen Java API for XML Processing (JAXP) 1.2 Integriert XML-Parser in J2EE-Anwendungen und implementiert den XSLT-Standard JavaMail 1.3 Schnittstelle für den E-Mail-Versand und Empfang 5 6 7 8 9 10 11 12 13 14 JavaBeans Activation Frame- Bestimmt den Typ von Daten aufgrund der MIME-Spezifikawork (JAF) tion und kann entsprechende Viewer starten. Wird für JavaMail benötigt. Java Authentication & Stellt Verfahren zur Authentifizierung und zur ZugriffskontAuthorization Service (JAAS) rolle zur Verfügung. Basiert auf dem unter UNIX verwendeten Pluggable Authentication Modules. JAX-RPC 1.1 Schnittstelle für die Nutzung von Webdiensten auf der Basis von WSDL und SOAP JAXP 1.2 Das Java API for XML Parsing macht J2EE unabhängig von konkreten Parsern und XSLT-Prozessoren. JAXR 1.0 Das Java API for XML Registries erlaubt den Zugriff auf UDDI und andere Repositorien. Allgemeine Merkmale von JSP 47 API Beschreibung SAAJ 1.2 Das SOAP with Attachments API for Java erlaubt die Bildung und Verarbeitung von Meldungen, die dem SOAP 1.1Standard entsprechen. JSEE Connector Architecture 1.5 Erlaubt die Bildung von Ressourcen-Adaptern, um auf beliebige betriebliche Informationssysteme zugreifen zu können Es soll allerdings nicht verschwiegen werden, dass der Umgang mit den oft tief gestaffelten Kompontenhierarchien in der Java-Welt nicht zu unterschätzende Anforderungen an die Entwicklung von Anwendungen stellt. Wettbewerbe mit Gedächtniskünstlern sind nicht die erste Aufgabe von Website-Entwicklern. Dokumentationen mit einfachen Navigationselementen, »intelligente« Editoren und Entwicklungsumgebungen sind deshalb dringende Erfordernisse für eine effektive Arbeitsweise. 1.6.3 Aufbau einer JSP Ohne hier schon auf Details der Standardsyntax einzugehen, lässt sich der Aufbau einer JSP in den meisten Fällen als eine Mischung aus speziellen JSP-Elementen und Nicht-JSP-Elementen beschreiben, wobei es sich meist um HTML-Code oder einfachen Text handelt. Der Zweck einer JSP ist dabei immer, exakt zu beschreiben, wie eine Anfrage verarbeitet und eine Antwort erzeugt werden soll. In der folgenden Abbildung wird an einem kleinen JSP-Beispiel die Anordnung der unterschiedlichen Elemente durch Markierungen verdeutlicht. Es ist gleich sichtbar, dass die verschiedenartigen Bestandteile der Seite nicht etwa in zwei abgesonderte Bereiche eingeordnet werden müssen, sondern über die Seite verstreut werden können. Der dynamische Inhalt einer Seite wird genau an der Stelle in der Abfolge der Seitenelemente beschrieben, an der er in der Antwort, die der Server generiert, erscheinen soll. Die Reihenfolge von statischen und dynamischen Inhalten wird also durch das Layout der Seite bestimmt. Abbildung 1.6 JSP mit Template-Daten und JSP-Elementen (grau markiert) 48 JavaServer Pages im Überblick 1 2 Diese JSP erzeugt folgende Ausgabe, wenn sie über den Browser aufgerufen wird: 3 4 5 6 7 Abbildung 1.7 Ausgabe der Seite mit statischen und dynamischen Bestandteilen 8 In dem Beispiel werden neben dem HTML-Code eine page-Direktive und eine Standardaktion verwendet, die auf eine JavaBean zugreift, also auf eine Komponente, die außerhalb der JSP definiert ist. Schließlich ist noch ein Ausdruck der neuen Expression Language (EL) enthalten, der für die Ausgabe der Zeitangaben sorgt. 9 10 11 1.6.4 Übersetzungsphase 12 Was geschieht nun, wenn diese Seite, vorausgesetzt, sie ist auf einem Server veröffentlicht, von einem Browser angefordert wird? Wird eine Anfrage für eine JSP von einem Browser abgeschickt, nimmt der auf der Seite des Servers aktive JSP- oder Web-Container – die JSP-Spezifikation verwendet diese beiden Begriffe synonym – die Anfrage entgegen. 13 14 Wird die JSP zum ersten Mal aufgerufen, übersetzt der Container aus dem Text der JSP zunächst den Java-Quellcode für ein entsprechendes Servlet und legt ihn in einer .java-Datei ab. Anschließend kompiliert er daraus eine ServletKlasse und legt sie in einer .class-Datei ab. Dies geschieht automatisch. Übersetzung und Kompilierung zusammen werden als Übersetzungsphase bezeichnet. In dieser Phase können Fehler entdeckt werden, die aber erst angezeigt werden, wenn versucht wird, die JSP auszuführen. Dabei wird für alle JSP-Elemente der entsprechende Java-Code übernommen, um durch die Verarbeitung dieses Codes die dynamischen Bestandteile der Seite zu erzeugen. Dagegen werden die Bestandteile, die keine JSP-Elemente sind, in die schon angesprochenen Java-Ausgabeanweisungen übersetzt, mit denen die entsprechenden statischen Elemente in der Antwort des Servers auf die eingegangene Anfrage fixiert werden. Allgemeine Merkmale von JSP 49 Abbildung 1.8 Übersicht über die Verarbeitung einer JSP-Anfrage 1.6.5 Die JSP-Implementierungsklasse Die aus der JSP generierte Servlet-Klasse wird JSP page implementation class genannt. Der genaue Name der erzeugten Klasse ist von der Implementierung abhängig. Das JSP-Implementierungsobjekt ist dabei Teil eines Pakets, dessen Name ebenfalls von der gewählten Implementierung abhängig ist. (Stattdessen kann für eine Seite auch eine Oberklasse angegeben werden, von der die Klasse abzuleiten ist, und zwar durch ein spezielles extends-Attribut der page-Direktive, was in Abschnitt 3.3 beschrieben wird. Allerdings schränkt dieses Verfahren die Entscheidungsmöglichkeiten des JSP-Containers ein und sollte normalerweise gemieden werden. JSP 2.0 erlaubt es übrigens nicht, mit unbenannten Paketen zu arbeiten, was bei der Übernahme von älteren Anwendungen, in denen so verfahren wurde, zu Fehlern führen kann. Die JSP-Klasse implementiert im Kern das Interface javax.servlet.Servlet, das die grundlegenden Methoden enthält, die von Servlets beherrscht werden müssen. Anfragen werden deshalb genau so an diese Klasse zur Ausführung übergeben, wie es die Servlet 2.4-Spezifikation festlegt. 50 JavaServer Pages im Überblick 1 2 Eine JSP-Implementierungsklasse kann von bestimmten Support-Klassen abhängig sein. Ist die Klasse in eine WAR-Datei verpackt, darauf wird in Abschnitt 4.2 noch im Detail eingegangen, muss jede dieser Klassen eingefügt werden, damit das Paket zwischen allen JSP-Containern portabel bleibt. 3 4 Da die Frage/Antwort-Kommunikation zwischen Client und Server nur über ein von beiden Seiten eingehaltenes Protokoll möglich ist, muss der JSP-Container außerdem sicherstellen, dass ein solches Protokoll verwendet wird. In der Regel ist das HTTP, und deshalb muss die Implementierungsklasse dafür auch das Interface HttpJspPage implementieren, welches eine Erweiterung des Interfaces JspPage ist. 5 6 7 Wird eine Seite, die schon kompiliert ist, später verändert, ist es Aufgabe des Containers, die Seite beim nächsten Aufruf neu zu kompilieren. Verwendet eine Seite Komponenten wie JavaBeans oder inkludierte Seiten, findet allerdings nicht unter allen Umständen eine Neukompilierung statt. Mehr dazu in Abschnitt 3.14. 8 9 10 Die Übersetzungsphase kann auch vom Aufruf der JSP getrennt werden. Dazu kann ein spezieller jsp_precompile-Parameter beim Aufruf der Seite verwendet werden, der den Container veranlasst, die Seite zu übersetzen und zu kompilieren, ohne die darin enthaltene Anfrage auszuführen. 11 12 http://localhost:8080/einstiegjsp/Kapitel1/zeitAnsage.jsp?jsp_ precompile=true 13 Diese Vorkompilierung hat den Vorteil, dass die durch die notwendige Übersetzung bedingte Verzögerung der Serverantwort beim ersten Aufruf einer JSP vermieden werden kann. Mehr dazu in Abschnitt 4.5. 14 1.6.6 Ausführungsphase Ist durch die Übersetzung und Kompilierung ein Servlet erzeugt, das die JSP repräsentiert, kann der JSP-Container alle Anfragen an das Implementierungsobjekt richten, das er als Instanz der JSP-Implementierungsklasse bildet. Dazu ruft der Container das Servlet auf. Es mag so lange im Speicher bleiben, bis der Server heruntergefahren wird, sodass eine Serie von Anfragen verarbeitet werden kann, ohne einen neuen Prozess starten zu müssen. Die Ausführung des Servers erzeugt schließlich auf der Basis der Daten und Anweisungen, die in der Anfrage enthalten sind, die Ausgabe, die als Antwort an den anfragenden Client zurückgeschickt wird. In diesem Prozess werden häufig noch andere Objekte erzeugt oder benutzt. Die JSP kann außerdem noch festlegen, wie auf bestimmte Ereignisse reagiert werden soll. JSP 2.0 Allgemeine Merkmale von JSP 51 kennt allerdings nur die Ereignisse init und destroy, also den Moment, in dem ein Servlet initialisiert wird, und den Moment, in dem das Implementierungsobjekt wieder zerstört wird. Für jede eingehende Anfrage findet der JSP-Container jeweils die passende Instanz der JSP-Implementierungsklasse und übergibt auf der Basis des ServletProtokolls die zugehörigen Anfragen. Die Servlet-Klasse definiert eine Art Kontrakt zwischen dem JSP-Container und der JSP-Implementierungsklasse. Da JSPs in der Regel das HTTP-Protokoll verwenden, wird dieser Kontrakt durch die HttpServlet-Klasse beschrieben. Der JSP-Container macht dabei automatisch eine Reihe von serverseitigen Objekten verfügbar, die implizite Objekte genannt werden. Auf solche Objekte kann während der Ausführung der Seite über Skriptlets und Skriptausdrücke zugegriffen werden, etwa um Daten aus den Anfrage-Headern auszulesen oder um Statusinformationen abzufragen. Auch Ausdrücke der Expression Language haben Zugriff auf implizite Objekte. Die JSP-Spezifikation ist im Prinzip auch für andere Protokolle offen. Verarbeitung einer JSP durch den JSP-Container Das Interface javax.servlet.Servlet stellt die Mittel bereit, damit ein Servlet ausgeführt werden kann. Es stellt die Methoden zur Verfügung, um Eingangswerte für ein Servlet zu setzen, sorgt für die Bedienung der Anfragen und ermöglicht es, das Servlet aus dem Speicher zu entfernen, wenn es seine Dienstleistung abgeschlossen hat. Wie dies genau geschieht, ist normalerweise Sache der jeweiligen JSP-Container-Implementierung, es sei denn, JSP-Autoren legen über das extends-Attribut der page-Direktive eine andere Oberklasse fest. Diese muss dann gewährleisten, dass das Nötige geschieht. Die Methodenabfolge regelt den Lebenszyklus Stellt der Container eine Anfrage durch einen Client fest, wird das entsprechende Servlet, wenn es noch nicht geladen ist, durch einen speziellen Klassenlader in den Speicher geholt. Für jede Anfrage wird normalerweise ein eigener Thread verwendet, sodass auch mehrere Anfragen von einer einzigen Instanz der Implementierungsklasse parallel bearbeitet werden können. Der Container ruft dabei die benötigten Methoden des Servlet-Objekts in einer bestimmten Reihenfolge automatisch auf. Diese Abfolge wird gern Lebenszyklus genannt. Für Servlets, die JSP-Implementierungsklassen sind, werden dabei von Servlet abgeleitete Interfaces verwendet. 52 JavaServer Pages im Überblick 1 2 Über das Interface JspPage stehen die Methoden jspInit() und jspDestroy() zur Verfügung, die der Autor einer JSP überschreiben kann. Über das Interface HttpJspPage, die JspPage erweitert, kommt die jspService()-Methode hinzu, um die Kommunikation zwischen Client und Server zu steuern. Diese Methode wird durch den JSP-Container automatisch definiert, und zwar aufgrund des Inhalts der JSP. Der JSP-Autor kann diese Methode nicht überschreiben. 3 4 5 6 7 8 9 10 11 12 Abbildung 1.9 Abfolge der Methodenaufrufe 13 Da bei jeder Anfrage an eine bestimmte Instanz innerhalb des dafür verwendeten Threads dieselben Methoden verwendet werden, muss bei der Entwicklung einer JSP folglich darauf geachtet werden, dass sich der auszuführende Code immer in derselben Weise verhält, egal ob nur eine Anfrage stattfindet oder gleich mehrere. Der Code muss also Thread-sicher sein. Welche konkreten Anforderung sich daraus ergeben, wird in Abschnitt 3.12 erläutert. 14 Initialisierung Die erste Methode jspInit() wird beim Laden des Servlets genau einmal aufgerufen, und zwar noch vor der Bearbeitung der ersten Anfrage. Bei weiteren Anfragen wird sie also nicht mehr aufgerufen. Sie tut in der Vorgabe zunächst gar nichts. Durch Überschreiben dieser Methode hat der JSP-Autor aber die Möglichkeit, bestimmte Initialisierungen vorzunehmen, etwa das Laden und Erzeugen von Objekten, die für jede Anfrage benötigt werden. Auch lassen sich hier Datenbankverbindungen aufbauen, die von mehreren Anfragen gemeinsam genutzt werden sollen. Dazu können entsprechende Parameter in den Deskriptor-Dateien der jeweiligen Webanwendung abgelegt werden. Die Parame- Allgemeine Merkmale von JSP 53 ter lassen sich an dieser Stelle einlesen und wenn nötig in Instanzvariablen speichern, die während der gesamten Ausführungszeit zur Verfügung stehen. Ist die jspInit()-Methode einmal aufgerufen, sollte die JSP-Implementierung sicherstellen, dass anschließend mit der Methode getServletConfig()auf die Initialisierungs- und Startparameter des Servlets zugegriffen werden kann. Seitenverarbeitung Die eigentliche Arbeit, nämlich aus der JSP-Anfrage eine entsprechende Antwortseite zu erzeugen, wird über die _jspService()-Methode erledigt. Diese Methode wird für jede Anfrage aufgerufen und auf der Basis der Inhalte der JSP automatisch generiert. Die Methode kann, wie schon gesagt, nicht durch Skriptelemente in der JSP überschrieben werden. Um die Kommunikation nach dem Muster Anfrage/Antwort zu steuern, werden entsprechende Parameter verwendet. Der formale Typ der Anfrageparameter – in der JSP 2.0-Spezifikation als <ServletRequestSubtype> bezeichnet – ist durch ein Interface bestimmt, das javax.servlet.ServletRequest erweitert. Entsprechend gilt für die Antwortparameter – <ServletResponseSubtype> - ein Interface, das javax.servlet.ServletResponse erweitert. Diese Interfaces werden durch die Interfaces javax.servlet.http.HttpServletRequest und javax.servlet.http.HttpServletResponse noch um Methoden bereichert, die für das HTTP-Protokoll spezifisch sind. Sie können vor allem protokollspezifische Daten liefern. Das betrifft z.B. das Abfragen der Request-Header mit getHeader() oder von Cookies mit getCookies(). Während HttpServletRequest der Anwendung das Parsen und Dekodieren der HTTP-Anfrage abnimmt, erlaubt HttpServletResponse einen einfachen Zusammenbau der HTTP-Antwort, das Puffern der Ausgabe und das Setzen von Headern und Cookies. Für die Ausgabe werden Stream-Klassen für Textdaten und für binäre Daten zur Verfügung gestellt. Freigabe der Ressourcen Das Servlet kann so lange Anfragen verarbeiten, bis es explizit vom Container aus dem Speicher entfernt wird. Dies geschieht, wenn dieser ein shutdown-Signal erhält. Vor dem Entladen ruft der Container aber noch die Methode jspDestroy() auf. Die Methode jspDestroy() kann überschrieben werden, um Dinge zu veranlassen, die geschehen sollen, bevor die Servlet-Instanz dem Garbage Collector überlassen wird, etwa Einträge in Log-Dateien. Häufig geht es auch um die Freigabe von Ressourcen oder das Schließen von offenen Verbindungen zu Datenbanken. Außerdem können Statusinformationen aus dem 54 JavaServer Pages im Überblick 1 2 ServletContext gespeichert werden, die bis zum nächsten Aufruf des Servlets erhalten bleiben sollen. 3 Die Methode wird in jedem Fall erst ausgeführt, wenn alle Threads, die _jspservice()-Methoden ausführen, beendet sind, also spätestens, wenn der Server heruntergefahren wird. 4 5 Während die jspInit()-Methode, falls der JSP-Autor sie überschreibt, in jedem Fall zum Zuge kommt, ist das bei der jspDestroy()-Methode nicht so sicher. Es kann vorkommen, dass der Server crashed und es nicht mehr zur Ausführung der Methode kommt. 6 1.6.7 8 7 Quellcode des Beispiels Der Quellcode des Servlets, das der JSP-Container aus der kleinen JSP erzeugt, zeigt die Umsetzung des Inhalts der JSP in den Java-Code einer Servlet-Klasse. Die Datei wird unter Tomcat zusammen mit der kompilierten Klasse in einem Unterverzeichnis von $CATILINA/work abgelegt. 9 10 Der Name der Java-Datei übernimmt dabei den Dateinamen der JSP-Datei und erweitert ihn um das Suffix _jsp, aus zeitAnsage.jsp wird also zeitAnsage_ jsp.java und zeitAnsage_jsp.class. 11 12 package org.apache.jsp.Kapitel1; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class zeitAnsage_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static java.util.Vector _jspx_dependants; public java.util.List getDependants() { return _jspx_dependants; } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { JspFactory _jspxFactory = null; PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Allgemeine Merkmale von JSP 13 14 55 Object page = this; JspWriter _jspx_out = null; try { _jspxFactory = JspFactory.getDefaultFactory(); response.setContentType("text/html"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write('\r'); out.write('\n'); out.write("<html>\r\n\t"); out.write("<head>\r\n\t\t"); out.write("<title>Say the time"); out.write("</title>\r\n\t"); out.write("</head>\r\n\t"); out.write("<body>\r\n\t\t"); java.util.GregorianCalendar now = null; synchronized (pageContext) { now = (java.util.GregorianCalendar) pageContext.getAttribute("now", PageContext.PAGE_SCOPE); if (now == null){ try { now = (java.util.GregorianCalendar) java.beans.Beans.instantiate(this.getClass().getClassLoader(), "java.util.GregorianCalendar"); } catch (ClassNotFoundException exc) { throw new InstantiationException(exc.getMessage()); } catch (Exception exc) { throw new ServletException("Cannot create bean of class " + "java.util.GregorianCalendar", exc); 56 JavaServer Pages im Überblick 1 2 } pageContext.setAttribute("now", now, PageContext.PAGE_SCOPE); 3 4 } } out.write("\r\n\t\t"); out.write("<p>The time is: "); out.write("</p>\r\n\t\t"); out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${now.time}", java.lang.String.class, (PageContext)pageContext, null, false)); out.write('\r'); out.write('\n'); out.write(' '); out.write("</body>\r\n"); out.write("</html> \t\r\n \t\r\n \r\n "); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) out.clearBuffer(); if (pageContext != null) pageContext.handlePageException(t); } } finally { if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext); } } } 5 6 7 8 9 10 11 12 13 14 Die Implementierungsklasse des Beispiels wird in der Tomcat-Umgebung als Erweiterung der Klasse HttpJspBase erzeugt, die zu dem Paket org.apache.jasper.runtime gehört. Diese Klasse wird für alle Servlets verwendet, die aus einer JSP generiert werden. Sie implementiert die schon angesprochenen Interfaces javax.servlet.jsp.HttpJspPage, javax.servlet.jsp.JspPage, javax.servlet. Servlet, javax.servlet.ServletConfig und zusätzlich java.io.Serializable. Allgemeine Merkmale von JSP 57 Da in der JSP keine Überschreibungen für die Methoden jspinit() und jspdestroy() vorhanden sind, wird nur die Methode _jspService() verwendet, um die Antwort auf die Anfrage zu erzeugen. Zunächst werden eine Reihe von Objekten initialisiert, die die JSP als implizite Objekte für Skriptelemente anbietet. Dann wird die getDefaultFactory()Methode verwendet, um Instanzen für die Interfaces und Klassen zu erzeugen, die für die Implementierung des JSP-Objekts benötigt werden. Die in der ersten Zeile der JSP enthaltene page-Direktive, die hier den MIME-Typ der Seite bestimmt, legt in diesem Fall das Argument der setContenType()-Methode des response-Objekts fest. Ist das Objekt pageContext gebildet, werden Methoden dieses Objekts benutzt, um andere Objekte zu erzeugen: application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); Die Bedeutung dieser Objekte wird in Abschnitt 3.6 näher erläutert. Anschließend werden die in der JSP vorkommenden Template-Elemente und die verschiedenen JSP-Elemente in der dort gegebenen Reihenfolge verwertet, um den Datenstrom zusammenzufügen, der die Antwort des Servers auf die Anfrage erzeugt. Mit Hilfe der getOut()-Methode des PageContext-Objekts wird der aktuelle Wert des impliziten out-Objekts festgestellt, das eine Instanz der JspWriter-Klasse ist, mit der die Ausgaben an den Browser erzeugt werden. Der Jspwriter arbeitet ähnlich wie ein PrintWriter, kann aber Daten auch zwischenspeichern. Um aus den vorhandenen Anfrageobjekten die entsprechenden Antwortobjekte zu gewinnen, werden bestimmte Umwandlungen vorgenommen. Für jedes Template-Element wird eine Java-Anweisung, wie z.B. out.write("<html>\r\n\t"); verwendet, um es in die Antwortseite einzubauen. Die in der Seite vorkommenden Standardaktionen, die hier die Verwendung einer JavaBean betreffen, werden durch den entsprechenden Java-Code ersetzt. Aus dem EL-Ausdruck ${now.time} wird beispielsweise der Java-Code: 58 JavaServer Pages im Überblick 1 2 out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${now.time}", java.lang.String.class, (PageContext)pageContext, null, false)); 3 4 Der Vergleich zwischen dem Code der JSP und dem Code des daraus generierten Servlets dürfte die Einschätzung bestätigen, dass es für die Entwicklung von Webanwendungen durchaus vorteilhaft ist, wo möglich von der Kodierung von Servlets zum Editieren von JSPs überzuwechseln. 5 6 Da die Übersetzung der JSP in den Java-Code des entsprechenden Servlets automatisch abläuft, muss sich der JSP-Autor um das Ergebnis in der Regel auch nicht unbedingt kümmern. Zum Lernen oder bei der Suche nach Fehlern, die bei der Ausführung der Seite gemeldet werden, ist es aber häufig sinnvoll, sich den generierten Code anzusehen, um dort Hinweise auf die Ursachen des Fehlers zu finden. 7 Werden andere JSP-Implementierungen verwendet, kann es zu leichten Abweichungen in der Übersetzung kommen. Bei anderen Containern muss eventuell die Option zum Speichern des Quellcodes erst eingeschaltet werden. 10 8 9 11 12 13 14 Allgemeine Merkmale von JSP 59 Index A B <auth-constraint> 404 <auth-method> 404 Accept 24 Accept-Charset 24 Accept-Charset-Header 320 Accept-Encoding 24 Accept-Language 24 Accept-Language-Header 316, 320 Accept-Ranges 28 Achsenbezeichner 218 Active Server Pages 35 addCookie() 293 Aktion 557 benutzerdefiniert 557 Standard 557 Aktionen 90 <jsp:attribute> 180 <jsp:body> 182 <jsp:doBody> 185 <jsp:element> 178 <jsp:fallback> 178 <jsp:forward> 169 <jsp:getProperty> 196 <jsp:include> 162 <jsp:invoke> 183 <jsp:param> 172 <jsp:params> 178 <jsp:plugin> 173 <jsp:setProperty> 197 <jsp:text> 185 <jsp:useBean> 190 ancestor 219 Anfrage 21, 557 Parameter 25 Antwort 21 Antwort-Header 26 Apache 557 Apache Jakarta Project 64 API 557 Applet 176 application 140, 144, 290, 491 applicationScope 152, 492 Applikationsserver 557 at-end scoped variables 202 Attribut 557 Attribute 91 attribute-Direktive 465 Attributwerte 162 Ausdruck 131, 557 Ausdrücke 115 Authentifizierung 401 autoFlush 147 Autorisierung 401 <body-content> 420 <button> 263 BodyTag 432 BodyTag-Interface 427 BodyTagSupport 433 BodyTagSupport-Klasse 428 Browser. 21 Bytecode 557 C <c:catch> 209, 511 <c:choose> 210, 515 <c:forEach> 211, 358, 516 <c:forTokens> 212, 517 <c:if> 210, 514 <c:import> 109, 213, 518 <c:otherwise> 210, 516 <c:out> 206, 358, 511 <c:param> 213, 521 <c:redirect> 213, 520 <c:remove> 206, 513 <c:set> 207, 291, 512 <c:url> 301, 519 <c:when> 210, 515 <Connector> 73 <Context> 75, 76 <context-param> 144, 394 CallableStatement 368 Cascading Stylesheets 558 CATALINA_HOME 68 CGI 29, 30, 558 CGI-Skript 558 child 219 Class.forName() 349 CLASSPATH 424 Client 21 Common Gateway Interface 29 config 140, 148, 491 conf-Verzeichnis 350 Connection 24 Connection Pooling 384 Container-Element 558 Content-Length 28 Content-Type 28 contentType 314, 485 Controller 40 Cookie 558 getCookies() 295 setMaxAge() 295 cookie 152, 492 Cookie-Header 293 Cookies 292 CREATE TABLE 329 Index 569 createStatement() 341, 364 CSS 558 D <DefaultContext> 352 <distributable> 394 DatabaseMetaData 380, 381 DataSource 347 Datenquellen 347 DDL 328 defaultHost 73 Deklaration 487, 558 Deklarationen 115, 116 deleteRow() 373 Deployment Descriptor 352 descendant 219 DHTML 35, 559 Direktive 483, 558 include 105, 108 page 95, 483 page autoFlush 98 page buffer 98 page charset 105 page contentType 103 page errorPage 100 page extends 96 page import 97 page info 99 page isELIgnored 105 page isErrorPage 100 page isThreadSafe 99 page pageEncoding 105 page session 97 taglib 110 taglib prefix 112 taglib tagdir 110 taglib uri 110 Direktiven 90, 95 dirty read 379 distributed container 558 DML 328 doAfterBody() 431, 433 doEndTag() 428, 430 doInitBody() 432 Dokumenttyp-Definition 559 doStartTag() 423, 429 doTag() 428, 438, 439 Dynamic HTML 559 Dynamisches Attribut 559 E <el-ignored> 407 <embed> 178 <Engine> 73 <env-entry> 408 <error-page> 101, 400 ECMA 560 ECMAScript 149, 493 570 Index einfache Tag-Handler 438 EJB 47, 559 EL 42, 149, 491 API 150 deaktivieren 159 Delimiter 151 Empty Operator 494 empty-Operator 155 fn:contains 158, 547 fn:containsIgnoreCase 158, 547 fn:endsWith 158, 548 fn:escapeXml 158, 548 fn:indexOf 158, 549 fn:join 158, 549 fn:length 158, 550 fn:replace 158, 550 fn:split 158, 551 fn:startsWith 158, 551 fn:substring 158, 552 fn:substringAfter 158, 552 fn:substringBefore 159, 553 fn:toLowerCase 159, 554 fn:toUpperCase 159, 554 fn:trim 159, 554 Funktionen 157, 453, 495 Implizite Objekte 152, 492 in Attributen 151 JSTL-Funktionen 158 Literale 492 Operatoren 155, 493 Syntax 154, 492 Template-Text 149 Typumwandlung 160 Zugriff auf JavaBeans 149 EL-API 43 EL-Ausdruck 91, 149, 559 Element 559 Elemente 91 ELExection 160 ELParseException 160 encodeRedirectURL() 300 encodeURL() 300 End-Tag 90 Enterprise JavaBeans 559 Entität 560 Entitätsreferenz 560 Entity 560 errorPage 387 exception 101, 140, 148, 491 execute() 364 executeBatch() 364 Expression 150 Expression Language 42, 491 ExpressionEvaluator 150 F <filter> 312, 397 <filter-mapping> 310, 398 <fmt:bundle> 232, 322, 543 <fmt:formatDate> 228, 539 <fmt:formatNumber> 228, 535 <fmt:message> 232, 323, 545 <fmt:param> 232, 323, 546 <fmt:parseDate> 228, 540 <fmt:parseNumber> 228, 537 <fmt:requestEncoding> 232, 546 <fmt:setBundle> 232, 323, 544 <fmt:setLocale> 232, 322, 544 <fmt:setTimeZone> 228, 542 <fmt:timeZone> 228, 542 <form> 254 action 259 method 259 <form-login-config> 404 Fehlermeldungen 386 Fehlerseite 101, 400 Filter 309, 397 FilterChain 310 FilterConfig 310 Filter-Kette 309 Filterkette 398 findAncestorWithClass() 438 findAttribute() 143 findColumn() 374 flush() 147 following 219 Formular 560 Formularauswertung 264 Formulare 254, 266 versteckte Felder 301 Fragmentbezeichner 560 Framework 560 FunctionMapper 150 G Geltungsbereich 138, 289 application 139 page 138 request 138 session 139 GenericServlet 32, 286 getAttribute() 143, 290 getAttributeNames() 144, 290 getBeanInfo() 273 getContext() 94 getEnclosingWriter() 435 getErrorData() 102 getInitParameter() 148 getJspBody() 438 getLocales() 320 getOut() 58 getPageContext() 143 getParameter() 264 getRequest() 143 getResponse() 143 getResultSet() 365 getServletConfig() 54 getServletContext() 148, 310 getSession() 304 getString() 347 getUpdateCount() 365 getVariableResolver() 151 getWriter() 146 H <Host> 73 header 152, 492 headerValues 152, 492 Host 24 HTML 35, 561 Formulare 133 htmlf 108 HTTP 20, 560 GET-Methode 23 Header 22, 23 POST-Methode 23 request-line 23 Ressourcen 23 Statuscodes 27 status-line 23 verbindungsloses Protokoll 21 zustandsloses Protokoll 22 HTTP/1.0 20 HTTP/1.1 20, 315 HTTP-Authentifizierung 404 HTTP-Port 21 HTTP-Protokoll 20, 297 HTTPServlet 32 HttpServlet 286 HttpServletRequest 293 HttpServletResponse 293 HttpSession 302 Objekte anbinden 304 HttpSessionBindingListener 305 HTTP-Statuscode 102 I I18N 316 <include-prelude> 109 <include-coda> 109, 408 <include-prelude> 408 <init-param> 394 <input> 262 <is-xml> 407 IANA 314 IETF 561 IETF) 20 IIS) 31 Implizites Objekt 139, 490, 561 Include-Direktive 485 Inhaltsmodell 561 initParam 152, 492 insertRow(), 373 Instanzvariable 117 Index 571 Interface 561 Introspektion 272 invalidate() 306 invoke() 184, 439 ISAPI 31 isELIgnored 464, 485 isErrorPage 387 ISO/IEC 10646 313 ISO-639 317 ISO-8859 105, 313, 314 isUserInRole() 403 IterationTag 431 IterationTag-Interface 427 J J2EE 45, 561 J2EE 1.4 47 j2ee_1_4.xsd 392 J2EE-Blueprints 46 J2EE-Spezifikation 46 J2ME 46, 561 J2SE 45, 63 _jspService() 119 <jsp:attribute> 44, 245, 507 <jsp:body> 44, 508 <jsp:declaration> 116, 247 <jsp:directive.attribute> 247 <jsp:directive.tag> 247 <jsp:directive.variable> 247 <jsp:doBody> 462, 509 <jsp:element> 245, 506 <jsp:expression> 131 <jsp:fallback> 176, 503 <jsp:forward> 398, 497 <jsp:getProperty> 504 <jsp:include> 498 <jsp:invoke> 462 <jsp:output> 245, 510 <jsp:param> 499 <jsp:params> 502 <jsp:plugin> 500 <jsp:root> 241, 460, 496 <jsp:setProperty> 505 <jsp:text> 244, 497 <jsp:useBean> 138, 503 <jsp-config> 109, 405 <jsp-file> 395 <jsp-property-group> 405, 407 JAAS 47, 562 JAF 47 Jakarta-Projekt 562 jar 412 JAR-Archiv 562 Java 562 Java Community Process 42, 562 Java RMI 562 Java Server Faces, 417 Java Server Pages 36, 562 572 Index java.lang.reflect 273 java.sql 333 java.util.locale 317 JAVA_HOME 63 JavaBean 186 JavaBeans 91, 271, 562 Designmuster 274 kompilieren 284 Konstruktor 275 package 284 Plazierung 284 Serialisierung 275 Zugriffsmethoden 273 javac 63 Java-Code 115 Javadoc 422 JavaMail 47, 562 JavaScript 562 JavaServer Pages Standard Tag Library 42 javax.servlet.Filter 309 javax.servlet.jsp.tagext 427 javax.servlet.Servlet 50, 286 javax.sql 333, 335 JAX 563 JAXP 47 JAXR 47 JAX-RPC 47 JCA 47, 563 JCP 41, 203, 562 JDBC 47, 328, 330, 563 close() 377 commit() 378 DataSource 338 Datenübernahme 374 DriverManager 338 executeQuery() 341 executeUpdate() 341 getConnection() 339 Isolierungsgrade 379 rollback() 378 setAutoCommit() 379 statement 341 Typkonvertierung 376 URL-Syntax 340 JDBC 3.0 337 JDBC 3.0 Spezifikation 335 JDBC-API 330 JDBC-ODBC-Brücke 332 JDBC-Treiber 330 JDNI-Pfad 409 JMS 47 JNDI 47, 348, 408, 563 java:comp/env 408 Ressourcenfabrik 350 JNDI API 350 JSP 36, 38, 562 Aktionen 161 Anwendungsgebiete 39 Ausführungsphase 51 Implementierungsklasse 50, 57 Initialisierung 53 Komponenten 105 Laufzeitumgebung 44 Lebenszyklus 52 relative Pfade, 94 Servlet-Klasse 55 Standardsyntax 87 Syntax 48 Tools 83 Übersetzungsphase 49 Verzeichnisstruktur 78 XML-Ansicht 249 XML-Syntax 87 JSP 1.2 41 JSP 2.0 42, 392 JSP 2.0-Spezifikation 45 JSP Implementierungsklasse 563 jsp_2_0.xsd. 392 JSP-API 43 jsp-api.jar 424 JSP-Container 44, 183, 563 JspContext 151, 431 JSP-Datei 563 jspDestroy() 53, 54, 119 JSP-Dokument 232, 314, 563 Template-Text 243 Wurzelelement 241 xmlns-Attribut 242 JSP-Dokumente 43, 241 JSP-Element 138 JSP-Elemente 88 jspf 108 JSP-Fragment 183, 439, 563 JSP-Fragmente 183 jspInit() 53, 119 JSP-Konfiguration 405 JspPage 53 JSP-Segment 563 jspService() 53 JSP-Spezifikation 417 JspWriter 58 JSR 563 JSR 152 41 JSTL 42, 201, 357, 510, 566 Format-Tags 228 SQL-Tags 227 JSTL 1.0 203 JSTL 1.1 203 JTA 47 JVM 34, 564 Konstruktor 564 Kontextknoten 218, 220 Kontextpfad 77 L <listener> 397 <load-on-startup> 396 <locale-encoding-mapping> 401 <Logger> 74 <login-config> 404 Ländercodes 318 Last-Modified 28 Listener 397, 564 Locale 317 localhost 71 log() 146 Log-Dateien 71, 120 Lokalisierungsstufe 218 M <mime-mapping> 399 <mime-type> 399 Markup 564 Maskierungen 481 Metadaten 564 META-INF 111 MIME-Typ 104, 399, 564 Model 40 Model-View-Controller 39, 276, 564 Multithreading oder 251 MySQL 342 CREATE DATABASE 342 CREATE TABLE 342 Treiber 343, 352 N name-from-attribute 466 name-given 466 Namensraum 565 Nebenläufigkeit genannt 251 nested scoped variables 202 node() 220 node-set 216 NSAPI 31 NullPointerException 160 O <object> 178 Objekt 565 Objekte 138 ODBC 331, 565 out 140, 146, 491 out.print() 122 K Klasse 564 Klassenvariable 117 Knotenmenge 216, 218 Kommentare 91, 482 P <page-encoding> 407 page 140, 148, 491 PageContext 58, 138, 290, 429 Index 573 pageContext 140, 143, 152, 490, 492 page-Direktive errorPage 485 import 484 isErrorPage 485 session 484 pageEncoding 314, 464, 485 pageScope 152, 492 param 152, 492 ParameterMetaData 381, 382 paramValues 152, 492 parent 219 Parser 565 PATH 63 PCDATA 565 Perl 565 phantom reads 379 PHP 565 PL/SQL 368 Plug-In 565 PooledConnection 384 Pooling 336 Port-Nummer 565 preceding 219 PreparedStatement 366 prepareStatement() 366 Principal 565 Property-Datei 323 PropertyEditor 162 R <resource-ref> 352 <Realm> 74 <res-auth> 409 <Resource> 352 <ResourceParams> 352 <resource-ref> 409 <res-type> 409 <role-link> 403 <role-name> 403 <rtexprvalue> 420 Referenzimplementierung 565 removeAttribute() 144, 277, 305 Renderer 566 request 21, 139, 141, 289, 490, 557 request.getHeaderNames() 141 request.getParameter() 141 request.getRequestURI() 141 RequestDispatchern 398 requestScope 152, 492 ResourceBundle 321 response 21, 140, 142, 490 response.getOutputStream() 142 response.getWriter() 142 Ressourcenbündel 321 ResultSet 334, 347, 364, 370, 373 resultSetConcurrency 371 ResultSetMetaData 381, 382 574 Index resultSetType 370 RFC 2109 294 RowSet 336, 378 S <scripting-invalid> 407 <security-constraint> 402 <security-role> 402 <security-role-ref> 403 <Server> 73 <Service> 73 <servlet> 394, 395 <servlet-class> 395 <servlet-mapping> 396 <servlet-name> 396 <session-config> 394 <session-timeout> 306, 394 <sql:dateParam> 227, 533 <sql:param> 227, 362, 533 <sql:query> 227, 358, 530 <sql:setDataSource> 228, 358, 529 <sql:transaction> 227, 534 <sql:update> 227, 532 SAAJ 48 scope 138, 184, 194 scoped variables 202 scriptless 464 self 219 sendRedirect() 300 Serializable 275 Server 28 server.xml 71, 350, 405 Servererweiterung 31 Servlet 31, 286, 566 CLASSPATH 287 destroy()-Methode 286 init()-Methode 286 kompilieren 286 Lebenszyklus 286 plazieren 287 service()-Methode 286 Servlet-API 31, 47, 286, 290 servlet-api.jar 286, 424 Servlet-Container 32 ServletContext 55, 94, 304 Servlet-Spezifikation 32, 393 Servlet-Spezifikation 2.4 42 Session 298 JSESSIONID 299 session 140, 143, 289, 490 getID() 304 invalidate() 303, 308 isNew() 303 Session-ID 300 sessionScope 152, 492 setAttribute() 143, 290 setBodyContent() 428, 432 setContentType() 103, 322 Set-Cookie-Header 293 setJspBody() 439 setLocale() 322 setPageContext() 429 setParent() 429 SGML 566 Simple Tag-Handler 43 SimpleTag-Interface 427, 438 SimpleTagSupport 438 SimpleTagSupport-Klasse 428 SingleThreadModel 117, 251 Sitzung eröffnen 303 Sitzungs-ID 302 Sitzungsverfolgung 298 Skriptausdruck 488 Skriptelement 90, 114, 487, 566 Skriptlet 120, 489, 566 Schleifen 126 Template-Text 122 Variable 121 Verzweigung 125 Skriptlets 115 SOAP 566 Sprachcodes 317 SQL 328 Batch-Updates 365 INSERT 353 SQL-Anweisung 329 SQLException 366, 383 SQL-Operator 362 sql-Skript 343 SQL-Typen 334 SSL 302 Standardaktionen 161 Start-Tag 90 stored procedures, 367 Struts 476 Synchronisierung 252 T <tag> 110 <tag-class> 111, 420 <taglib> 110, 405, 420 <taglib-uri> 406 <textarea> 263 Tag 566 Tag Library Descriptor 110, 417, 445, 566 Tag-Bibliothek 418, 566 Tag-Datei 43, 418, 459 Direktiven 463 installieren 461 JSP-Fragmente 475 Syntax 462 tag-Direktive 463 Variablensynchronisierung 467 tagdir 487 TagExtraInfo 446 Tag-Handler 418, 421, 426, 566 Tag-Interface 427 taglib-Direktive 446, 455, 486 TagLibraryValidator 249, 446, 458 Tags benutzerdefinierte 417 TagSupport-Klasse 428 TCP/IP 20 TCP/IP-Socket 21 Template-Daten 88, 566 Template-Element 58 Template-Text 91 text() 220 Thread 33, 566 Throwable 387 Throwable-Objekt 102 TLD 110, 417, 442, 445, 446, 566 <attribute> 451 <body-content> 450 <dynamic-attributes> 452 <fragment> 452 <function> 495 <rtexprvalue> 451 <tag-class> 449 <tag-file> 461 <taglib> 447 <tlib-version> 448 <uri> 448 <variable> 450 impliziter Deskriptor 461 installieren 454 TLD-Datei 419 Token 567 Tomcat 64 installieren 65 konfigurieren 66 Manager-Anwendung 413 Verzeichnisse. 67 webapps-Verzeichnis 411 tomcat-users.xml 405 toString() 229 Transaktionsverarbeitung 378 try/catch-Blöcke 124 T-SQL 368 U <url-pattern> 396, 407 <user-data-constraint> 403 Unicode 313, 567 Uniform Resource Identifier 567 Uniform Resource Locator 567 updateRow() 373 URI 567 uri 487 URL 23, 567 Escape-Codes 25 URL-Kodierung 261 URL-Rewriting 304 Index 575 URL-Syntax 25 URL-Umschreibung 299 User-Agent 24 UTF-16 313 UTF-32 313 UTF-8 105, 313 V Validierung 248, 567 valueBound() 305 valueUnbound() 305 var 184 Variable 138 variable-Direktive 466 VariableResolver 150 varReader 184 Vererbung 567 verteilte Webanwendung 567 Verzeichnis 336 View 40 Vorbereitetes SQL 365 W <web-app> 393 <web-resource-collection> 402 <welcome-file-list> 400 WAR 74, 568 archivieren 412 installieren 413 WAR-Archiv 391, 411 wasNull() 377 Web Application Archive 74, 568 Web services 568 web.xml 75, 76, 111, 204, 306, 352, 391, 409 Webanwendung 44, 567 web-app_2_4.xsd 392 webapps 77 Web-Dienste 568 WEB-INF 111, 421 WEB-INF/tags 461 Webseite 568 Webserver 568 Website 568 Wohlgeformtes XML 568 work-Verzeichnis 386 Wrapper-Klasse 291 Wurzelverzeichnis 78 X X/Open SQL CLI, 331 <x:choose> 225, 524 <x:forEach> 224, 225, 525 <x:if> 225, 524 <x:otherwise> 225, 525 <x:out> 224, 523 <x:param> 226, 528 <x:parse> 223, 522 <x:set> 225, 523 576 Index <x:transform> 223, 225, 526 <x:when> 225, 525 XHTML 560 XML 214, 560 Datentypen 558 Document Object Model 559 Dokumentelement 558 Dokumentinstanz 558 Dokumentmodell 559 Dokumenttyp-Deklaration 559 DOM 559 DOM-Schnittstelle 240 DTD 239, 559 Infoset 561 Knoten 564 Komplexer Datentyp 564 Markup 234 Namensräume 237 Namensraum-URI 237 Parser 240 QName 565 QNames 237 Syntax 236, 557 Tags- 236 Transformationen 225 Wohlgeformtheit 239 Wurzelelement 393, 568 Wurzelknoten 568 XML Schema 568 XML-Deklaration 569 XML-Dokument 232, 569 XML-Dokumente 215 XML-Elemente 246 xmlns 113 xmlns-Attribute 393 XML-Prozessor 569 XML-Schema 42, 239, 392 XPath 43, 91, 149, 215, 569 Achsen 219 Attributknoten 216 DOM 216 Elementknoten 216 Funktionen 220 Knotenmengenfunktionen 221 Knotentest 219 Kommentarknoten 217 Logische Functionen 222 Lokalisierungspfad 217 Namensraumknoten 217 Numerische Funktionen 222 Prädikate 220 Prozessoren 220 Schreibweise 218 String-Funktionen 221 Textknoten 216 Verarbeitungs-anweisungsknoten 217 Wurzelknoten 216 XSL 569 XSLT 240, 569