Generierter Java−Quellcode // begin [file="/export/home/klute/tomcat/webapps/ROOT/Kontostand.j sp";from=(12,5);to=(15,2)] float kaufsumme = 123.46f; float saldoAlt = 100.00f; float saldoNeu; // end // begin [file="/export/home/klute/tomcat/webapps/RO... String format(float f) { String s = Float.toString(f); return f >= 0 ? s : "<span style=’color: red’>" + s + "</span>"; } // end Web−Anwendungen mit Java 151 Generierter Java−Quellcode static { } public _0002fKontostand_0002ejspKontostand_jsp_0( ) { } private static boolean _jspx_inited = false; public final void _jspx_init() throws JasperException { } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { JspFactory _jspxFactory = null; PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; Web−Anwendungen mit Java 152 Generierter Java−Quellcode String try { _value = null; if (_jspx_inited == false) { _jspx_init(); _jspx_inited = true; } _jspxFactory = JspFactory.getDefaultFactory(); response.setContentType("text/html;charset=8859_1"); pageContext = _jspxFactory.getPageContext(this, request, response, "", true, 8192, true); application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); Web−Anwendungen mit Java 153 Generierter Java−Quellcode // HTML // begin [file="/export/home/klute/t... out.write("<!doctype html public \"− //W3C//DTD HTML 4.0//EN//\">\r\n<html>\r\n <head>\r\n <title>Ihr Kontostand</title>\r\n </head>\r\n\r\n <body style=\"background: #ffffff\">\r\n <h1>Ihr Kontostand</h1>\r\n\r\n "); // end // HTML // begin [file="/export/home/klute/t... out.write("\r\n <!−− HTML−Kommentar: wird in generiertes Servlet eingefügt. −−>\r\n\r\n "); // end // HTML // begin [file="/export/home/klute/t... out.write("\r\n\r\n <table border=\"1\">\r\n <tr>\r\n <td>Alter Saldo:</td>\r\n <td>"); // end // begin [file="/export/home/klute/t... out.print( saldoAlt ); // end Web−Anwendungen mit Java 154 Generierter Java−Quellcode // HTML // begin [file="/export/home/klute/t... out.write(" EUR</td>\r\n </tr>\r\n <tr>\r\n <td>Kaufsumme:</td>\r\n <td>"); // end // begin [file="/export/home/klute/tomcat/we... out.print( kaufsumme ); // end // HTML // begin [file="/export/home/klute/t... out.write(" EUR</td>\r\n </tr>\r\n\r\n"); // end // begin [file="/export/home/klute/tomcat/we... saldoNeu = saldoAlt − kaufsumme; // end // HTML // begin [file="/export/home/klute/t... out.write("\r\n\r\n <tr>\r\n <td>Neuer Saldo:</td>\r\n "); // end // HTML // begin [file="/export/home/klute/t... out.write("\r\n <td>"); // end Web−Anwendungen mit Java 155 Generierter Java−Quellcode // begin [file="/export/home/klute/tomcat/we... out.print( format(saldoNeu) ); // end // HTML // begin [file="/export/home/klute/t... out.write(" EUR</td>\r\n </tr>\r\n </table>\r\n\r\n "); // end // HTML // begin [file="/export/home/klute/t... out.write("\r\n\r\n <p>\r\n "); // end // begin [file="/export/home/klute/tomcat/we... if (saldoNeu >= 0) { // end // HTML // begin [file="/export/home/klute/t... out.write("\r\n Sie haben ein Guthaben von "); // end // begin [file="/export/home/klute/tomcat/we... out.print( saldoNeu ); // end Web−Anwendungen mit Java 156 Generierter Java−Quellcode // HTML // begin [file="/export/home/klute/t out.write(" EUR.\r\n "); // end // begin [file="/export/home/klute/tomcat/w... } else { // end // HTML // begin [file="/export/home/klute/t... out.write("\r\n Ihr Konto ist um "); // end // begin [file="/export/home/klute/tomcat/w... out.print( −saldoNeu ); // end // HTML // begin [file="/export/home/klute/t... out.write(" EUR überzogen.\r\n "); // end // begin [file="/export/home/klute/tomcat/w... } // end Web−Anwendungen mit Java 157 Generierter Java−Quellcode // HTML // begin [file="/export/home/klute/t... out.write("\r\n </p>\r\n\r\n </body>\r\n</html>\r\n"); // end } } } catch (Exception ex) { if (out.getBufferSize() != 0) out.clearBuffer(); pageContext.handlePageException(ex); } finally { out.flush(); _jspxFactory.releasePageContext(pageContext); } Web−Anwendungen mit Java 158 JSP−Seite als XML−Dokument Skripting−Anweisungen sind nicht SGML− bzw. XML− konform. Syntaxgesteuertes Editieren der JSP−Seiten mit SGML− oder XML−Editor nicht möglich. Schnellschuß der ersten JSP−Version JSP 1.2 ermöglicht XML−Darstellung Alternativ zum JSP−Skripting <jsp:expression>i + 27</jsp:expression> Web−Anwendungen mit Java 159 Java−Bean nutzen MVC: JSP−Seite visualisiert Controller (Java−Bean). Java−Bean (vereinfacht): Exemplar einer Java− Klasse, deren Attribute foo sich mit Methoden wie getFoo() und setFoo(value) abfragen und ändern lassen Java−Bean repräsentiert ein Business −Objekt. Beispiel: Produkt JSP−Seite präsentiert die Bean: Aufruf der entsprechenden getFoo()−Methoden und Integration der Ergebniswerte in die HTML−Seite. JSP−Seite benötigt Zugriff auf die Java−Bean. Web−Anwendungen mit Java 160 Beispiel: Java−Bean nutzen <html> <jsp:useBean id="product" class="eshop.Product"/> <% product.setId (request.getParameter("productId")); %> <ul> <li> <p>Produkt: <%= product.getName() %></p> </li> <li> <p>Preis: <%= product.getPrice() %></p> </li> </ul> </html> Web−Anwendungen mit Java 161 Beispiel: Java−Bean nutzen Elemente wie <jsp:xxx>...</jsp:xxx> oder <jsp:xxx/> heißen Aktionen. Element <jsp:useBean ...> erzeugt Instanz der Klasse eshop.Product mit dem Namen product. Das Objekt product steht anschließend in der JSP− Seite zur Verfügung. <% product.setId (request.getParameter("productId")); %> übermittelt den Wert des Request−Parameters productId zur Initialisierung an das Objekt. <%= product.getPrice() %> ermittelt den Preis und schreibt ihn in den Ausgabestrom out. Web−Anwendungen mit Java 162 Ressourcen einbetten Ziel: Weitere Ressource der Anwendung in den Ausgabestrom einbetten Datei in Ausgabe einbetten, z.B. standardisierten Seitenkopf oder −fuß JSP−Seite, −Fragment oder Servlet in Ausgabe integrieren Weg: PageContext−Methode include(String relativeUriPath) pageContext.include("header.html"); pageContext.include("/ad/finance.jsp"); Einbetten von Ressourcen anderer Web−Server nicht möglich Web−Anwendungen mit Java 163 Ressourcen einbetten URI ohne /: relativ zur Adresse der JSP−Seite URI mit /: relativ zur Wurzel des Web−Servers pageContext.include("header.jsp"); pageContext.include("/copyright.html"); Der HttpServletRequest bleibt in allen beteiligten Seiten derselbe. HttpServletRequest Web−Anwendungen mit Java Seite 1: 164 Seite 2: Ressourcen einbetten JSP−Fragment Wird dynamisch in eine JSP−Seite eingebettet Selbst keine syntaktisch korrekte JSP−Seite Übersetzung nicht möglich JSP−1.2−Spezifikation schlägt Namenskonvention vor. Endung .jspf oder .jsf Web−Anwendungen mit Java 165 Request weiterleiten Ziel: Request nicht durch die aktuelle JSP−Seite bearbeiten, sondern durch eine andere aktive Komponente der Anwendung (Servlet, JSP−Seite). Typische Anwendungsfälle: Aktuelle JSP−Seite dient als Verteiler und verzweigt parameterabhängig zur eigentlichen Zielseite. Ausnahmebehandlung, z.B. weil Rechte fehlen Weg: PageContext−Methode forward(String relativeUrlPath) Web−Anwendungen mit Java 166 Request weiterleiten Beispiel: if (!request.isUserInRole("webmaster")) { pageContext.forward("wm−login.jsp"); return; } Nach Aufruf von forward() darf der aufrufende Thread keine Ausgaben nach out schreiben (siehe Beispiel). Web−Anwendungen mit Java 167 Implizite Objekte Implizite Objekte stehen in jeder JSP−Seite automatisch zur Verfügung. Gültigkeitsbereiche: Page: Objekt ist nur in dieser JSP−Seite gültig. Request: Objekt ist in allen JSP−Seiten gültig, die denselben Request bearbeiten − siehe include() und forward(). Session: Objekt ist in allen JSP−Seiten und Requests gültig, die zu derselben Sitzung gehören. Application: Objekt ist in allen JSP−Seiten und Requests einer Anwendung gültig, auch in Seiten ohne Session−Kontext und in anderen Sessions. Web−Anwendungen mit Java 168 Implizite Objekte Name Klasse Bedeutung request Unterklasse von ServletRequest, z.B. HttpServletRequest response Response Unterklasse von ServletResponse, z.B. HttpServletResponse pageContext PageContext session HttpSession Web−Anwendungen mit Java Request Gültig in Request Page Kontext dieser JSP− Seite. Bietet Zugriff auf alle impliziten Page Session, falls vorhanden. Session 169 Implizite Objekte Name Klasse Bedeutung Gültig in application ServletContext Servlet−Kontext Application out JspWriter Schreiben von Ausgabedaten Page config ServletConfig Servlet−Konfiguration Page page Object Diese JSP−Seite (this) exception Throwable Ursache des Aufrufs Page der Fehlerseite (nur definiert, falls die JSP− Seite eine Error−Seite ist) Web−Anwendungen mit Java 170 Page Direktiven an den JSP−Container page Definiert Eigenschaften der JSP−Seite. <%@ page session="false" buffer="15kb" %> include Integriert Datei in JSP−Seite <%@ include file="copyright.html" %> taglib Erlaubt selbstdefinierte Tags <super:foo>...</super:foo> <%@ taglib uri="http://www.foo.bar/tags" prefix="super" %> Web−Anwendungen mit Java 171 Direktive »page«: Attribute language="scriptingLanguage" Sprache der Skripting−Anweisungen. Derzeit einziger möglicher Wert: "java". extends="className" Generiertes JSP−Servlet besitzt die angegebene Oberklasse. Vorsicht: Dieses Attribut überschreibt die Voreinstellung des JSP−Containers. Tomcat: org.apache.jasper.runtime.HttpJspBase (erbt von HttpServlet, implementiert HttpJspPage). Web−Anwendungen mit Java 172 Direktive »page«: Attribute import="importList" Liste importierter Klassen bzw. Pakete. Beispiel: <%@page import="java.util.*, java.io.File"%> Voreingestellt: java.lang.*, javax.servlet.*, javax.servlet.jsp.*, javax.servlet.http.* session="true|false" Gibt an, ob diese Seite zu einer Session gehört. Definiert implizites Objekt HttpSession session. Falls session="false", ist dieses Objekt undefiniert. Web−Anwendungen mit Java 173 Direktive »page«: Attribute buffer="none|sizekb" Mindestgröße des Puffers für den Ausgabestrom out. buffer="none": Ausgaben gehen ohne Pufferung an den PrintWriter der ServletResponse. Voreinstellung für size ist implementationsabhängig, aber mindestens 8kb. autoFlush="true | false" Gibt an, ob voller Puffer automatisch zum Empfänger geschickt wird (true) oder eine Exception erzeugt (false). Web−Anwendungen mit Java 174 Direktive »page«: Attribute isThreadSafe="true | false" Gibt an, ob JSP−Seite thread−sicher ist. Eine thread−sichere JSP−Seite kann von mehreren parallelen Requests gleichzeitig ausgeführt werden. Eine nicht thread−sichere Seite wird von mehreren parallelen Requests nacheinander ausgeführt. info="infoText" Beliebiger Text, läßt sich mit Servlet.getServletInfo() abfragen. Web−Anwendungen mit Java 175 Direktive »page«: Attribute errorPage="errorUrl" isErrorPage="true | false" Diese Seite führt eine Fehlerbearbeitung durch. Hier ist die Variable Throwable exception definiert, die auf das nicht abgefangene Throwable verweist. contentType="contentType" Bei einem nicht abgefangenen Throwable bearbeitet die angegebene JSP−Seite den Request weiter. Voreinstellung: text/html;charset=ISO−8859−1 pageEncoding="encoding" Voreinstellung: Zeichensatz aus contentType oder ISO−8859−1 Web−Anwendungen mit Java 176 Direktive »include« Dateien in die Ausgabe integrieren Direktive »include« Beispiel: <%@ include file="header.html" %> Bindet Datei zur Übersetzungszeit ein. Eingebundene Datei wird dynamisch ausgewertet. Alternative: Aktion <jsp:include> Beispiel: <jsp:include page="/copyright.html" flush="true"/> Adressierung relativ zur Wurzel der Web−Anwendung Bindet Datei zur Laufzeit ein. Übernahme des Dateiinhalts ohne Veränderungen Web−Anwendungen mit Java 177 Direktive »taglib« Stellt eigene Elemente (»Tags«) zur Verfügung Beispiel: <%@ taglib uri="http://www.foo.bar/taglib" prefix="form" %> <form:questionnaire foo="bar"> ... </form:questionnaire> uri="taglibURI" Identifizierung eines Tag library descriptors (TLD) Zuordnung zum TLD im Deployment descriptor prefix="prefix" Präfix der Tag−Namen in dieser Seite Web−Anwendungen mit Java 178 Tag Library: Beispiel <html> <%@ taglib uri="http://acme.com/taglibs/simpleDB.tld" prefix="x" %> <x:queryBlock connData="some connection data"> <x:queryStatement> SELECT ACCOUNT, BALANCE FROM ... </x:queryStatement> <p>The top 10 accounts and balances are:</p> <table> <tr><th>ACCOUNT</th><th>BALANCE</th></tr> <x:queryCreateRows from="1" to="10"> <td><x:queryDisplay field="ACCOUNT"/></td> <td><x:queryDisplay field="BALANCE"/></td> </x:queryCreateRows> </table> </x:queryBlock> </html> Web−Anwendungen mit Java 179 Tag Library Definiert neue Elemente für HTML−Seite. Im Beispiel: <x:queryBlock>, <x:queryStatement>, <x:queryCreateRows> Kein gültiges HTML mehr, aber XML−konform Definiert zur Laufzeit eine spezifische Umgebung Innerhalb von queryBlock steht eine Datenbankverbindung zur Verfügung. queryStatement führt SQL−Anweisung über die Datenbankverbindung aus. queryCreateRows iteriert über Ergebnis und erzeugt Ausgabezeilen. queryDisplay gibt Tabellenfeld aus. Web−Anwendungen mit Java 180 Aktionen Können in den Ausgabestrom out schreiben. Können Objekte erzeugen oder verändern Selbstdefinierte Aktionen (Tag libraries) Standardaktionen Reservierter Namensraum <jsp:...> Andere reservierte Namensräume: _jsp, java, sun XML−Syntax <action attr="foo">bar</action> <action attr="foo"/> <action attr="foo"></action> Web−Anwendungen mit Java 181 Standardaktion <jsp:useBean> Java−Objekt in der JSP−Seite nutzen. Zwei Hauptvarianten: Neues Java−Objekt erzeugen und Namen vergeben Bereits vorhandenes Objekt suchen und nutzen Wählbarer Gültigkeitsbereich page, request, session, application Sucht spezifiziertes Objekt. Falls nicht vorhanden, erzeugt <jsp:useBean> das Objekt. Genaues Verhalten hängt ab von den jeweiligen Attributkombinationen und den bereits existierenden Java−Objekten Web−Anwendungen mit Java 182 Standardaktion <jsp:useBean> Beispiel: <jsp:useBean id="foo" scope="session" class="de.rainer_klute.eshop.Product"/> id: Zwei Bedeutungen: Name des Java−Objekts Name der Skripting−Variablen, die auf das Java−Objekt verweist scope: Gültigkeitsbereich der Skripting−Variablen Mögliche Werte: page, request, session, application Web−Anwendungen mit Java 183 Standardaktion <jsp:useBean> class: Vollqualifizierter Klassenname des Java− Objekts. Beispiel: de.rainer_klute.eshop.Product type: Typ der Skripting−Variable Skripting−Variable wird Referenz des Java−Objekts zugewiesen. Mögliche Werte für type: dieselbe Klasse wie class, eine Oberklasse von class, ein Interface, das class implementiert. Beispiel: de.rainer_klute.AbstractProduct Web−Anwendungen mit Java 184 Standardaktion <jsp:useBean> beanName: Name einer Java−Bean (serialisiertes Objekt) Beispiel: beanName="foo.bar.Product" Serialisiertes Objekt wird aus Datei foo/bar/Product.ser deserialisiert. Bei Mißerfolg wird neues Objekt der Klasse foo.bar.Product erzeugt. Web−Anwendungen mit Java 185 Standardaktion <jsp:useBean> Variable id definieren: type id (falls type spezifiziert) class id (falls type nicht spezifiziert) Objekt id in scope suchen → ref Objekt vorhanden id = (type) ref; Body enthält typischerweise Skriptlets oder <jsp:setProperty>. Objekt nicht vorhanden, beanName nicht spezifiziert id = new class(); scope.add(id); id = Beans.instantiate (beanName); scope.add(id); Body von <jsp:useBean> ausführen, falls vorhanden Web−Anwendungen mit Java 186 Objekt nicht vorhanden, beanName spezifiziert Standardaktion <jsp:setProperty> Setzt Properties in einer Bean (siehe <jsp:useBean>). Einfacher Zugriff auf Servlet−Parameter Beispiele: Property row in Bean results Wert zuweisen: <jsp:setProperty name="results" property="row" value="<%= i+1 %>"/> Alle Servlet−Parameter in gleichnamige Properties übertragen, soweit vorhanden (Introspection): <jsp:setProperty name="request" property="*"/> Standardaktion <jsp:setProperty> Zum Setzen der Property »foo« benötigt Bean die Methode void setFoo(type). Servlet−Parameter sind immer Strings. Automatische Konvertierung von Strings in diverse Zieltypen boolean, byte, char, double, int, float, long Boolean, Byte, Character, Double, Integer, Float, Long Beim Zuweisungen des Typs <jsp:setProperty value="value" .../> darf value auch ein Objekt oder Array sein. Entsprechende set−Methode notwendig Web−Anwendungen mit Java 188 Standardaktion <jsp:getProperty> Property aus Bean nach out schreiben Konvertierung in String Beispiel: <jsp:getProperty name="user" property="username"/> Web−Anwendungen mit Java 189 Standardaktion <jsp:include> Bindet Ressource (statische Datei, Servlet, JSP−Seite) zur Laufzeit unverändert ein. Siehe pageContext.include(...) Beispiele: <jsp:include page="copyright.html" flush="true"/> Adressierung ohne /: relativ zur anfordernden JSP−Seite " Kein Zugriff auf andere Server, da »http://...« nicht mit »/« beginnt <jsp:include page="/eshop/product?id=4711" flush="true"/> Adressierung mit /: relativ zur Wurzel des Web−Servers " Zugriff auf Ressourcen in anderen Web−Anwendungen möglich Web−Anwendungen mit Java 190 Standardaktion <jsp:include> Eingebundene JSP−Seite bzw. Servlet erhält dasselbe Request−Objekt wie der Aufrufer von <jsp:include>. Servlet−Parameter lassen sich mittels <jsp:param> modifizieren oder ergänzen. Beispiel für Parameterübergabe: <jsp:include page="foo.jsp" flush="true"> <jsp:param name="bar1" value="1111"/> <jsp:param name="bar2" value="2222"/> </jsp:include> Standardaktion <jsp:forward> Veranlaßt Bearbeitung des Requests durch eine andere Ressource (statische Datei, Servlet, JSP− Seite) Siehe pageContext.forward(...) Beispiel: <%! String goTo() { Calendar c = new GregorianCalendar(); if (c.get(c.AM_PM) == c.AM) return "GoodMorning.jsp"; else return "GoodAfternoon.jsp"; } %> <jsp:forward page=’<%="/dayTime/" + goTo()%>’/> Web−Anwendungen mit Java 192 Standardaktion <jsp:forward> Falls schon Ausgaben erzeugt wurden: Ausgabe vollständig im Puffer bzw. noch nichts an Client geschickt: Puffer leeren, dann Request zur neuen Seite weiterleiten. Ungepufferte Ausgabe bzw. bereits Daten an Client geschickt: IllegalStateException. Eingebundene JSP−Seite bzw. Servlet erhält dasselbe Request−Objekt wie der Aufrufer von <jsp:forward>, aber entsprechend modifiziert. Servlet−Parameter lassen sich mittels <jsp:param> modifizieren oder ergänzen. Beispiele für Parameterübergabe siehe oben (<jsp:include>). Web−Anwendungen mit Java 193 Standardaktion <jsp:plugin> Erzeugt HTML−Code für den jeweiligen Browser zur Integration des Java−Plugins von Sun Microsystems. OBJECT− oder EMBED−Element Java−Applets oder Java−Beans im Browser ablaufen lassen Details siehe JSP−Spezifikation Web−Anwendungen mit Java 194 Standardaktion <jsp:param> Parameter an <jsp:include>, <jsp:forward> und <jsp:plugin> Name−/Wert−Paare Beispiele siehe oben Bei <jsp:include> und <jsp:forward> gilt: Durch <jsp:param> spezifzierte Parameter überschreiben oder ergänzen die bereits vorhandenen Servlet− Parameter. Nur innerhalb der durch <jsp:include> bzw. <jsp:forward> adressierten Seite Web−Anwendungen mit Java 195 Übungsaufgabe 6: E−Shop mit JSP Dies ist die angekündigte harmlose Aufgabe: Stellen Sie die Web−Anwendung aus Übungsaufgabe 5 (E−Shop) auf Java Server Pages um! Darüber hinaus sollten Sie die evtl. noch nicht fertiggestellten Teile der Übungsaufgabe 5 komplettieren. Web−Anwendungen mit Java 196 Compile−Fehler Ursache 1: fehlerhafte JSP−Direktiven oder JSP− Aktionen Ursache 2: fehlerhafte Java−Anweisungen in der JSP− Seite Wird vom Entwickler beim ersten Zugriff auf die neue oder modifizierte Seite bemerkt. Behandlung von Übersetzungsfehlern implementationsspezifisch Von JSP 1.2 nicht spezifiziert Beispiel: <%= new java.util.Datei() %> Web−Anwendungen mit Java 197 Compile−Fehler Web−Anwendungen mit Java 198 Compile−Fehler Web−Anwendungen mit Java 199 Laufzeitfehler JSP−Seite wird korrekt in ein Servlet übersetzt. Fehler tritt erst bei einem Request auf, also beim Ablauf des Servlets. Was ist ein Fehler? Instanz einer Unterklasse von Throwable, die nicht abgefangen wird. Maßnahmen: Fehler explizit abfangen und geeignet behandeln Fehlermeldung ausgeben Web−Anwendungen mit Java 200