Java Web-Anwendungen Modell 1 JSPs & Servlets Beans Model-1-Architektur
Web-Server Was ist ein Web-Server? Implementierung des HTTP-Request-Response-Paradigmas Empfängt HTTP-Requests: URL evtl. mit Parametern und Cookie Antwortet mit Rückgabe des dadurch referenzierten Dokuments als Response URL Web- Client HTML Web- Server (c) schmiedecke 10 SE2-2-Java-Webapps 2
Web-Anwendung: Dynamischer Content dynamischer Content URL CGI PHP JSP/ Servlet ASP Web- Client Web - Server Programm DB HTML +JavaScript +Applets Front End Web Publishing Back End (c) schmiedecke 10 SE2-2-Java-Webapps 3
Programmiermodelle Programmorientiert (Perl) serverseitige Applikation besteht aus Programmen erzeugen HTML-Dokument als Ausgabestrom + Fachlogik gut strukturierbar, Kontrolle übersichtlich - Dokumentenstruktur verborgen - Layout-Veränderungen erfordern Programmänderungen - Dokumentenorientiert (ColdFusion) - serverseitige Applikation ist HTML-Dokument mit eingebetteten Scripten + Dokumentenstruktur gut erkennbar (gestaltbar) + einfaches Handling - Fachlogische Struktur verwischt (c) schmiedecke 10 SE2-2-Java-Webapps 4
PHP-Beispiel Dokumentenorientierte Programmierung PHP-Skripte in HTML eingebettet Unmittelbar interpretierbarer Code Semantik: Der Code wird interpretiert und ggf. das Ergebnis in die HTML- Seite eingefügt. <html> <head><title>first Example</title></head> <body> <h3>php-clock</h3> Hello<br> It is now: <?= date("l, d.m.y, G:i:s")?><br> </body> </html> (c) schmiedecke 10 SE2-2-Java-Webapps 5
Ausführung von Server-Skripten (PHP) PHP-Implementierung: Ausführung von PHP-Skripten vorkompiliert - interpretiert Standardinstallation als CGI-Prozess Moderner als Server-Modul innerhalb des Server-Adressraums dauerhafte Prozesse dauerhafte DB-Verbindungen Wöhr Wöhr (c) schmiedecke 10 SE2-2-Java-Webapps 6
Scripting mit Java: JSP Java Server Pages: Struktur einer HTML-Seite Skripte: "eingestreuter Java-Code" Suggerierte Semantik: Der Code wird ausgeführt und das Ergebnis an der entsprechenden Stelle in die HTML-Seite eingefügt. <html> <head><title>first Example</title></head> <body> <h3>jsp-clock</h3> Hello<br> It is now: <%= new java.util.date().tostring() %><br> </body> </html> (c) schmiedecke 10 SE2-2-Java-Webapps 7
Was ist möglich? JSP-Syntax JSP-Expressions <%= auswertbarer Java-Ausdruck %> der ermittelte Wert wird textuell in die Seite eingefügt und damit angezeigt JSP-Scriptlets <% beliebiger ausführbarer Java-Code %> der Code wird ausgeführt, ggf. gesetzte Variablenwerte können im weiteren Verlauf der Seite genutzt, z.b. mittels Expressions angeszeigt werden. JSP-Deklarationen <%! Deklaration einer Methode oder Instanzvariablen %> die Deklarierten Methoden und Instanzvariablen können an beliebiger Stelle in der Seite genutzt werden. (c) schmiedecke 10 SE2-2-Java-Webapps 8
JSP-Syntax Forts. JSP-Kommentare <%-- JSP-Kommentar, im HTML-Code unsichtbar --%> <!-- HTML-Kommentar, im HTML-Code sichtbar --> JSP-Direktiven File-Direktive: <%@ include file="datei Pfad relativ zur JSP" %> Datei wird vor der HTML-Erzeugung textuell eingebunden Page-Direktive: <%@ page pageencoding="utf-8" %> <%@ page contenttype="text/html" %> <%@ page import="java.util.date,java.util.arraylist" %> Machen globale Angaben über die JSP-Seite Taglib-Direktive: später (c) schmiedecke 10 SE2-2-Java-Webapps 9
JSP-Beispiel Deklaration und Benutzung einer Instanzvariable <html> <head><title>second Example</title></head> <body> <h3>jsp-clock</h3> Hello<br> <%! String datetime = new java.util.date().tostring(); %> It is now: <%= datetime %><br> </body> </html> Das ist einfach aber auch problematisch Wir kommen darauf zurück... (c) schmiedecke 10 SE2-2-Java-Webapps 10
JSP-Beispiel Mit import-direktive <%@ page import="java.util.date" %> <html> <head><title>first Example</title></head> <body> <h3>jsp-clock</h3> Hello<br> <%! String datetime = new Date().toString(); %> It is now: <%= datetime %><br> </body> </html> (c) schmiedecke 10 SE2-2-Java-Webapps 11
JSP-Beispiel Scriptlet zum Berechnen von Werten Verwendung lokaler Variablen <html> <head><title>why, doesn't this look ugly?</title></head> <body style="font-family:sans-serif;padding-top:15px;"> <h3> <% String[] valuearray = {"This", "is", "a", "rather", "dull", "example"}; int i; for (i = 0; i < valuearray.length; i++) { %> <%= valuearray[i] %> <% } %> </h3> </body> </html> (c) Lesbarkeits-Alarm! schmiedecke 10 SE2-2-Java-Webapps 12
Java ist nicht Basic! Java-Code steht nicht einfach für sich Es muss einen Klassen-Kontext geben Jede JSP entspricht einer Java-Klasse Alle Methoden- und Instanzvariablen-Deklarationen gelten genau innerhalb einer JSP Import-Direktiven gelten für eine JSP (daher auch "Page- Direktiven") Es könnten auch andere Klassen genutzt werden, die im Classpath liegen aber was ist der Classpath? Natürlich kann so auch auf Datenbanken und andere Ressourcen zugegriffen werden alles, was Java kann, ist möglich. (c) schmiedecke 10 SE2-2-Java-Webapps 13
Wie wird eine JSP ausgeführt? Auf dem Webserver muss ein Web-Container installiert sein. Die JSP wird in dem Web-Container gespeichert (das nennt man Deployment) Der Web-Container wandelt die JSP in eine Java-Klasse um. Die Klasse wird kompiliert und instanziiert. Eine Client-HTTP-Anfrage auf eine JSP (Endung.jsp) wird dem Web-Container übergeben. Der Web-Container ruft die Klasseninstanz und gibt die als Ergenis gelieferte HTML (oder XML, chtml,...)-seite als Response an den Webserver zurück Container JSP (c) schmiedecke 10 SE2-2-Java-Webapps 14
Java-Web-Technologie: JEE Ohne EJB- Container: JSE (c) schmiedecke 10 SE2-2-Java-Webapps 15
Deployment Genormte Verzeichnisstruktur für Java-Web-Anwendungen Gesamtes Verzeichnis packen: WAR-Datei ("Web Archive") == JAR mit fester Struktur In ein bestimmtes Unterverzeichnis des Web-Containers "schieben" bei Tomcat ist das "webapps bei Glassfish "autodeploy" Ggf. den Web-Container starten Der Web-Container erledigt den Rest (s.nächste Folie) myjsp myjsp.war (c) schmiedecke 10 SE2-2-Java-Webapps 16
Der JSP-Lebenszyklus (im Web-Container) 1. Transformieren: Die gesamte JSP-Seite wird in eine Java-Klasse umgeformt Klasse vom Typ Servlet Leistet das, was wir intuitiv von der JSP erwarten und erzeugt ("druckt") HTML-Code 2. Kompilieren Das Servlet wird "normal" kompiliert. (Benötigt Servlet-API) 3. Instanziieren Das Servlet wird geladen und instanziiert. Der Web-Container verwaltet die Instanz. 4. Aufruf Bei jeder Client-Anfrage wird eine bestimmte Service-Methode der Servlet- Instanz gerufen (meistens "doget" oder "dopost") Schritte 1-3 geschehen implizit beim "Deployen" (c) schmiedecke 10 SE2-2-Java-Webapps 17
Servlets müssen reentrant sein! Servlets werden beim Deployment instanziiert und dann von verschiedenen Clients genutzt: Client 1 Servlet 1 Servlet 2 Client 2 Servlet 3 Web-Container (c) schmiedecke 10 SE2-2-Java-Webapps 18
Vorsicht, Instanzvariablen! Initialisierungen von Instanzvariablen erfolgen bei Deployment oder Server-Neustart, nicht beim Aufruf! <html> <head><title>firstexample</title></head> <body> <h3>jsp-clock</h3> Hello<br> <%! String datetime = new java.util.date().tostring(); %> It is now: <%= datetime %><br> </body> </html> Hier wird die Initialisierung wird nur 1x bei Instanziierung ausgeführt!! (c) schmiedecke 10 SE2-2-Java-Webapps 19
Vorsicht, Instanzvariablen! Dieselbe Servlet-Instanz beantwortet Anfragen verschiedener Clients! Das bedeutet, dass dieselben Instanzvariablen von unterschiedlichen Clients gesetzt und benutzt werden können. Instanzvariablen machen den Code nicht "reentrant" oder "threadsafe"! <html> <head><title>fourth Example</title></head> <body> <h3>jsp-clock</h3> Hello<br> <%! String datetime = new Date().toString(); %> Your last visit was <%= datetime %> <% datetime = new Date().toString(); %> It is now: <%= datetime %><br> </body> </html> Hier wird vermutlich der Besuch eines anderen Clients genannt! (c) schmiedecke 10 SE2-2-Java-Webapps 20
Lokale Variablen Lokale Variablen sind threadsafe: Bei jedem Aufruf von getdate wird die Variable neu berechnet, <html> <head><title>firfth Example</title></head> <body> <h3>jsp-clock</h3> Hello<br> <%! String getdate() { String datetime = new java.util.date().tostring() ; return datetime; } %> It is now: <%= getdate() %><br> </body> </html> (c) schmiedecke 10 SE2-2-Java-Webapps 21
Fragen... Warum nur eine Instanz? Zeitersparnis: Lade- und Instanziierungszeit Skalierung durch zusätzliche Instanzen und Load-Balancing Wie funktioniert der Datenaustausch? Eingabedaten werden als Request-Parameter übergeben. Der Web-Container macht sie als Umgebungsvariablen zugänglich. Wie hält man die Daten der verschiedenen Clients auseinander? Der Web-Container verwaltet Sessions und auch andere Kontexte. Die Umgebungsvariablen sind Kontexten zugeordnet. Was ist der Classpath? Der Web-Container stellt einen Classpath her. Dieser wird beim Deployment ergänzt. (c) schmiedecke 10 SE2-2-Java-Webapps 22
Und was ist ein Servlet? Normale Java-Klasse Erweitert (z.b.) HttpServlet und kann damit HttpRequests verarbeiten und HttpResponses erzeugen benötigt dazu das Servlet-API: Paket javax.servlet und Unterpakete implementiert vom Web-Container Läuft im Web-Container. Der Web-Container ruft entweder doget(httprequest, HttpResponse) oder dopost(httprequest, HttpResponse) Diese Methode implementieren! Response als PrintStream erzeugen! linearisiertes HTML (c) schmiedecke 10 SE2-2-Java-Webapps 23
Simple JSP <html> <head><title>simple JSP</title></head> <body> Your browser is: <%= request.getheader("user-agent") %><br> Your IP address is: <%= request.getremoteaddr() %><br> </body> </html> (c) schmiedecke 10 SE2-2-Java-Webapps 24
SimpleServlet public class SimpleServlet extends HttpServlet { public void doget(httpservletrequest request, HttpServletResponse response) throws IOException, ServletException{ // 1. process request-parameters and -headers... String client = request.getheader("user-agent"); String ipaddress = request.getremoteaddress(); // 2. prepare the response... response.setcontenttype("text/html"); // 4. write to Response PrintWriter PrintWriter out = response.getwriter(); out.println("<html>"); out.println("<head>"); out.println("<title> SimpleServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("your browser is: "+ client + "<br> Your IP address is: "+ ipaddress + "<br>); out.println("</body></html>"); (c) schmiedecke 10 SE2-2-Java-Webapps 25 }
Servlet-Deployment Servlets gehören ins WEB-INF-Verzeichnis kompiliert ins Unterverzeichnis.classes Sie werden in einer XML-Konfigurationsdatei bekannt gemacht: web.xml der Deployment Descriptor beschreibt die Servlets enthält Servlet-Mappings: welches Servlet reagiert auf welche URLs? gehört in die Wurzel des WEB-INF-Verzeichnisses (c) schmiedecke 10 SE2-2-Java-Webapps 26
web.xml der Deployment Descriptor <?xml version="1.0" encoding="utf-8"?> <web-app> <servlet> <servlet-name>start</servlet-name> <servlet-class>myapps.startservlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>start</servlet-name> <url-pattern>/index.html</url-pattern> </servlet-mapping> </web-app> (c) schmiedecke 10 SE2-2-Java-Webapps 27
Wohin mit den Daten? Instanzvariablen?? nicht threadsafe, Clients kommen sich ins Gehege lokale Variablen?? minimale Lebensdauer nicht zur Speicherung und Weitergabe von Information geeignet Speicher-Objekte erzeugen! aber wo speichert man die Referenzen darauf (s.o.!)?? Der Server muss hier Unterstützung leisten! Beans werden vom Web-Container instanziiert und verwaltet (c) schmiedecke 10 SE2-2-Java-Webapps 28
Was sind Beans? Beans sind "Pojos" "plain old java objects" Attribute heißen "Properties" und haben Getter- und Setter-Methoden (ggf. gibt es ein genormtes Event-Modell) public class Bohne { private String prop; public void setprop(..); public String getprop(); } Durch diese "genormte" Form können Attribut-Zugriffe automatisch generiert werden können Bean-Objekte durch Werkzeuge "konfiguriert" werden und das war's schon! Für die Datenspeicherung von JSPs gut geeignet... (c) schmiedecke 10 SE2-2-Java-Webapps 29
Beans im Web-Container Der Web-Container instanziiert und verwaltet die Beans. Servlet 1 Die Servlets können sie als Datenspeicher nutzen. Servlet 3 Servlet 2 Web-Container (c) schmiedecke 10 SE2-2-Java-Webapps 30
Kontexte Beans sollen client-spezifische Daten enthalten! Zu lösen: Lebensdauer und Zugehörigkeit der Beans Die Antwort heißt Kontext page context für Beans, die nur während eines (nur JSP) Seitenaufrufs benötigt werden request context für Beans, die von dem Eintreffen eines Requests bis zum Senden des Response benötigt werden session context für Beans, die über die Dauer einer Session erhalten bleiben sollen application context für Beans, die während der gesamten Laufzeit der Webanwendung erhalten bleiben sollen (bis zum Server-Neustart). (c) schmiedecke 10 SE2-2-Java-Webapps 31
Beans verschiedener Sessions Die Beans einer Session bilden einen Kontext. Servlet 1 Der Zugriff erfolgt über diesen Kontext. (Das Servlet bedient jeden Kunden aus seinem Konto) Web-Container (c) schmiedecke 10 SE2-2-Java-Webapps 32
Beans mit verschiedenen Lebensdauern Jsp1 Jsp2 Jsp3 request session application (c) schmiedecke 10 SE2-2-Java-Webapps 33
Bean-Nutzung: <jsp: usebean.../> <jsp:usebean id="bohne" scope="session" class="front.bean1.class" /> JSP-Standardaktion, wird vom Container ausgeführt: Die JSP möchte ein Objekt namens "bohne" vom Typ Bean1 benutzen, das im Session-Kontext liegt. Diesen Wunsch könnten auch andere JSPs in derselben Session äußern dann kommunizieren sie innerhalb einer Session über dieses Objekt. Wenn es "bohne" schon gibt, wird das Objekt identifiziert, wenn nicht, wird es erzeugt (c) schmiedecke 10 SE2-2-Java-Webapps 34
Zugriff auf die Beans <jsp:setproperty name="bohne" property="username" value="mustermann"/> <jsp:setproperty name="bohne" property="username" param="username"/> <jsp:setproperty name="bohne" property="username" /> <%-- gleicher Name für property und request-parameter --%> <jsp:getproperty name="bohne" property="prop" /> (c) schmiedecke 10 SE2-2-Java-Webapps 35
Beans zur Seitendynamisierung (Zwischen-)Speichern von Eingaben: Eingaben werden als Request-Parameter an die JSP übergeben mit <jsp:setproperty> werden sie in einer Bean-Property gespeichert. Soll die Eingabe persistent gespeichert werden, so kann in der Setter-Methode ein DB-oder Dateizugriff programmiert werden. Anzeigen dynamischer Werte: Die Getter-Methode der Bean greift auf Anwendungsdaten (z.b. eine Datenbank) zu oder errechnet einen Wert dynamisch Der Wert wird mit <jsp:getproperty> in die JSP eingebunden und so beim Erzeugen der HTML-Seite dynamisch generiert. (c) schmiedecke 10 SE2-2-Java-Webapps 36
Beans-Deployment? da hinein, als.class-dateien (eigentlich) alles "HTML-artige" + "Zubehör" gehört ins Wurzelverzeichnis alle Java-Dateien gehören ins WEB-INF-Verzeichnis auch die Servlets (c) schmiedecke 10 SE2-2-Java-Webapps 37
HTML-Formulare <html><body> <form name="input" action="jsp1.jsp" method="get"> Vorname: <input type="text" name="vorame" value="mickey" size="20"> <br>nachname: <input type="text" name="nachname" value="mouse" size="20"> <br> </form> <p> <input type="submit" value="ok"> Wenn Sie auf OK klicken, senden Sie Ihre Eingaben an JSP1.jsp </p> </body></html> dynamisch z.b.: <jsp:getproperty name="mybean" property="nachname"> (c) schmiedecke 10 SE2-2-Java-Webapps 38
Request-Parameter? Was sind Request-Parameter? Paare Name, Wert immer vom Typ String werden beim Aufruf einer Seite im http-protokoll übertragen HTTP-Methode GET: mit? an die URL angehängt HTTP-Methode POST: im Header eingefügt, unsichtbar Wie kommen die Benutzereingaben in die Request- Parameter? Eingaben in HTML-Formularen (nächste Folie) JSP-Tags, die HTML-Eingabeelemente erzeugen und die Eingaben als Request-Parameter weitergeben (später). (c) schmiedecke 10 SE2-2-Java-Webapps 39
Dynamische Navigation? <jsp:forward page="jsp23.jsp" <jsp:param name="servicecenter" value="hb2" /> option. Ergänzung <jsp:forward /> Die Verarbeitung wird von der angegebenen JSP übernommen alle Request-Parameter bleiben erhalten aller bisher erzeugte HTML-Code wird verworfen die Adresszeile im Browser bleibt unverändert <% response.sendredirect("http://myserver/jsp23.jsp") %> Die Kontrolle geht zurück an den Browser der nun jsp23.jsp aufrufen soll Im der Adresszeile erscheint die neue URL In beiden Fällen darf vorher noch nichts an den Client zurückgeschickt worden sein (Puffergröße beachten) (c) schmiedecke 10 SE2-2-Java-Webapps 40
Sessions? HTTP ist zustandslos Der Web-Container verwaltet Sessions über ein Session-ID (generierte Nummer) Wird beim ersten Response wenn möglich als Cookie gesendet, sonst an die URL gehängt Wird bei weiteren Anfragen als Request-Parameter "jsessionid" mitgegeben bei GET sichtbar (c) schmiedecke 10 SE2-2-Java-Webapps 41
Modell-1-Architektur...damit kann man ALLES machen! Jsp1 Jsp2 Java- Anwendung Jsp3 request DB session application (c) schmiedecke 10 SE2-2-Java-Webapps 42
Bean-Nutzung aus Servlets: Kontextvariablen / Implizite Objekte Für jeden Kontext erstellt der Web-Container implizite Objekte, die über Kontextvariablen erreichbar ist: Kontextvariable pagecontext request session application Typ javax.servlet.jsp.pagecontext javax.servlet.http.httpservletrequest javax.servlet.http.httpsession javax.servlet.http.servletcontext (c) schmiedecke 10 SE2-2-Java-Webapps 43
Weitere Kontextvariablen Kontextvariable config out exception Typ javax.servlet.servletconfig javax,servlet.jsp.jspwriter java.lang.throwable (c) schmiedecke 10 SE2-2-Java-Webapps 44
Arbeiten mit Kontextvariablen Kontexte haben Attribute Bean-Struktur, getter und setter z.b. request.getcookies(), response.addcookie(cookie) Attribute können dynamisch hinzugefügt werden und durch die Methoden setattribute(string, Object) und getattribute(string) benutzt werden. Auf diese Weise können Objekte in Kontexten gespeichert werden: die Beans. Dies wird durch die Aktion jsp:usebean spezifiziert (s.u.). Der Container verwaltet die Beans: Instanziierung und Speicherung im passenden Kontext erfolgt implizit (c) schmiedecke 10 SE2-2-Java-Webapps 45
Zugriff auf die Kontexte Servlets können über das Request-Objekt auf die Kontexte zugreifen: request.getsession().getattribute() setattribute() findattribute() if(request.getsession(false).getattribute ("user")== null) response.sendredirect(contextpath + "/login.jsp"); Beans können dort über get/set/find Attribute angelegt und genutzt werden. (c) schmiedecke 10 SE2-2-Java-Webapps 46
Modell-1-Architektur...damit kann man ALLES machen! Jsp1 Jsp2 Java- Anwendung Jsp3 request DB session application (c) schmiedecke 10 SE2-2-Java-Webapps 47
Probleme mit "einfachen" JSPs Übersicht! Vermischung von Technologien und Sprachen: HTML Java JSP-Tags (Standardaktionen) Abhilfe Schritt 1: JSTL JSP Standard Tag Library Tags für alle Kontrollstrukturen Tags für die wichtigsten Formularelemente Abhilfe Schritt 2: JEL JSP Expression Language vereinfachter Zugriff auf Beans (c) schmiedecke 10 SE2-2-Java-Webapps 48
Probleme mit Modell 1 Jede Seite "macht ihr Ding" Verteilte Kontrolle Harte "Verdrahtung" der Anbindung an das "Backend" Referenzen kreuz und quer. Abhilfe Rückbesinnung auf MVC nächstes Mal! (c) schmiedecke 10 SE2-2-Java-Webapps 49
...genug für heute Nächstes Mal geht es um ein Model2- Framework