Ein eigenes Servlet Lernen der Mechanismen Nichts Kompliziertes, sondern einfaches Servlet, das »Hello World« mit Datum und Uhrzeit ausgibt Einige Vorarbeiten (einmalig): Verzeichnisstruktur erstellen Servlet schreiben Servlet übersetzen Klasse an die richtige Stelle kopieren Deployment descriptor einrichten Web−Anwendungen mit Java 101 Verzeichnisstruktur erstellen Verzeichnisse unterhalb von webapps enthalten Web−Anwendungen. ROOT ist eine Web−Anwendung. Jede Web−Anwendung benötigt das spezielle Verzeichnis WEB−INF mit Metainformationen und internen Daten der Web−Anwendung. web.xml: Deployment descriptor classes/de/rainer_klute/servlet/Hello.class: Servlet Web−Anwendungen mit Java 102 Verzeichnisstruktur erstellen Konfiguration in conf/server.xml spezifisch für Tomcat. Dateisystemstruktur der Web− Applikationen durch Servlet− Spezifikation definiert. Web−Anwendungen mit Java Andere Server, andere Konfigurationsmechanismen 103 Java−Quellen könnten auch an anderem Ort stehen. Servlet übersetzen Für die Übersetzung müssen die Klassen des Servlet−APIs im Classpath enthalten sein. cd webapps/ROOT/WEB−INF/src/de/rainer_klute/servlet javac −classpath /opt/local/tomcat/common/lib/servlet.jar Hello.java CLASSPATH="/opt/local/tomcat/common/lib/servlet.jar" export CLASSPATH javac Hello.java Web−Anwendungen mit Java 104 Servlet übersetzen Tomcat sucht Servlets im Verzeichnis WEB−INF/classes der Web−Applikation. mkdir −p [tomcat]/webapps/ROOT/WEB− INF/classes/de/rainer_klute/servlet mv Hello.class [tomcat]/webapps/ROOT/WEB− INF/classes/de/rainer_klute/servlet Klassendatei unmittelbar in WEB−INF/classes generieren cd webapps/ROOT/WEB−INF mkdir classes javac −classpath /opt/local/tomcat/common/lib/servlet.jar −d classes src/de/rainer_klute/servlet/Hello.java Web−Anwendungen mit Java 105 Deployment descriptor erstellen Datei WEB−INF/web.xml Beschreibt Struktur und Eigenschaften einer Web−Anwendung XML−Datei DTD (Document Type Definition) definiert die Syntax. Idealerweise mit syntaxgesteuertem XML−Editor bearbeiten Emacs mit PSGML−Modus Web−Anwendungen mit Java 106 Deployment descriptor erstellen <?xml version="1.0" encoding="ISO−8859−1"?> <!DOCTYPE web−app PUBLIC "−//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web−app_2_2.dtd"> <web−app> <!−− Macht Servlet dem Servlet−Container bekannt: −−> <servlet> <servlet−name>Hello</servlet−name> <servlet−class>de.rainer_klute.servlet.Hello</servlet−class> </servlet> <!−− Ordnet das Servlet einem URL−Muster zu: −−> <servlet−mapping> <servlet−name>Hello</servlet−name> <url−pattern>/Hello</url−pattern> </servlet−mapping> <servlet−mapping> <servlet−name>Hello</servlet−name> <url−pattern>/World</url−pattern> </servlet−mapping> </web−app> Web−Anwendungen mit Java 107 Servlet testen Tomcat neu starten URI http://localhost:8080/Hello abrufen: Web−Anwendungen mit Java 108 Servlets automatisch neu laden Tomcat kann neue Versionen von Servlet−Klassen erkennen. Automatisches Laden einer neuen Servlet−Version ohne Tomcat−Neustart Sehr nützlich während der Entwicklung Performance−Bremse in der Produktion, weil Tomcat Änderungen überprüft Voreinstellung: kein automatisches Laden Web−Anwendungen mit Java 109 Servlets automatisch neu laden In conf/server.xml ändern: −−− server.xml.orig Fri Mar 1 23:49:40 2002 +++ server.xml Sat Mar 9 19:07:05 2002 @@ −158,6 +158,10 @@ <!−− Define the default virtual host −−> <Host name="localhost" debug="0" appBase="webapps" unpackWARs="true"> + + + + <!−− Define the default configuration for all contexts of this host. −−> <DefaultContext reloadable="true"/> <!−− Normally, users must authenticate themselves to each web app individually. Uncomment the following entry if you would like a user to be authenticated the first time they encounter a Festlegungen gelten als Voreinstellungen für alle Web− Applikationen desselben Hosts. Bei Änderungen des Deployment descriptors (WEB−INF/web.xml) Tomcat neu starten! Web−Anwendungen mit Java 110 Manager−Applikation Weitergehende Funktionen als Reload Neue Web−Anwendung laden (»deployen«) Beliebiger Context−Path Beliebige Quelle (Verzeichnis oder WAR−Datei) Web−Anwendungen neu laden Web−Anwendungen und Anzahl der Sessions anzeigen Web−Anwendung entladen (»undeploy«) Web−Anwendung anhalten, aber nicht entladen Angehaltene Web−Anwendung neu starten Web−Anwendungen mit Java 111 Manager−Applikation Manager−Applikation nach ${CATALINA_BASE}/webapps kopieren manager/WEB−INF/web.xml Aktiviert Tomcat−interne Servlets Benutzer mit Rolle »manager« eintragen Beispielsweise bei MemoryRealm: <tomcat−users> <user name="tomcat" <user name="role1" <user name="both" <user name="klute" </tomcat−users> password="tomcat" password="tomcat" password="tomcat" password="geheim" Web−Anwendungen mit Java 112 roles="tomcat, secret" /> roles="role1" /> roles="tomcat,role1" /> roles="manager" /> Manager−Applikation Sehr rudimentäre Bedienung durch Eingabe von URIs http://mark.rainer−klute.de:8080/manager/reload?path=/auth Alles weitere: Tomcat−Dokumentation lesen, hier: Manager−HOWTO Web−Anwendungen mit Java 113 Übungsaufgabe 3: Property−Servlet Vor dem Erstellen »richtiger« Web−Anwendungen sind einige Fingerübungen sehr hilfreich: Richten Sie auf dem Übungsrechner unter Ihrer Benutzerkennung Ihre eigene Tomcat−Umgebung ein! Schreiben Sie ein Servlet, das die System−Properties (siehe Übungsaufgabe 2) alphabetisch sortiert ausgibt, idealerweise als HTML−Tabelle! Web−Anwendungen mit Java 114 HTTP−Requests mit Parametern Ziel: Verarbeiten von Benutzereingaben durch das Servlet Basis aller »echten« Web−Anwendungen Übergabe von Parametern an Servlet im HTTP− Request Einfache Beispiele: »Hello World«−Servlet soll Nutzer individueller ansprechen: Übergabe eines Ortsnamens Ortsname wird in Servlet−Ausgabe eingeblendet. E−Shop: Von der Produktübersicht zu den Detailinformationen verzweigen Dynamische Zielangabe beschreibt Datenbankobjekt. Web−Anwendungen mit Java 115 Parameterübergabemechanismen Speziell geformte URLs /Hello/Dortmund?Sprache=DE /Hello?Ort=Dortmund&Sprache=DE GET−Request Web−Formulare Übertragen der Formulardaten − meist als POST− Request, manchmal als GET−Request (siehe oben) Cookies Sessions ID im HTTP−Header Mischformen Web−Anwendungen mit Java 116 Snoop−Servlet Snoop−Servlet: zeigt Servlet−Parameter und weitere Informationen an. Web−Anwendungen mit Java 117 Snoop−Servlet Servlet−Mapping: <servlet−mapping> <servlet−name>Snoop</servlet−name> <url−pattern>/Snoop/*</url−pattern> </servlet−mapping> Bildet alle URIs, die mit »/Snoop/« beginnen, auf das Servlet namens »Snoop« ab. Servlet analysiert den URI (siehe unten) und kann entsprechende Aktionen durchführen. Web−Anwendungen mit Java 118 Info−Methoden Dreh− und Angelpunkt eines HTTP−Servlets: Methode void service(ServletRequest, ServletResponse) Analysiert HTTP−Methode und leitet Request weiter an doGet(...), doPost(...) usw. HttpServletRequest Unterklasse von ServletRequest Besitzt Methoden zum Erfragen diverser Informationen, insbesondere der Servlet−Parameter. Web−Anwendungen mit Java 119 Request−Parameter abfragen Einfache Abfrage fest definierter Parameter Beispiel: /Hello?Ort=Dortmund »?« leitet Parameter ein, »&« trennt Parameter. Parametername: Ort Parameterwert: Dortmund public void doGet(HttpServletRequest request, { } HttpServletResponse response) throws ServletException, IOException String ort = request.getParameter("Ort"); .... Web−Anwendungen mit Java 120 Beliebige Parameternamen Im URI können beliebige Parameternamen stehen. Ein Servlet kann sie erfragen: /Hello?Ort=Dortmund&Schnism=Tr%FCst »%FC«: im URL zulässige Ersatzdarstellung für »ü« Im URL sind keine »Sonderzeichen« erlaubt. Darstellung beliebiger Zeichen durch Hexadezimalwert Enumeration e = request.getParameterNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); String values = request.getParameter(name); ... } Web−Anwendungen mit Java 121 Mehrfache Parameterwerte Gleicher Parameter kann mehrfach mit unterschiedlichen oder gleichen Werten vorkommen. Beispiel: /Hello?x=0&x=1&x=0 Enumeration e = request.getParameterNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); String[] values = request.getParameterValues(name); for (int i = 0; i < values.length; i++) System.out.println(name + ": " + values[i]); } Web−Anwendungen mit Java 122 Parameter−Map Statt getParameterNames() und getParameterValues() das Map−Interface nutzen. Map p = request.getParameterMap(); Schlüssel sind von Typ String. Werte sind vom Type String[]. Web−Anwendungen mit Java 123 Der Query−String Beispiel−URI: http://localhost:8080/Snoop/Hello/Foo?Bar&x=%FC String getQueryString() Ergebnis: Bar&x=%FC Query−String: alles ab »?« In URI ohne »?« ist der Query−String null. In URI mit »?«, aber ohne Parameter hinter dem »?« ist der Query−String leer. Web−Anwendungen mit Java 124 Request−URI und Pfade http://localhost:8080/Snoop/Hello/Foo?Bar&x=%FC String getRequestURI() Ergebnis: /Snoop/Hello/Foo Request URI: alles bis zum »?« »http://localhost:8080« steckt nicht im HTTP− Request, sondern in der Art und Weise des Verbindungsaufbaus. String getServletPath() Ergebnis: /Snoop String getPathInfo() Ergebnis: /Hello/Foo Web−Anwendungen mit Java 125 Pfad zur Web−Anwendung http://localhost:8080/Snoop/Hello/Foo?Bar&x=%FC String getPathTranslated() Ergebnis: /home/klute/tomcat/webapps/ROOT/Hello/Foo Pfad zur Web−Anwendung Nur definiert, falls Pfadinformationen (siehe getPathInfo()) vorhanden sind, sonst null. Ein einzelner »/« reicht aus. Web−Anwendungen mit Java 126 Weitere Info−Methoden des Requests Vom Browser gesendete HTTP−Header HTTP−Methode Interessant, wenn Servlet die Methode service() überschreibt. Bei authentifizierten Zugriffen: Benutzername, Authentifizierungsschema Sitzungen: Session−ID, Session, Cookies, Principal, Rolle Servlet: Initialisierungsparameter, Konfiguration, Kontext, Info, Name Web−Anwendungen mit Java 127 Servlets: Ausblick Bisher: Einführung in Servlet−Grundlagen, Tomcat als Servlet−Container, einfache Servlets mit und ohne Parametern sowie Deployment descriptor Demnächst: Formulare, Sessions, HTTP−Response, Sicherheit Vorher aber: Java Server Pages (JSP) HTML−Seiten mit eingebettetem Java−Quellcode Kein »programmiertes HTML« mehr nötig: out.println("<title>Hello World!</title>"); out.println("<h1>Hello World!</h1>"); Wesentlich einfacheres Vorgehen bei Änderungen Automatische Übersetzung und Installation Web−Anwendungen mit Java 128 Übungsaufgabe 5: Produktansichten Schreiben Sie eine Web−Anwendung aus einem oder mehreren Servlets, die die Produkte eines E−Shops präsentiert. Folgende Funktionalität wird erwartet: Die Eingangsseite zeigt einen Übersicht aller Produkte. Aus der Übersicht gelangt man durch einen Klick zur Darstellung eines einzelnen Produkts mit detaillierten Informationen, einem Bild (falls vorhanden) und dem Preis. Aus der Einzelsicht gelangt der Benutzer per Klick wieder zurück zur Übersicht. Die Pflege der Inhalte (Text, Bild, Preis und evtl. weitere) ist noch nicht Gegenstand der Web−Anwendung. Überlegen Sie, wie Sie diese Daten außerhalb der Web−Anwendung geeignet ablegen und pflegen können! Überstürzen Sie nichts: Sie haben für diese Aufgabe fast zwei Wochen Zeit, da die nächste Übungsaufgabe harmlos ist! Die folgenden Aufgaben bauen auf dieser auf, so daß Sie sie ernstnehmen sollten. Web−Anwendungen mit Java 129 Java Server Pages (Teil 1) Java Server Pages (Teil 1) Web−Anwendungen mit Java 130 JSP im Überblick Was ist eine JSP−Seite? Erste Antwort: eine HTML−Seite mit integrierten Java−Anweisungen Beispieldatei ROOT/Beispiel.jsp: <!DOCTYPE html PUBLIC "−//W3C//DTD HTML 4.0//EN//"> <%@ page session="false" import="java.util.*" %> <html> <head> <title>JSP−Beispiel</title> </head> <body style="background: #ffffff"> <h1>JSP−Beispielseite</h1> JSP im Überblick Anzeige im Browser: Allgemein: Schablone aus statischem Text (nicht nur HTML) Integrierte Skripting−Anweisungen in Java (oder im Prinzip anderen Sprachen) Web−Anwendungen mit Java 132 Model View Controller (MVC) Ziel: Trennung von Anwendungslogik und Präsentation (Visualisierung) Vorteile: Klare Unterscheidung der unterschiedlichen Aufgabenbereiche Anwendungslogik und Präsentation werden voneinander unabhängig. Präsentation wird austauschbar. Parallele Präsentationen werden möglich, z.B. unterschiedliche Sprachen, unterschiedliche Designs, unterschiedliche Oberflächen (Web, Swing usw.). Web−Anwendungen mit Java 133 Model View Controller (MVC) Model Controller View Das MVC−Prinzip ermöglicht die gewünschte Trennung. Model enthält Anwendungsdaten und −logik. View präsentiert dem Benutzer die Daten und nimmt Eingaben entgegen (Tastatur, Maus, Sprache usw.). Mehrere Views sind möglich. Controller vermittelt zwischen Model und Views. Web−Anwendungen mit Java 134 MVC: Zustandsänderung des Models Model 1 Controller 2 2 View 1 View 2 Änderung des Models muß sich in den Views widerspiegeln. Schritt 1: Model informiert Controller über Zustandsänderung. Schritt 2: Controller ändert View(s). Web−Anwendungen mit Java 135 MVC: Änderung eines Views 2 Model 3 Controller 1 4 View 1 View 2 Benutzereingabe oder Änderung durch Controller Schritt 1: View propagiert Änderung zum Controller. Schritt 2: Controller modifiziert Model. Schritt 3: Model informiert Controller (siehe oben). Schritt 4: Controller ändert Views (siehe oben). View sollte selbstbewirkte Model−Änderungen ignorieren. Web−Anwendungen mit Java 136 MVC mit JSP JSP−Seite dient lediglich der Präsentation. Einbetten von Anwendungsdaten in die HTML−Seite Einfache Präsentationsanweisungen Weiterleiten von Benutzereingaben an eine Controller− Klasse Anklicken von Links Absenden von HTML−Formularen Interaktion mit Java−Applets Keine Anwendungslogik in der JSP−Seite! Im wesentlichen Aufruf von get− und set−Methoden der Controller−Klasse Web−Anwendungen mit Java 137 Funktionsweise von JSP JSP−Container Web−Server JSP−Servlet Generierte Servlets Aus JSP−Seiten werden Servlets. Steuerung durch JSP−Container Servlet−Container plus JSP−Funktionalität Andere Bezeichnung: Web−Container Web−Anwendungen mit Java 138 JSP−Seiten Dateien mit Endung .jsp Funktionsweise von JSP Der JSP−Container bemerkt Änderung an JSP−Seite und generiert daraus die Servlet−Klasse neu Java−Quellcode erzeugen Java−Quellcode übersetzen, führt Methode destroy() der alten Servlet−Instanz aus und entlädt das Servlet, lädt das neu generiertes Servlet und führt dessen Methode init() aus. Anschließend bearbeitet das neue Servlet ankommende Requests mittels service(). Translation phase / Execution phase Web−Anwendungen mit Java 139 Funktionsweise von JSP JSP−Container Web−Server JSP−Servlet Generierte Servlets Separate Übersetzung der JSP−Seiten Keine Aktualitätsprüfungen zur Laufzeit Bessere Performance in produktiven Anwendungen Web−Anwendungen mit Java 140 JSP−Seiten JSP−Compiler Funktionsweise von JSP Eine JSP−Seite ist ein Servlet. Lebenszyklus wie bei »normalen« Servlets: init(), service(), destroy() Diese Methoden stehen in der JSP−Seite nicht zur Verfügung. Der JSP−Container generiert sie in das Servlet hinein. In der JSP−Seite kann man vergleichbare Methoden definieren: void jspInit() wird vor dem ersten Ausführen der JSP−Seite ausgeführt. void jspDestroy() wird vor dem Entladen der JSP−Seite ausgeführt. Web−Anwendungen mit Java 141 Tomcat und JSP In Tomcat erledigt das JSP−Servlet Jasper die nötigen Aufgaben. Zuordnung von URI zu JSP−Seite bzw. dem generierten Servlet implizit durch Endung ».jsp« Zeitstempel von JSP−Seiten und generierten Servlets vergleichen und bei Bedarf Java−Quellcode generieren, Java−Quellcode übersetzen, alte Servlet−Version durch neue ersetzen. Voreingestellte Konfiguration: keine Aktualitätsprüfung zur Laufzeit Web−Anwendungen mit Java 142 JSP−Skripting Deklarationen Variablen, Methoden usw. <%! int i; %> Skriptlets Java−Anweisungen Werden unverändert in das generierte Servlet eingefügt. Ausgaben auf den JspWriter out nur explizit <% i = i + 1; out.println(i); %> Ausdrücke Werden ausgewertet und nach out ausgegeben <%= i + 27 %> Web−Anwendungen mit Java 143 JSP−Skripting Kommentare Erscheinen nur in der JSP−Seite, aber weder im generierten Servlet noch in der HTML−Ausgabe. <%−− Dies ist ein JSP−Kommentar. −−%> <% /* Dies auch (für Java). */ %> HTML−Kommentare <!−− Kommentar −−> Haben mit JSP nichts zu tun. Erscheinen in der HTML−Ausgabe Per JSP modifizierbar: <!−− Kommentar mit <%= ... %> Einfügung −−> Web−Anwendungen mit Java 144 JSP−Skripting Ersatzdarstellungen Im Skript: %> → %\> In der Schablone: <% → <\% In Attributen: ’ → \’ (In Attributen attr=’value’) " → \" (In Attributen attr="value") \ → \\ %> → \%\> <% → <\% ’ → &apos; " → &quot; Web−Anwendungen mit Java 145 JSP−Skripting: Beispiel Szenario: Kunde hat im E−Shop eingekauft. Anzeige des neuen Kontostands nach dem Einkauf Web−Anwendungen mit Java 146 JSP−Skripting: Beispiel <!doctype html public "−//W3C//DTD HTML 4.0//EN//"> <html> <head> <title>Ihr Kontostand</title> </head> <body style="background: #ffffff"> <h1>Ihr Kontostand</h1> <%−− JSP−Kommentar: wird nicht in generiertes Servlet eingefügt. −−%> <!−− HTML−Kommentar: wird in generiertes Servlet eingefügt. −−> <%! float kaufsumme = 123.46f; float saldoAlt = 100.00f; float saldoNeu; %> Web−Anwendungen mit Java 147 Skripting−Elemente: Beispiel <table border="1"> <tr> <td>Alter Saldo:</td> <td><%= saldoAlt %> EUR</td> </tr> <tr> <td>Kaufsumme:</td> <td><%= kaufsumme %> EUR</td> </tr> <% saldoNeu = saldoAlt − kaufsumme; %> <tr> <td>Neuer Saldo:</td> < <td><%= format(saldoNeu) %> EUR</td> </tr> </table> Web−Anwendungen mit Java 148 Skripting−Elemente: Beispiel <%! String format(float f) { String s = Float.toString(f); return f >= 0 ? s : "<span style=’color: red’>" + s + "</span>"; } %> <p> <% if (saldoNeu >= 0) { %> Sie haben ein Guthaben von <%= saldoNeu %> EUR. <% } else { %> Ihr Konto ist um <%= −saldoNeu %> EUR überzogen. <% } %> </p> </body> </html> Web−Anwendungen mit Java 149 Generierter Java−Quellcode import import import import import import import import import import import import javax.servlet.*; javax.servlet.http.*; javax.servlet.jsp.*; javax.servlet.jsp.tagext.*; java.io.PrintWriter; java.io.IOException; java.io.FileInputStream; java.io.ObjectInputStream; java.util.Vector; org.apache.jasper.runtime.*; java.beans.*; org.apache.jasper.JasperException; public class _0002fKontostand_0002ejspKontostand_jsp_0 extends HttpJspBase { Web−Anwendungen mit Java 150