Datenbanken: Servlets und JSP Datenbank-Anwendungen für das Web basieren auf der Client - Server - oder Client - Middleware - Datenbankserver - Architektur. Grundsätzlich zu unterscheiden sind: Client-basierte Webanwendungen (z.b. Java-Applets oder Microsoft Active X) Server-basierte Webanwendungen (z.b. CGI, SSI, ASP, Servlets, JSP ) 1
Datenbanken: Servlets und JSP Server-basierte Web-Datenbank-Anwendungen Die Webseite wird auf dem Server aus HTML-Tags und Datenbankinhalten zusammengebaut, bevor sie über HTTP zum Client (browser) geschickt wird. Problematisch: Das HTTP ist zustandslos, d.h. bei aufeinander folgenden Anfragen des Clients an die Datenbank muss ein Session-Management diese Anwendungsfunktionalität regeln. Wir werden im Folgenden Server-basierte Web-Datenbank-Anwendungen mit Hilfe von Servlets und Java Server Pages (JSPs) besprechen. Die Datenbank-Kommunikation wird dabei mit JDBC geführt. 2
Datenbanken: Servlets und JSP Web Browser Der Browser sendet eine Anforderung für ein bestimmtes Servlet oder eine JSP-Seite. Web Server Die Servlet / JSP - Engine führt den zugehörigen Java Code aus. Servlet & JSP Engine JSP Processor Java Servlet Eine dynamisch erzeugte HTML-Seite wird als Antwort an den Browser zurückgeschickt 3
Datenbanken: Servlets und JSP Servlets Java Servlets sind Java-Programme, die HTML-Code auf Anfrage generieren. Java Servlets haben 2 Voraussetzungen: a) Integration einer JVM in den Webserver. b) Erweiterung des Webservers um eine Servlet-Engine, die für die Ausführung der Servlet-Klassen zuständig ist (z.b. Tomcat). Java Servlets werden bei der ersten Anfrage initialisiert und verbleiben im Speicher des Servers, müssen also nicht immer neu gestartet werden! Java Servlets können als Klassen exportiert werden, d.h. an potenziell vielen Stellen verwendet werden (Wiederverwendbarkeit). Java Servlets können andere Servlets aufrufen. 4
Datenbanken: Servlets und JSP Servlets Beispiel: (PersonenWebApp.java -> Eclipse, Anwendung) class PersonenWebApp extends HttpServlet { public void service ( HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException { resp.setcontenttype("text/html"); String user = request.getparameter("user"); PrintWriter out = resp.getwriter();...datenbank-kommunikation... // Erzeugen einer HTML-Seite out.println("<!doctype HTML PUBLIC \"-//W3C//DTD HTML 4.0 Final//EN\">\n"); out.println("<html>\n" + "<HEAD> <TITLE>Personendaten mit servlet</title> </HEAD>\n"); } }...Ausgabe der Datenbank-Kommunikation... 5
Datenbanken: Servlets und JSP Servlets Zur Erzeugung von Servlets wird das Archiv servlet-api.jar benötigt und muss im Klassenpfad der Anwendung stehen. Dieses Archiv enthält die Packages javax.servlet, javax.servlet.http, etc... mit den notwendigen Interfaces und Klassen. Das kompilierte Servlet wird ins entsprechende Verzeichnis der Servlet- Engine gelegt. Der Lebenszyklus ist wie folgt: - Beim ersten Aufruf (etwa über ein Form Action tag): - Laden der Servlet-Klasse - Erzeugen einer Instanz - Initialisierung durch Aufruf der Methode init - Bei jedem Aufruf : - Aufruf der Methode service public void service ( HttpServletRequest req, HTTPServletResponse resp) 6
Datenbanken: Servlets und JSP Servlets Übergabe von Parametern und Daten: In der aufrufenden HTML-Seite: Auslesen im Servlet: < form action = MyServlet method = post > < input type = Text name = v_personenname > < /form > String name= request.getparameter( v_personenname ); Dynamische Ausgabe als HTML-Seite: PrintWriter out = resp.getwriter(); out.println( <H2> name </H2> ); 7
Datenbanken: Servlets und JSP Servlets Kommunikation mit relationalen Datenbanken: Prinzipiell: Zur Kommunikation mit einem relationalen DB-System kann nur die JDBC-Technik benutzt werden! Es gibt zwei Möglichkeiten: a) Bei jedem Browser-Aufruf Erzeugen einer einzelnen Connection in der service() - Methode; b) Beim Starten des Servlets in der init() - Methode einen Connection- Pool erzeugen mit einer gewissen Anzahl dann existierender DB- Connections, die bei jedem Browser-Aufruf in der service() - Methode benutzt werden können; Werden in der Anwendung immer wieder kleinere DB-Anfragen gestellt von verschiedensten Anwendern, die nicht viele Rechte in der DB haben sollen, empfiehlt sich die Möglichkeit b), da dann der Zeitaufwand zur Erstellung einer Verbindung entfällt! 8
Datenbanken: Servlets und JSP Servlets Kommunikation mit relationalen Datenbanken: Beispiel Connection Pool public class PersonenWebAppJSP_CP extends HttpServlet { private int errorcode; private ConnectionPool cp; public void service(httpservletrequest request, HttpServletResponse resp) throws SQLException { Connection con = null; try { con = cp.getconnection(); } catch(sqlexception sqle) {...} }... } public void init() { String driver = "oracle.jdbc.driver.oracledriver"; String url = "jdbc:oracle:thin:@localhost:1521:gbir" ; String user = adbsws1011"; String pw = "test"; try { cp = new ConnectionPool(driver, url, user, pw, 10, 50, false); } catch(sqlexception sqle) { // Irgendwie die Exceptions behandeln } } 9
Datenbanken: Servlets und JSP Servlets Servlets im Einsatz mit der Servlet-Engine Tomcat 5.5 und höher: Für jede Web-Anwendung muss im Unterverzeichnis /webapps des Tomcat-Homeverzeichnisses ein eigenes Verzeichnis angelegt werden ( hier: /webapps/personenwebapp ). In dieses Verzeichnis wird die aufrufende HTML-Seite gelegt ( hier: PersonenWebApp-Servlet.html ). In dieses Verzeichnis muss auch das Verzeichnis /WEB-INF mit den Unterverzeichnissen /classes und /lib kopiert werden. Das kompilierte Servlet und weitere Anwendungsklassen oder -packages werden im Verzeichnis /classes abgelegt ( hier:.../webapps/personenwebapp/web-inf/classes/personenwebapp.class ) Im Verzeichnis Tomcat-Home/shared/lib sollte das Archiv ojdbc14.jar oder höher für den Zugriff auf die ORACLE-Datenbank liegen. 10
Datenbanken: Servlets und JSP Servlets Servlets im Einsatz mit der Servlet-Engine Tomcat 5.5 und höher: Wenn die Applikation mit einem SDK wie Eclipse entwickelt wird, vereinfacht sich die Sache: 1. Erzeugen eines neuen dynamischen Webprojekts und Programmieren der Applikation; 2. Speichern dieses Webprojekts als WAR (Web Archive); 3. Einfügen dieser WAR-Datei in das webapps-verzeichnis des Tomcat; 4. Beim ersten Aufruf dieser neuen Applikation erzeugt Tomcat ein Unterverzeichnis mit allen nötigen Einträgen. 11
Datenbanken: Servlets und JSP Servlets Servlets im Einsatz mit der Servlet-Engine Tomcat 5.5 und höher: Im Verzeichnis.../WEB-INF muss eine Datei web.xml existieren mit den Informationen über das Servlet (Name, Zugriffspfad,...) Beispiel: <?xml version = '1.0' encoding = 'ISO-8859-1'?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>meinservlet</servlet-name> <servlet-class>personenwebapp</servlet-class> </servlet> <servlet-mapping> <servlet-name>meinservlet</servlet-name> <url-pattern>/pwa</url-pattern> </servlet-mapping> </web-app> Wird die Datei web.xml oder das Servlet verändert, muss Tomcat neu gestartet werden! 12
Java Server Pages (JSPs) sind eine Weiterentwicklung der Servlet- Technologie von Sun Microsystems. Servlets sind Java-Programme, in die HTML-Code eingebettet ist zur Erzeugung dynamischer HTML-Seiten. Java Server Pages sind HTML-Seiten, in die über spezielle Tags Java-Code eingebettet werden kann zur Erzeugung dynamischer HTML-Seiten. JSPs werden als.jsp-dateien geschrieben, die im gleichen Verzeichnis der Servlet-Engine (Tomcat) abgelegt werden wie die HTML-Seiten. Beim ersten Aufruf einer JSP erzeugt die Servlet-Engine bzw. der JSP- Prozessor aus der JSP ein Servlet, das weiterverarbeitet wird. In JSPs kann der komplette Sprachumfang von Java über spezielle Tags genutzt werden, also auch die Bibliotheken für Zugriffe auf andere Systeme 13 (JDBC, JNDI, etc...
Typische Vorgehensweise: Erstelle den statischen Teil der Response-Seite mit normalem HTML; Ergänze den statischen Teil durch den Java-Code, der den dynamischen Teil erzeugt, eingebettet in spezielle System- Tags. Oder: Ergänze den statischen Teil durch speziellen HTML-Code, der durch die Benutzung spezieller Tags möglich ist (ohne Java-Code, z. B. mit JSTL). 14
Es gibt 3 Kategorien von System-Tags, die zur Verfügung stehen: -Scripting-Tags (Formulierung von Java-Code) < % Java-Code % > -Directive-Tags (Formulierung von Kontrollstrukturen für das resultierende Servlet) < %@ Directive % > -Action-Tags (Steuerung der JSP-Engine bzw. Nutzung bestehender anderer Komponenten) < jsp: Action / > Darüber hinaus gibt es weitere Bibliotheken mit Tags, die eingebunden werden können, und auch Benutzer definierte Tags können erstellt werden! Der Aufruf geschieht wie beim Servlet über das Form Tag : < form action= myjsp.jsp method= post >... </form> 15
Beispiel: <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Final//EN\"> <HTML> <HEAD> <TITLE>Personenanzeige mit JSP</TITLE> </HEAD> <BODY bgcolor = "FFFF99"> < %@ page contenttype = text/html; charset=iso-8859-1 %> < %@ page import = "java.sql.* %> < %@ page import = "java.util.* %> < %@ page import = "personenwebapp.*" %> < %@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> < % String user = request.getparameter("user"); String password = request.getparameter("passwd"); String database = request.getparameter("database"); Connection con = DAOPersonen.getConnection(user, password, database); % >... </BODY> </HTML> 16
Scripting Tags: Vereinbarungen Vereinbarungen zur Deklaration von Variablen, Methoden,... Syntax: < %! Vereinbarungen % > Beispiel: <%! int v_persnr=0; String v_name; %> <%! String tuwas(int i) {... } %> Diese deklarierten Vereinbarungen werden beim Übersetzen der JSP in den Rumpf der Servlet-Klasse außerhalb bestehender Methoden eingefügt und zur Laufzeit ausgewertet. 17
Scripting Tags: Anweisungen (Scriptlets) Anweisungen zur Formulierung von Java-Ausführungscode Syntax: < % Anweisungscode % > Beispiel: <% if (j<100) { tuwas(1); } else { tuwas(2); } var_x = 37; %> Dieser Java-Code wird beim Übersetzen in die Service-Methode des Servlets eingefügt und zur Laufzeit ausgewertet. 18
Scripting Tags: Ausdrücke Ausdrücke zur Ausgabe von Werten Syntax: < %= Ausdruck % > Beispiel: <%= Das ist ein guter Ausdruck %> Anmerkung: ist äquivalent zu: <%= Das ist ein guter Ausdruck %> <% out.println( Das ist ein guter Ausdruck ) %> Ausdrücke werden zur Laufzeit ausgewertet und der Ausgabe des Servlets hinzugefügt. 19
Scripting Tags: Kommentare Kommentare können auf zwei Arten erzeugt werden: Kommentare die in das erzeugte Dokument übernommen werden: Syntax: <!-- Dieser Kommentar wird übernommen -- > Kommentare auf der JSP-Seite: Syntax: < %-- Dieser Kommentar bleibt in der JSP-Seite --% > 20
Scripting Tags: Um die Arbeit zu erleichtern, können bei Ausdrücken und Anweisungen vordefinierte Variablen benutzt werden. Die wichtigsten sind: request (vom Typ HttpServletRequest) Beispiel: user :< %= request. getparameter( user ) % > response (vom Typ HttpServletResponse) Beispiel: <% response.setcontenttype( text/html ); %> session out (vom Typ HttpSession) (vom Typ PrintWriter) 21
Directive Tags: Direktiven beeinflussen die gesamte Struktur des resultierenden Servlets. Hier können spezielle Taglibs oder andere Dateien in die aktive JSP eingebunden werden, oder andere Festlegungen getroffen werden. Allgemeine Syntax: <%@ Direktivenname {Attribut= wert } %> Die Spezifikation Version 1.1 legt 3 Direktiven fest: taglib, include, page. 22
Directive Tags: taglib Die Direktive taglib dient dazu, zusätzliche Tag-Bibliotheken in die aktive JSP einzubinden Beispiel: <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c %> Es gibt Erweiterungen der hier beschriebenen Tags, die vom Hersteller zur Verfügung gestellt werden wie zum Beispiel die jstl Bibliothek (java standard tag library). Man kann auch eigene neue Tags generieren und diese über die taglib- Direktive einbinden. 23
Directive Tags: include Die Direktive include bindet zur Übersetzungszeit externe Dateien, zum Beispiel andere JSPs, in die aktive JSP bzw. das resultierende Servlet ein. Beispiel: <%@ include file = relativer URL %> Damit ist es möglich, bestimmte Dateien, zum Beispiel Kopf- und Fuß- Seiten einmal zu schreiben und diese in alle JSP-Seiten der Applikation einzubetten. Die include Direktive wird an die Stelle im Code der JSP gesetzt, an der die neue Funktionalität eingebunden werden soll! Vorsicht: wird die eingebundene Seite verändert, müssen alle JSPs, die diese Seite einbinden, aktualisiert werden! 24
Directive Tags: page Die Direktive page wird verwendet zur Strukturierung des resultierenden Servlets. Beispiel: <%@ page import= java.sql.*" %> <%@ page contenttype= text/html %> <%@ page errorpage= Fehler.jsp %> Für die page Direktive sind verschiedene Attribute festgelegt: language, extends, import, buffer, autoflesh, info, isthreadsave, contenttype, errorpage, iserrorpage, session. Eine JSP kann mehrere page Direktiven enthalten, jedes Attribut darf nur einmal vorkommen, mit Ausnahme von import. Die page Direktive kann an beliebiger Stelle im Code der JSP gesetzt werden. 25
Action Tags: Es gibt Standard Aktionen und benutzerdefinierte Aktionen. Letztere werden über Tag-Bibliotheken vereinbart. Allgemeine Syntax: <jsp: Aktionsname {Attribut= wert } /> Als Standard-Aktionen stehen eine Reihe von Attributen zur Verfügung: include, forward, plugin, param, fallback,... include: z.b. Einbettung der Ausgabe einer JSP in eine andere JSP zur Laufzeit! <jsp: include page= MeineandereJSP.jsp flush= true /> forward: Weiterleitung einer Anfrage an eine andere Seite oder ein Servlet. <jsp: forward page= MeineAntwortJSP.jsp /> 26
Unterschied zwischen der Direktive include und der Aktion include: <%@ include file= Kopf.jsp" %> Die JSP Kopf.jsp wird zur Übersetzungszeit in die aufrufende JSP übernommen! Mit dieser Technik können z.b. oft wiederholte Teile von Seiten (Kopf- und Fuss-Zeilen) ausgelagert und eingebunden werden! <jsp: include page= Weiterverarbeitung.jsp flush= true /> Die Ergebnisse der JSP Weiterverarbeitung.jsp werden zur Laufzeit in die aufrufende JSP eingebettet! 27
Eine weitere wichtige Aktion ist das usebean Tag: <jsp: usebean id= person" class= DBPerson /> Mit dieser Anweisung werden komplexe Objekte, die an die JSP übergeben wurden, in der JSP zur Weiterverarbeitung aufgenommen. Im aufrufenden Servlet: ein DBPerson-Objekt pers mit Namen person req.setattribute( person", pers); String url = resp.encodeurl("/anzeige-person.jsp"); RequestDispatcher dispatcher = getservletcontext().getrequestdispatcher(url); dispatcher.forward(req,resp); In der JSP Anzeige-Person.jsp: <jsp: usebean id= person" class= DBPerson /> 28
Verwendung weiterer Tag Bibliotheken: Die Verwendung langer Java-Codefragmente in den JSPs macht diese unübersichtlich. java.sun bietet deshalb in weiteren Bibliotheken zusätzliche Tags an zu Variablendeklarationen, bedingten Anweisungen, Schleifen, auch SQL- Verarbeitung. Beispiel: JSTL (Java Standard Tag Library) JSTL enthält z. B. folgende Tags: c:set c:out c:foreach sql:setdatasource... Setzen von lokalen Variablen Ausgabe Iteration Erzeugen einer Datenbankverbindung Zusätzlich können von den Benutzern weitere Tag-Bibliotheken angelegt werden, so dass man am Ende in einer JSP völlig ohne Java- Code auskommt! 29
Beispiel: <c:if test="${!empty person.adressen}"> <H2 align="center"> Adressen: </H2> <table align=center width="70%" bgcolor="#cccccc" border="0" cellpadding="3" cellspacing="3" > <tr> <th align="left width="10%">adrnr</th><th>plz</th><th>ort</th> <th>strasse</th> <th>typ</th> </tr> <c:foreach var="adr" items="${person.adressen}"> <tr> <td align=left><c:out value="${adr.adrnr}"/></td> <td align=center><c:out value="${adr.plz}"/></td> <td align=center><c:out value="${adr.ort}"/></td> <td align=center><c:out value="${adr.str}"/></td> <td align=center><c:out value="${adr.typ}"/></td> </tr> </c:foreach> </table> </c:if> 30
Fazit: Die Erzeugung von Web-Datenbank-Anwendungen mit Servlets und JSPs sollte nach dem MVC-Muster erfolgen: Control (C): - ein oder mehrere Servlets, die quasi als Dispatcher dienen zwischen Browser, Datenbank und JSPs; - Data Access Object-Klassen (DAO-Klassen), die die Kommunikation mit der Datenbank übernehmen; View (V): - JSPs, die die Ausgabe erzeugen; Model (M): - Datenbanktabellen; - Anwendungsklassen, die die Tabellen abbilden; 31
Datenbanken: Servlets und JSP Zusammenspiel zwischen Servlet und den Ausgabe-JSPs: Das Servlet übergibt die erstellten Daten einer JSP über eine Dispatcher- Funktionalität: request.setattribute( eineperson", person); String url = "/PersonenSucheAusgabe.jsp"; RequestDispatcher dispatcher =getservletcontext().getrequestdispatcher(url); dispatcher.forward(request,resp); Hier wird ein Objekt person als Parameter mit dem Namen eineperson übergeben. Mit der Methode forward() des Dispatcher-Objekts geht die Kontrolle vom Servlet auf die JSP PersonenSucheAusgabe.jsp über! 32
Datenbanken: Servlets und JSP Zusammenspiel zwischen Servlet und den Ausgabe-JSPs: Die JSP kann die erstellten Daten aus dem Servlet auf unterschiedliche Art übernehmen. Eine davon ist z.b.: <% DBPersonen person = (DBPersonen) request.getattribute( eineperson"); %> Hier wird ein Objekt person vom Typ DBPersonen als Parameter mit dem Namen eineperson und dem Wert person übernommen und kann zur Ausgabe weiterverarbeitet werden. Alternative: <jsp:usebean id= eineperson" class="personenwebapp.dbpersonen" /> 33