Organisatorisches. Web-basierte Anwendungen. Ziele der Veranstaltung. Voraussetzungen

Größe: px
Ab Seite anzeigen:

Download "Organisatorisches. Web-basierte Anwendungen. Ziele der Veranstaltung. Voraussetzungen"

Transkript

1 Organisatorisches Organisatorisches Web-basierte Anwendungen Grundlagen und Frameworks Prof. Dr. Peter Barth Hochschule RheinMain Fachbereich Design Informatik Medien Medieninformatik 6. Juli 2015 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Vorlesung Mittwochs, Raum 14, 8:15 9:45 Uhr Praktikum Mittwochs, Raum 13: B ab 10:00 Uhr, A ab 14:15 Uhr, C ab 16:00 Uhr Vorlesungsfolien, Übungsblätter, weitere Informationen https://read.mi.hs-rm.de barth/hsrm/webanw /opt/share/praktika/webanw Bewertung Prüfungsleistung, Mündliche Prüfung 70 % Studienleistung, Praktikum 30 % Projekt Web Python/Basis, mindestens 8 von 15 Punkten Projekt Web Servlet/Framework (Abgabe August), mindestens 8 von 15 Punkten Infrastruktur Pool und/oder fertiges Image /opt/share/downloads/linux/zuhause Jeder individuell ein Repository, 2015webanw/2015webanw<user> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Ziele der Veranstaltung Organisatorisches Voraussetzungen Organisatorisches Design und Realisierung Web-basierter Anwendungen Einsatzgebiete Web-basierter Anwendungen erkennen Problemadäquater Entwurf, Architektur und Technologie- Frameworkwahl Integration externer Dienste und Anwendungen, z.b. DBMS Sicherheitsaspekte, Lastaspekte Umgang mit praxisrelevanten Web-Technologien Grundlagen (CGI, Templating, Integration): mit Python Bewußt ohne (minimal) weitere Frameworks (selber machen) Applikationsserver/Servlet-Container: mit Tomcat Webkomponentensystem: mit Vorbereitung Praxisphase und Beruf Oft wichtigstes Thema Im Praktikum dann meist auch Python (Django), Ruby (Rails), PHP (Zend, Simfony, Typo3), womit Sie nach Veranstaltung nach 1 Woche produktiv arbeiten können Auszeichnungssprachen HTML Grundkenntnisse (de.selfhtml.org) XML Grundkenntnisse Programmieren Python, Java OO, UI-Patterns Datenbanken SQL Integration in Programmiersprachen Spaß An komplexen Dingen An der Umsetzung Infos, Tools und Downloads: /opt/share/praktika/webanw/ /opt/share/downloads/linux/zuhause Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

2 Organisatorisches Einführung Literatur Einführung CGI, Grundlagen Programming Python, O Reilly, Lutz, Kapitel 16 Servlets Core Servlets and JavaServer Pages, Hall & Brown, JAVAEE/servlet, JavaEE/jsp 2.2, dpunkt, Marinscheck et. al JAVAEE/javaserverfaces html, Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Web-basierte Anwendung Dokumentenbasiert, Client-Server Client Präsentation, Dokumentendarstellung Web-Browser Desktop, mobiles Device Server Anwendungsfunktionalität, Dokumentenerzeugung Web-Server Meist Server Klassifikation Inhalte, Layout, Interaktion Anzahl Nutzer, Zugriffe Sicherheit, Verfügbarkeit Anfrage Server Antwort Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Einführung Einführung Statische Inhalte Historie 88, Tim Berners-Lee, Enquire Hypertext, <a href="..." >WWW</a> 90, Name World Wide Web Standards HTTP, URI, HTML Übertragungsprotokoll HTTP, Hypertext Transfer Protocol Eindeutiger Zugriff auf Ressourcen URI (Bezeichner), Uniform Resource Identifier URL (Locator), ein URI Dokumentenformat HTML, Hypertext Markup Language HTTP-Client (Web Browser) Anfrage internet/www.htm de.selfhtml.org Http-Server (Web Server) Antwort Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Dynamische Inhalte Statische Dokumente Dokument liegt vorbereitet vor Keine Personalisierung, keine zustandsabhängigen Seiten, keine Interaktion Dokumente dynamisch generieren Erzeugen des Dokuments für die Antwort der Anfrage Durch Ausführen eines Programms unter Berücksichtigung des Zustands Programm-Ausgabe ist HTML Client/Server Web-Server weiß wann was generiert wird und kommuniziert mit Programm Web-Client (Browser) merkt davon nichts HTTP-Client (Web Browser) dynamisch generiert Anfrage https://www.mi.hs-rm.de/portal/ Http-Server (Web Server) Konfiguration Konfiguration Antwort Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

3 Einführung Einführung Dynamische Inhalte Server Infrastruktur an der Hochschule Common Gateway Interface (CGI) Einfache Integration, mit allen Programmen und Umgebungen möglich, meist Skriptsprachen Aufruf eines externen Programms (separater Prozess) je Anfrage Kommunikation über stdin/stdout und Umgebungsvariablen Integration in Web-Server Programm und Ablaufumgebung (Interpreter) läuft im Web-Server Effizienter, ein Prozess für mehrere Anfragen Separater Container Eng integriert mit HTTP-Server oder eigener HTTP-Server Zusätzliche Dienste (Skalierung, Sicherheit,... ), Ablaufumgebung HTTP-Server Prozess HTTP-Server Prozess HTTP-Server HTTP-Server Container Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Dynamische Inhalte Client Einführung Host Host Host Host: Web-Server: Apache, httpd ssinn001/public_html/ Verfügbar als http.../ ssinn001/ CGI-Programme ssinn001/public_html/cgi-bin/p.cgi Verfügbar als CGI-Programm http.../ ssinn001/cgi-bin/p.cgi Nur in public_html/cgi-bin Integration in Web-Server, Python Web Server Gateway Interface (WSGI) Unter Apache Benutzerkennung ssinn001/public_html/wsgi/app.wsgi http.../ ssinn001/wsgi/app.wsgi Eine WSGI-Datei je App httpd (apache2) Prozess httpd (apache2) Prozess Prozess www login3 mi1x www login3 mi1x Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Common Gateway Interface Erzeugen dynamischer Web-Seiten auf dem Server CGI Roundtrips Visualisierung Common Gateway Interface (CGI) Problem: Jede Interaktion bedingt Server-Kommunikation, auch reine Visualisierung Lösung Skript (Javascript) im Web-Browser Veränderung der Anzeige durch Manipulation des DOM Roundtrips Flackern, wenig Daten Problem: Neuaufbau Seite bei Server-Zugriff (Usability), vorhandene Daten neu übertragen Lösung Skript (Javascript) im Web-Browser Geänderte Daten nachladen, Aktualisieren über DOM-Manipulation Daten asynchron, HTTP/WebSocket Beispiel Autocompletion HTML HTTP-Server XML(Daten) Asynchronuous Javascript and XML (AJAX) In Veranstaltung nur Verwendung, nicht wie es funktioniert Vertiefung im 5. Semester Starten externer Programme zur Dokumentenerzeugung Kommunikation über Umgebungsvariablen und Standardeingabe / Standardausgabe Standardisiert Vorteil Funktioniert in jeder Umgebung, mit jeder Programmiersprache Darauf aufbauend alles realisierbar Nachteil Ressourcen-intensiv, ein neuer Prozess je Anfrage Keine weitergehenden Features Anfrage HTTP-Server Prozess Antwort Host Umgebungsvariablen Standardausgabe Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

4 Common Gateway Interface Common Gateway Interface CGI-Programm in Python Ausgabe auf Standardausgabe Erst Header, dann Content (HTTP-Protokoll) Getrennt durch eine Leerzeile (Extra newline Zeile 2) HTTP-Header Content-Type zwingend notwendig, meist text/html Weitere Header-Zeilen möglich, werden meist von Web-Server ergänzt HTML-Dokument, Content Einfach print auf Standardausgabe Beliebiger Code Fehler: Internal Server Error Vielleicht noch was im Log... hallo.cgi 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 print("<html>") 4 print("<head><title>hallo</title></head>") 5 print("<body>") 6 print("hallo CGI Python") 7 print("</body></html>") CGI Beispiel Details Anfrage 1 GET 2 /~pbart001/cgi-bin/hallo.cgi 3 HTTP/1.1 Umgebungsvariablen 1 SERVER_SOFTWARE=Apache/ SCRIPT_NAME=/~pbart001/cgi-bin/hallo.cgi 3 REQUEST_METHOD=GET 4 SERVER_PROTOCOL=HTTP/1.1 5 HTTP_CONNECTION=Keep-Alive 6 REMOTE_ADDR= SERVER_PORT=80 8 SERVER_ADDR= DOCUMENT_ROOT=/var/www/ 10 HTTP_HOST=www 11 GATEWAY_INTERFACE=CGI/ REMOTE_PORT=53197 Antwort 1 HTTP/ OK 2 Date: Mon, 04 Feb :21:42 GMT 3 Content-Encoding: gzip 4 Connection: Keep-Alive 5 Content-Length: 82 6 Server: Apache/ (Ubuntu)... 7 Vary: Accept-Encoding 8 Content-Type: text/html 9 Keep-Alive: timeout=15, max= <html>... Standardausgabe 1 Content-Type: text/html 2 3 <html> 4 <head><title>hallo</title></head> 5 <body> 6 Hallo CGI Python 7 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Common Gateway Interface Common Gateway Interface Komfortable CGI-Programmierung Umgebungsvariablen Python-Bibliothek cgi Hilfsroutinen cgitb (TraceBack), Ansicht Fehlermeldungen, sehr sinnvoll hallokomf.cgi Informationen in Umgebungsvariablen Vom Web-Server, aus Anfrage Vom Skript verwertbar Informationen Anfrage Anfragemethode, Query-String,... 1 #!/usr/bin/python 2 # immer gleich am Anfang Informationen Infrastruktur 3 print("content-type: text/html\n") 4 import cgi, cgitb 5 cgitb.enable() 6 7 # ab hier spezifisch je Skript 8 fehler 9 print("<html>") 10 print("<head><title>hallo</title></head>") 11 print("<body>") 12 print("hallo CGI Python") 13 print("</body></html>") Fehler in Zeile 8 wird erkannt und entsprechend im Browser ausgegeben. Sehr hilfreich beim Entwickeln. Web-Browser, Web-Server,... env.cgi 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 import cgi, cgitb 4 cgitb.enable() 5 import os 6 for key in os.environ: 7 print("%s=%s" % (key, os.environ[key])) 8 print("<br />") Beispiel ohne HTML-Rahmen. Viele Browser können daraus immer noch etwas machen. Für Vorlesung ok, da man ansonsten zu viel Boilerplate-Code hat. Sie generieren immer korrektes HTML. Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

5 Common Gateway Interface Common Gateway Interface Anfragemethode GET Anfragemethode GET Query-String Uniform Resource Locator (URL) Abruf einer Ressource Beispiel-URL pbart001/cgi-bin/hallo.cgi Protokoll: HTTP Server: www(.mi.hs-rm.de) Pfad: / pbart001/cgi-bin/hallo.cgi HTTP-Protokoll GET GET / pbart001/cgi-bin/hallo.cgi HTTP/1.1 Methode GET Ressource / pbart001/cgi-bin/hallo.cgi HTTP Protokoll Version 1.1 Im Web-Server verpacken In Umgebungsvariablen POST Inhalte in stdin Anfrage GET ~pbart001/cgi-bin/hallo.cgi HTTP/1.1 HTTP-Server Prozess Antwort Host REQUEST_METHOD = GET SERVER_PROTOCOL = HTTP/1.1 REQUEST_URI = /~pbart001/cgi-bin/hallo.cgi Ziel Übergabe von zusätzlichen Informationen an Web-Server Nur die Anfrage (Query) betreffend Query-String Anfrageparameter String an die URL angehängt Einleitendes? Schlüssel/Wert-Paare durch & getrennt Kodierung: ohne Änderung [a-za-z0-9]. - _, Leerzeichen als +, %FF HEX sonst Query-String Integration bei CGI Durch Umgebungsvariable QUERY_STRING Einleitendes??name=Tim&ende=ciao Schlüssel Wert name = Tim ende = ciao Trennendes & Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Common Gateway Interface Common Gateway Interface Query-String verwenden CGI-Bibliothek Auslesen aus FieldStorage Vorgefertigtes Aufbereiten querystring.cgi 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 import cgi, cgitb 4 cgitb.enable() 5 import os 6 form = cgi.fieldstorage() # Aufbereiten 7 name, ende = "noname", "EOF" 8 if "name" in form: 9 name = form["name"].value 10 if "ende" in form: 11 ende = form["ende"].value 12 print("hallo %s,<br />%s" % (name, ende)) 13 print("<br />%s" % os.environ["query_string"]) Ohne Query-String Query-String?name=Tim&ende=ciao Formulare erzeugen Query-String Erzeugen Query-String mit <form>-tag action-attribut: (relative) Ziel-URL method-attribut: Anfrage-Methode, get (oder post) Eingabefelder mit <input>-tag type-attribut: Welches Eingabefeld text: Text-Eingabefeld submit: Knopf... SelfHTML Erzeugter Query-String im Beispiel name=tim&ende=ciao&ok=ok querystringform.html 1 <html><body> 2 <form action="querystring.cgi" method="get"> 3 Name: <input type="text" name="name" /> <br /> 4 Ende: <input type="text" name="ende" /> <br /> 5 <input type="submit" name="ok" value="ok" /> 6 </form> 7 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

6 Common Gateway Interface Formularelemente Parameter mit POST statt GET Formularelemente Hausaufgabe POST statt GET Philosophie: Daten schicken statt holen Server-Zustand darf sich ändern Wiederholte Anfragen können unterschiedliche Ergebnisse haben, Ergebnisse nicht cachen Eigenschaften POST Verpacken auch in String aus Schlüssel/Wert-Paaren, aber Größere Datenmengen möglich (GET auf 2 KByte beschränkt), auch Binärdaten (Bilder, etc.) Nicht sichtbar in URL (nicht im Query-String) Meist nicht sichtbar in Log-Datei Änderung in HTML-<form>, nicht in FieldStorage (ist für POST und GET) Weitergabe CGI über Standardeingabe 1 <form action="postparam.cgi" 2 method="post"> postparam.cgi 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 import sys 4 print sys.stdin.read() Wichtigste Formularelemente Einzeiliges Eingabefeld Einzeiliges Eingabefeld für Passwörter Mehrzeiliges Eingabefeld Mehrzeilige Auswahlliste Dropdown-Box, einzeilige Auswahlliste Radiobuttons Check Box Versteckte Eingabewerte Aktion ausführen, Knopf/Button In SelfHTML nachlesen und ausprobieren Namen/Werte setzen, vorbelegen, formatieren /html/formulare/index.htm Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Formularelemente Templating Formulare und Mehrfachauswahl Mehrfachauswahl Derselbe Schlüssel mehrfach in Formular verwendet Bei Radiobuttons natürlicherweise Mehrere Ergebnisse in Parameter je Schlüssel möglich Muss in Anwendungsprogramm berücksichtigt werden 1 <html><body> 2 <form action="mehrfach.cgi" method="post"> mehrfach.cgi 1 #!/usr/bin/python 3 <input type="checkbox" name="skill" value="c"/> C <br /> 4 <input type="checkbox" name="skill" value="java"/> Java <br /> 5 <input type="checkbox" name="skill" value="python"/> Python <br /> 6 <input type="submit" name="ok" value="ok" /> 7 </form> 8 </body></html> 2 print("content-type: text/html\n") 3 import os, cgi 4 5 form = cgi.fieldstorage() 6 for skill in form.getlist("skill"): 7 print("ich kann %s <br />\n" % skill.capitalize()) Erzeugen der Dokumente Dokumentenfragmente als String im Quellcode :-( HTML im Quellcode nicht als Markup zu erkennen Markup-Quelle ist nicht validierbar Keine Tool-Unterstützung beim Editieren Vermischen von Anwendungslogik und Präsentation Ziel Trennen von Anwendungslogik und HTML-Präsentation HTML-Präsentation auslagerbar Anwendungslogik frei von Markup Ansatz Templating Server Pages Konzept 1 #!/usr/bin/python 2 ctype = "Content-Type: " 3 mime = "text/html" 4 print(ctype+mime+"\n") 5 6 print("<html>") 7 print("<head><title>") 8 print("hallo") 9 print("</title></head>") 10 print("<body>") 11 print("hallo CGI Python") 12 print("</body></html>") Template-Engines Achtung: Art der Dokumentenerstellung unabhängig von technischer Integration (egal ob CGI oder proprietär) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

7 Templating Templating Server Pages Konzept Server Pages Anwendungsgebiet hello.sp Server Pages Einbettung von Skript-Code in Markup (HTML) Zwischen speziellen Tags, z.b. <?..?> oder <%... %> Verfügbar für viele Sprachen und Umgebungen Entwicklungssicht Erstelle statische HTML-Seite Spezieller Bereich agiert dynamisch Ausführungssicht Übersetze HTML-Seite in Skript HTML kopiert sich auf Ausgabe Code bleibt erhalten Führe entstehendes Skript aus 1 <!-- Server Page --!> 2 <html><body> 3 <? 4 s = "Hello World" 5 print(s) 6?> 7 </body></html> hello.sp.py 1 #!/usr/bin/python 2 # Generated 3 print("content-type: text/html\n") 4 5 print("<!-- Server Page --!>") 6 print("<html><body>") 7 s = "Hello World" 8 print(s) 9 print("</body></html>") Anwendungsgebiet Präsentations-Templates, Fokus auf Darstellung/HTML Behandelt Problem, dass Markup in Zeichenketten nicht als solcher erkennbar und validierbar ist Vorteile Web-Designer (HTML-Autoren) können Templates mit vorhandenen Skills anpassen Kann mit HTML-Editoren bearbeitet und teilweise validiert werden (ignorieren Skriptteil) Schnell Ergebnisse Nachteil: Fördert chaotische Mischung von Präsentation und Anwendung Reinform obsolet: Code im HTML nicht besser als HTML im Code Ersetzt durch dedizierte Templating-Engines Heißt auch als Template verwendet noch *SP Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Templating Templating Dokumentenerzeugung mit Templates Dokumentenerzeugung mit Templates Beispiel Trennen Markup und Code Spaghetti-Code Template-Code Markup als separate Teile, z.b. Zeichenketten oder Dateien Markup mit speziellen Platzhaltern Code generiert Inhalte Am Ende Templates mit Inhalten füllen und ausgeben Beispiel Tabelle erzeugen mit Klein-/Großbuchstaben Nächste Seite Templates Skript Eingaben Seite spagzeichen.cgi 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 import cgi, cgitb, string 4 cgitb.enable() 5 6 prog = "Zeichen" 7 8 print("<html><head><title>") 9 print(prog) 10 print("</title></head>") 11 print("<body><table>") for c in string.lowercase: 14 print("<tr><td>") 15 print(c) 16 print("</td>") 17 print("<td>") 18 print(c.upper()) 19 print("</td></tr>") tempzeichen.cgi 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 import cgi, cgitb, string 4 cgitb.enable() 5 6 page = """<html> 7 <head><title>%s</title></head> 8 <body> 9 <table>%s</table> 10 </body> 11 </html>""" 12 tabline="<tr><td>%s</td><td>%s</td></tr>" lines = [] 15 for c in string.lowercase: 16 lines.append(tabline%(c,c.upper())) print(page % ("Zeichen", "\n".join(lines))) print "</table></body></html>" Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

8 Templating Templating Templating mit Python Einfachst-Templating eingebaut Python Formatier-Operator % Ersetzungsstelle in template durch %(name)s markieren In Ersetzungs-Dictionary dic["name"] = wert setzen Für mehrere Stellen und mehrere Name/Wert-Paare Einsetzen mit template % dic Template-Engines Reichlich vorhanden, ein paar Dutzende in Mehr Features, zum Beispiel Iterieren Uns reicht Einfachst-Templating tpage.tpl 1 <html> 2 <head><title>%(title)s</title></head> 3 <body> 4 <h1>%(title)s</h1> 5 <table>%(tablecontent)s</table> 6 </body> 7 </html> tabline.tpl 1 <tr> 2 <td>%(first)s</td> 3 <td>%(second)s</td> 4 </tr> Templating mit Python Beispiel Beispiel Template-Dateien vollständig einlesen Ersetze z.b. title durch Zeichen, zwei Mal, im Header und am Anfang der Seite Typische letzte Zeile, vorher nie eine Ausgabe tplzeichen.cgi 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 import cgi, cgitb, string 4 cgitb.enable() 5 6 tabline = file("tabline.tpl").read() 7 page = file("tpage.tpl").read() 8 9 lines = [] 10 for c in string.lowercase: 11 dic = { first : c, 12 second : c.upper()} 13 lines.append(tabline%dic) dic = { title : "Zeichen"} 16 dic[ tablecontent ] = "\n".join(lines) print(page % dic) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Templating Templating Sichere Integration von Inhalten Korrekte/sichere Darstellung von Texten Spezielle Regeln für Markup (HTML) müssen eingehalten werden (Aufgabe des Template-Autors) Benutzerdefinierte Inhalte (potenziell böse) müssen integriert werden Probleme böse Inhalte Browserland ist Feindesland Texte mit Sonderzeichen/Tags Vorgefertigte Funktionen verwenden Beispiel Quotieren von Strings mit cgi.escape, Sonderzeichen und Tag-Zeichen (<, >) umwandeln Einfügen von Skript-Code verhindert Weiteres: Entfernen von Tags,... 1 #!/usr/bin/python 2 # -*- coding: utf-8 -*- 3 print("content-type: text/html\n") 4 import os, cgi 5 lines = ["Hallo", "Hällo", "<tag>", "<b> bold </b>", 6 a " double quote ] 7 for line in lines: 8 print("%s <br />" % line) 9 print 10 for line in lines: 11 print("%s <br />" % cgi.escape(line, True)) Hallo <br /> Hällo <br /> <tag> <br /> <b> bold </b> <br /> a " double quote <br /> Hallo <br /> Hällo <br /> <tag> <br /> <b> bold </b> <br /> a " double quote <br /> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Komponenten zur Ansicht Rendern von HTML beschränken Manuelles Generieren von HTML unabhängig von Präsentationslogik Reines Rendern (Generieren) von HTML unabhängig, wiederverwendbar realisieren Beispiel Tabelle 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 import cgi, cgitb, string 4 cgitb.enable() 5 6 from tabelle import table 7 8 V,N,M = vorname, nachname, matnr 9 keys = [(V, Vorname ), (N, Nachname ), (M, MatNr )] 10 data = [{V: Susi, N: Sinnlos, M: }, 11 {V: Rudi, N: Ratlos, M: }, 12 {V: WWW, N: WickedWestWitch, M: }] 13 ctable = table(keys, data) 14 c = "<html><body><h3>tabelle</h3>%s</body></html>" % ctable 15 print(c) 1 # Markup nur konstant, auslagerbar/aenderbar 2 _table = "<table>\n%(header)s\n%(data)s\n</table>\n" 3 _row = "<tr>%s</tr>" 4 _header = "<th>%s</th>" 5 _entry = "<td>%s</td>" 6 7 def _rowformat(line, keys, wrap): 8 entries = [wrap % line[t[0]] for t in keys] 9 return _row % " ".join(entries) def table(keys, data): 12 dic = dict() 13 hdict = {} 14 for tup in keys: 15 hdict[tup[0]] = tup[1] 16 dic["header"] = _rowformat(hdict, keys, _header) 17 rows = [_rowformat(line, keys, _entry) 18 for line in data] 19 dic["data"] = "\n".join(rows) 20 return _table % dic Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

9 Proprietäre Integration Proprietäre Integration Vor- und Nachteile von CGI Vorteile Einfach, standardisiert Funktioniert immer, mit jeder Programmiersprache Ausführung unter der eigenen Benutzerkennung Nachteile Je Anfrage ein Prozess, Last Lösungsansatz: FastCGI, mehrere Anfragen je Prozess, vermeidet Start der Ablaufumgebung Lösungsansatz: Integration in Web-Server, meist proprietär, Interpreter/Runtime läuft im Web-Server, mehr Features möglich Keine Trennung Anwendungslogik und Präsentationslogik erzwungen Verleitet zu Spaghetti-Code (muss aber nicht sein) Einsatzgebiet Einfache Anwendungen mit wenigen dynamischen Seiten Darstellung und Eingabe von strukturierten Daten Einfache Wiederverwendung von vorhandenem Anwendungs-Code Beispiele Bugzilla, Bugtracking Tool, Perl MoinMoin, Wiki, Python... Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Integration von Python in Web-Server WSGI Ziele Integration so einfach wie CGI Kein neuer Interpreter je Aufruf, ein Prozess für mehrere Anfragen Unabhängig vom Web-Framework Web Server Gateway Interface (WSGI) Python-Schnittstelle zur Integration in Web-Server, Teil der Standardbibliothek Gut dokumentiert, PEP-0333 (2003) Akzeptiert: Von (fast) allen Frameworks und HTTP-Servern unterstützt mod_wsgi für Apache-Integration code.google.com/p/modwsgi/ Proprietäre effiziente Integration HTTP-Server WSGI Python-Prozess Python-Prozess Apache-HTTP-Server mod_wsgi (WSGI-Gateway) WSGI-Protokoll Python-Prozess Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Proprietäre Integration Proprietäre Integration Ablauf WSGI im Web-Server WSGI jetzt.wsgi Anfrage von Client im Web-Server HTTP-Server mit WSGI liefert 1 import datetime Skript jetzt.wsgi wird verwendet Warum konfigurierbar (kommt noch), zum Beispiel anhand von Dateiname Übergabe an Python Prozess/Interpreter Nur bei erstem Aufruf Python soll Modul jetzt importieren Python übersetzt Modul in Byte-Code und lädt Modul Bei jedem Aufruf Konfigurierte Funktion wird gerufen (zum Beispiel application) Iterieren über Funktionsergebnis ist Ergebnisseite Gut für Betrieb, aber bei Entwicklung zunächst kein Neuladen bei Änderung Python Bytecode Apache-HTTP-Server mod_wsgi (WSGI-Gateway) Python-Prozess Importieren,1x Übersetzen, 1x Funktionsaufruf, jedes Mal Python Quellcode environ Umgebungsvariablen start_response Antwort-Funktion HTTP-Server mit WSGI erwartet Eine Funktion Params (environ, start_response) Aufruf von start_response mit status: HTTP Status, meist 200 OK header: Liste von Schlüssel/Wert- Tupeln, zum Beispiel mit ("Content-Type", "text/html") Rückgabe ein iterierbares Objekt aus dem Dokument erzeugt wird Beispiel jetzt.wsgi, aktuelles Datum/Uhrzeit 2 page = "<html><body>%s</body></html>" 3 def app(environ, start_response): 4 today = str(datetime.datetime.today()) 5 header = [("Content-Type","text/html")] 6 start_response("200 OK", header) 7 return [page % today] 8 9 application = app # mod_wsgi WSGI und Apache mod_wsgi Erwartet den Namen application Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

10 Proprietäre Integration Proprietäre Integration URL auf WSGI-Skript abbilden Abbildung bei CGI/WSGI Konfiguration Web-Server Meist automatische Assoziation von Skriptname im Pfad auf Skript Eingeschränkt auf spezifisches Unterverzeichnis cgi-bin bzw. wsgi unterhalb von public_html mit Endung.cgi bzw..wsgi Achtung: Pfadangabe nach Skriptname möglich (und sinnvoll) Im Produktivbetrieb nicht sichtbar Web-Server Konfiguration (z.b. Apache mod_rewrite), alle Anfragen auf ein Skript, sinnvoll Hochschule: Angabe von Skript ssinn001/wsgi/jetzt.wsgi Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Je nach URL andere Seiten erzeugen URL-Mapping Üblich bei statischen Inhalten: Assoziation zwischen Dateipfad und Zugriffspfad in URL Assoziation abhängig von der Konfiguration des HTTP-Servers Bei Anwendungen meist alles, bis auf statische Dateien, auf ein Skript (Rest-)URL kann verwendet werden, um andere Seiten zu generieren Konfiguration an Hochschule Skriptname unterhalb von public_html/wsgi mit Endung.wsgi Alles darunter auch! URL darf weiter gehen Mapping: Je nach URL andere Funktion url.wsgi 1 def app(environ, start_response): 2 rurl = environ["path_info"] 3 page = "Rest-URL: %s" % rurl 4 header = [("Content-Type","text/html")] 5 start_response("200 OK", header) 6 return [page] 7 8 application = app # mod_wsgi Bei cgi gleiches Verhalten Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Proprietäre Integration Proprietäre Integration GET Anfragen mit WSGI POST-Anfragen mit WSGI get.wsgi postparam.wsgi GET Anfragen mit WSGI Zugriff auf Query-String wie bei cgi, parse_qs auch bei cgi parse_qs liefert Dict. aus Inhalten des Query-Strings, Achtung: Liste als Wert, da mehrere Einträge erlaubt sind 1 from urlparse import parse_qs 2 def application(environ, start_response): 3 query = parse_qs(environ[ QUERY_STRING ]) 4 content = "Bye" 5 if "hi" in query: 6 content = hi(query) 7 header = [("Content-Type","text/html")] 8 start_response("200 OK", header) 9 return [content] 10 def hi(query): 11 name = "niemand" 12 if "name" in query: 13 name = "".join(query["name"]) 14 return "Hallo, %s\n" % name Rückrichtung mit urllib.urlencode Folge von Schlüssel/Wert-Paaren als ein Query-String kodieren Tupel können Sonderzeichen enthalten, die encodiert werden Abhängig von Query-String Inhalten unterschiedliche Seiten generieren Leerzeichen als +, & als %26 %XY generische Kodierung Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 POST Anfragen mit WSGI Änderung Formular für POST <form action="postparam.wsgi" method="post"> Zugriff auf Query-String durch Lesen des Eingabestroms Nur so viel lesen wie zu dieser Anfrage gehört Verarbeiten wie bei GET mit parse_qs 1 from urlparse import parse_qs 2 3 def app(environ, start_response): 4 name, ende = ["niemand"], ["None"] 5 post = "" 6 if environ[ REQUEST_METHOD ] == POST : 7 contentlen = int(environ[ CONTENT_LENGTH ]) 8 post = environ[ wsgi.input ].read(contentlen) 9 dic = parse_qs(post) 10 if "name" in dic: 11 name = dic["name"] 12 if "ende" in dic: 13 ende = dic["ende"] 14 tup = (name[0], ende[0]) 15 content = "Hallo %s, <br />%s" % tup 16 header = [("Content-Type","text/html")] 17 start_response("200 OK", header) 18 return [content] application = app # mod_wsgi Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

11 Proprietäre Integration Proprietäre Integration Lokale WSGI-Umgebung zur Entwicklung Entwicklung Integration in HTTP-Server (Container) kompliziert und für Entwicklung nicht notwendig Einfacher HTTP-Server Teil der Python Standardbibliothek Nutzung mit Paket wsgiref Paket wsgiref Referenzimpl. von wsgi simpleserver für Entwicklung make_server erstellt HTTP-Server mit WSGI-Anwendung Servername: localhost Port (beliebig): 8080 app: WSGI-Anwendung envwsgiref.wsgi 1 #!/usr/bin/python 2 3 def app(env, start_response): 4 header = [("Content-Type","text/html")] 5 content = ["%s: %s <br />" % (k,env[k]) for k in env] 6 start_response("200 OK", header) 7 return content application=app 11 if name == main : 12 from wsgiref.simple_server import make_server 13 httpd = make_server( localhost, 8080, app) 14 httpd.serve_forever() mod_wsgi Kompatibilität app in application umbenennen if: Anwendung mit mod_wsgi im Apache und wsgiref lokal ausführbar Benutzung wsgiref Starten als lokales Python Programm python envwsgiref.wsgi Endung.wsgi nur für mod_python, sonst auch.py möglich Log-Ausgabe je Anfrage auf Konsole Benutzung mit IDEs Idle, Emacs oder Eclipse (PyDev) Debugging unterstützt, einfach Breakpoint in Anwendung setzen und mit Browser auf Anwendung zugreifen PyDev Endung muss.py sein Separate.wsgi-Datei, importiert nur application-objekt Beispiel env2.py und env2.wsgi Testen mit env2.py env2.wsgi 1 #!/usr/bin/python 2 import sys, os 3 sys.path.append(os.path.dirname( file )) 4 os.chdir(os.path.dirname( file )) 5 from env2 import application Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Proprietäre Integration werkzeug pydev Python mit Eclipse Abstraktion von der dokumentenbasierten Web-Schnittstelle PyDev Web-Anwendung Abstraktion bei Web-Frameworks pydev.org Eclipse-Plugin, über Eclipse-Marketplace verfügbar und von jedem selbst zu installieren Vor Start einmal Python-Interpreter setzen Python-Entwicklung Completion Debugging Subversion... Im Praktikum Idle oder Eclipse mit PyDev verwenden (oder natürlich Emacs). Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Anfrage erzeugt Antwort, Textdokumente Kommunikation in Anwendung hinein Schlüssel/Wert-Paare der Eingabestrom Kommunikat. von Anwendung heraus Schlüssel/Wert-Paare (HTML-)Dokument Viele Konventionen: REQUEST_METHOD: GET bei GET-Anfrage Content-Type: text/html bei HTML-Dokument als Antwort... Nicht komfortabel Request-Objekt, Response-Objekt; kapselt Anfrage, Antwort Zugriff über Request-Objekt auf Eigenschaften der Anfrage, z.b. (Query)-Parameter,... Verändern des Response-Objekt, um dann Text-Antwort zu erzeugen, z.b. Typ setzen Web-Abstraktion/Frameworks in Python werkzeug, einfache WSGI-Abstraktion, verwenden wir Alternative webob, nur Req.-/Resp. django, Full-Stack Framework (sehr schön, aber zu Lehrzwecken zu groß und zu stark abstrahiert) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen Juli / 295

12 werkzeug werkzeug Abstraktion mit werkzeug werkzeug Weit verbreitete WSGI-Abstraktion, noch kein Web-Framework Python-Bibliothek Features Request/Response Objekte URL-Routing, welche Funktion für welche URL Cookies, Sessions,... Entwicklungsunterstützung: automatisches Neuladen, Tracebacks Einfaches Beispiel: werkzeug.pocoo.org/docs/quickstart (Tutorial passt nicht) werkzeug.pocoo.org 1 from werkzeug.wrappers import Request, Response 2 3 def app(environ, start_response): 4 request = Request(environ) 5 name = request.args.get("name", "Welt") 6 response = Response("Hallo %s" % name) 7 response.content_type="text/html" 8 return response(environ, start_response) 9 10 if name == main : 11 from wsgiref.simple_server import make_server 12 httpd = make_server( localhost, 8080, app) 13 httpd.serve_forever() werkzeug Entwicklung Request/Response häufig eine Abkürzung Nur noch ein Parameter, request Neue Instanz von Response zurück werkzeug.serving, run_simple Reloader: Bei Änderung der Quelldatei wird automatisch die Quell-Datei neu geladen; kein Neustart mehr notwendig Debugger Aussagekräftige Fehlermeldung Cool: Interaktive Konsole im Browser Nachteil: Debugger (Eclipse) funktioniert nicht mehr Beides verwenden je nach Bedarf Eclipse: use_reloader=false 1 from werkzeug.wrappers import Request, Response 3 def app(request): 4 name = request.args.get("name", "Welt") 5 fehler 6 return Response("Hallo %s" % name) 7 if name == main : 8 from werkzeug.serving import run_simple 9 run_simple( localhost, 8080, app, 10 use_reloader=true, use_debugger=true) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 werkzeug werkzeug Standard WSGI-Rahmen Für Deployment in Apache; für Entwicklung mit Debugging in Eclipse oder Entwicklung mit Traceback und Debug-Konsole im Browser werkzeugstd.wsgi In passenden von Apache konfig. Verzeichnis, public_html/wsgi Pfad zum Suchen der Quellen und Wechslen in das Verzeichnis Laden eines Moduls und Funktion application zur Verfügung stellen werkzeugstd.py Ein Python Modul im Suchpfad. Z. B. unter ~ssinn001/dev/stdapp; außerhalb von Apache konf. Verzeichnis. Lokale Entwicklung; start; eingebauter Web-Server werkzeugstd.wsgi 1 #!/usr/bin/python 2 import sys, os 3 PATH="/home/mi/ssinn001/dev/stdapp" 4 sys.path.append(os.path.dirname(path)) 5 os.chdir(os.path.dirname(path)) 6 from werkzeugstd import application werkzeugstd.py 1 #!/usr/bin/python 2 from werkzeug.wrappers import Request, Response 3 5 def application(rquest): 6 "the main application" 7 8 if name == main : 9 from werkzeug.serving import run_simple 10 run_simple( localhost, 8080, application, 11 use_reloader=true, use_debugger=true) Request-Objekt Request-Objekt request = Request(environ) (oder Parameter) Erzeugt aus Umgebungsvariablen Nur lesbar Attribute, Methoden: Dokumentation: werkzeug.pocoo.org/docs/wrappers method: GET, POST,... args: Dictionary aus Query-String (GET) form: Dictionary aus Formulareingaben (POST) values: kombiniert args und form url(base_url): URL (ohne Query-String) path: Angefragter Pfad environ: Die Original-Umgebungsvar. Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

13 werkzeug Routing Response-Objekt Routing Welche Seite soll angezeigt werden? Response-Objekt response = Response();... ; return response(environ, start_response) (oder return response) Optional Inhalts-String Veränderbar, auch Liste als Inhalt Attribute, Methoden: Dokumentation: werkzeug.pocoo.org/docs/wrappers Iterable als Content (im Beispiel Liste) status, status_code: HTTP-Status headers: HTTP-Header automatically_set_content_length: Größe (HTTP/1.1 offene Verbindung!) charset: utf-8 1 from werkzeug.wrappers import Request, Response 2 4 def app(request): 5 c = [] 6 response = Response(c) 7 c.append("content modifiable\n") 8 response.status = "200 OK" 9 response.status_code = c.append("response.headers:\n") 11 hs = response.headers 12 for k in hs.keys(): 13 s=" %s: %s\n" % (k, hs[k]) 14 c.append(s) 15 response.automatically_set_content_length = True 16 return response Mehr mit Mixins; Dokumentation Web-Anwendung Mehrere Seiten (Formulare) Nicht nur angepasst, sondern andere Aufgabe (Produkt vs. Warenkorb) Je nach Anfrage (Routing) und Zustand der Anwendung wird eine andere Seite ausgewählt Routing Statische Seiten/Inhalte: Abbildung von Pfad in URL und Dateiname in Ordnerhierarchie (z.b. index.html, /static/style.css) Dynamisch: Abbildung von Pfad in URL auf inhaltsgenerierende Funktionalität (Skript) Beispiel: Apache Web-Server Hochschule von / <user>/... auf user/public_html/... (unter anderem statische Inhalte wie Bilder, HTML-Seiten, Style-Sheets, JavaScript-Dateien,... ) von / <user>/cgi-bin/<app>.cgi/* auf CGI-Skript user/public_html/cgi-bin/<app>.cgi von / <user>/wsgi/<app>.wsgi/* auf Python-Skript user/public_html/wsgi/<app>.wsgi von allem mit Endung *.php auf eingebetteten PHP-Interpreter Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Routing Routing Routing Beispiel Statische Inhalte mit WSGI Optionen Code-Organisation Statische Inhalte Statische Inhalte (Assets wie Bilder, Style-Sheets) müssen in Web-Anwendung zur Verfügung gestellt werden In Produktiv-Umgebungen häufig separater Server und separate URL, bzw. Apache speziell konfiguriert Während Entwicklung mühselig Ziel: statische Inhalte während Entwicklung Beispiel: Einfaches statisches Routing Wenn URL mit /statisch/ beginnt, dann einfach nur Inhalt wiedergeben Ansonsten mit application weitermachen 1 from werkzeug.wrappers import Request, Response 2 import datetime, os 3 page = """<html><body><p>es ist %(uhr)s Uhr</p> 4 <img src="statisch/uhr.png" /></body></html>""" 5 7 def application(request): 8 if request.path.startswith("/statisch"): 9 return statisch(request) 10 n = datetime.datetime.now() 11 uhr="%02d:%02d:%02d"%(n.hour,n.minute,n.second) 12 c = page % { uhr : uhr} 13 return Response(c, content_type="text/html") 14 def statisch(request): 15 base = os.path.dirname( file ) 16 # fuehrendes / bei path wegmachen 17 asset_fname = os.path.join(base, request.path[1:]) 18 asset = file(asset_fname).read() 19 return Response(asset) Eine Python-Funktion je Seite Klassisches Dispatching Mappen Anfrage auf Funktion Meist auf Basis der URL, geht auch auf Grund des Zustands Eine Python-Funktion für alles Ein Python-Funktion generiert alles Je nach Bedarf spezifisch Content (durch Funktionsaufrufe) generieren Kombiniert application-objekt von WSGI als ein Skript für alles, einfache API Darin Dispatcher, um unterschiedliche Seiten zu generieren routing.py 1 from werkzeug.wrappers import Request, Response 2 product_page = """%(name)s sind toll""" 3 def product(request, name): 4 return product_page % { name : name} 5 service_page = """Wir kuemmern uns um %(name)s""" 6 def service(request, name): 7 return service_page % { name : name} 9 def application(request): 10 name = "ACME Luftgitarren" 11 if request.path.startswith("/product"): 12 c = product(request, name) 13 elif request.path.startswith("/service"): 14 c = service(request, name) 15 else: 16 c = "nicht verfuegbar" 17 return Response(c) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

14 Routing Routing Einfache Routing-Abstraktion Abbildung URL-Anfang auf Funktion Falls URL mit Schlüssel beginnt, dann auf passende Funktion weiterleiten Vorbelegen von Funktionsparametern möglich, nur ein Parameter (request) erwartet Mächtigere Alternativen in Frameworks URL-Matcher wann passt eine URL auf ein Pattern Übernahme von Parametern aus URL und Typkonvertierung automatisch Ausgefeilte Regelwerke und Konfigurationsmöglichkeiten Beispiel: werkzeug werkzeug.pocoo.org/docs/routing (brauchen wir nicht) 1 from werkzeug.wrappers import Request, Response 2 from routing import product, service 3 4 name = "ACME Luftgitarren" 5 url_map = { 6 /product/ : lambda req: product(req, name), 7 /service/ : lambda req: service(req, name), 8 # None default 9 None: lambda req: product(req, name) 10 } def application(request): 15 for key in url_map: 16 if key and request.path.startswith(key): 17 return Response(url_map[key](request)) 18 return Response(url_map[None](request)) Hinweis: Abbildung sollte eindeutig sein, sonst ist Reihenfolge nicht definiert Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Struktur Programmlogik Hinweise Trennen HTML und Code, durch Einsatz von Templating erledigt Einsatz von Funktionen und Objekten für die Programmlogik Ausgabe (Generieren HTML) meiden Ausnahme für dynamische Strukturen (Listen, Tabellen) da mächtigere Templatesprache/Controls fehlen Strikte Reihenfolge einhalten Reihenfolge Programmzustand wiederherstellen (Auswertung Eingabe, Z13) Berechnung neuer Zustand (Funktionalität Z15 Z18) Ausgabe (Templating und Ausgaberoutinen Z20 Z21) 1 from werkzeug.wrappers import Request, Response 2 3 page = """<html><head><title>zaehler</title><head> 4 <body><form method="post"> %(zahl)d <br/> 5 <input type="submit" name="up" value="hoch" /> 6 <input type="submit" name="down" value="runter" /> 7 <input type="hidden" name="zahl" value="%(zahl)d" /> 8 </form></body>""" 9 11 def application(request): zahl = int(request.form.get("zahl", "0")) if request.form.get("up", None): 16 zahl += 1 17 elif request.form.get("down", None): 18 zahl -= c = page % { zahl : zahl} 21 return Response(c, content_type="text/html") Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Lebensdauer Daten über Anfragen hinaus Bisher Daten nur aus der Anfrage Kein Zustand in der Anwendung Daten nur in der Anfrage vorhanden Eigentlich kein Anwendungskontext Erste Ausnahme: Zähler zahl Anwendungskontext Menge von Variable/Wert-Paaren Gültigkeitsbereiche Anwendung: Für alle gleich, für die Lebensdauer der Anwendung, Beispiel: Klick-Zähler Session: Für jeden Anwender unterschiedlich, für eine Folge von Interaktionen eines Anwenders (Session) gleich, Beispiel: Warenkorb Lebensdauer Daten Block Programmiersprachenebene, {} Lokale Variablen Nicht spezifisch für Web Während einer Anfrage Für Dauer Bearbeitung einer Anfrage In Prog.sprache Attribute des request- Objekts, nicht globale Variablen Session Interaktionsfolge eines Anwenders In Prog.sprache nicht abgebildet Meist Speicher oder Dateisystem Anwendung Über Session hinaus In Prog.sprache nicht abgebildet Meist persistent (Dateisystem, DBMS) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Sessions Session im Mehrbenutzerbetrieb mehrere Interaktionen je Benutzer im gleichen Anwendungskontext (bestehend aus Daten) Welche Daten, Beispiele Benutzerdaten, Einstellungen, Optionen, Einkaufskorb... Problem HTTP-Protokoll ist zustandslos, Request/Response Keine Daten der letzten Anfragebearbeitung in aktueller Anfrage Lösung Explizite Session-Verwaltung Anwendungskontext Kontext-Daten manuell verwalten Ablage: Client (Browser) oder Server Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

15 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Anwendungskontext im Client Kontext im Client Formulare Anwendungskontext im Web-Browser Manuelle Weitergabe des Kontextes von Seite zu Seite Techniken: Formulare (GET/POST), Cookies Vorteile Keine Belastung des Servers (Datenhaltung) Keine eindeutige Zuordnung zu Server-Session notwendig Nachteile Datenübertragung je Anfrage Anfällig gegenüber Manipulationen Abhängig von Web-Client Garantie Persistenz schwierig Formulare als Träger des Anwendungskontextes Verstecke Formularfelder <input type="hidden"/> Alle Schlüssel/Wert-Paare Weitergabe Anfrage POST: Datenstrom in Anfrage GET: Query-String in Anfrage (sichtbar) Auswertung/Wiederherstellung Automatisch: request.form/args 1 from werkzeug.wrappers import Request, Response 2 import cgi 3 _hidden = <input type="hidden" 4 _hidden += name="%(key)s" value="%(value)s" /> 5 6 def render_context(context): 7 entries = [] 8 for k,v in context.iteritems(): 9 v = cgi.escape(unicode(v), True) 10 entry = _hidden % { key : k, value : v} 11 entries.append(entry) 12 return "\n".join(entries) def application(request): 16 ctx, args = {}, request.args 17 ctx[ a ] = args[ a ] if a in args else A 18 ctx[ b ] = args[ b ] if b in args else B 19 ctx[ z ] = int(args[ z ]) if z in args else 0 20 ctx[ z ] += f = <form>%s<input 22 f+= type="submit" name="ok" value="ok"/></form> 23 c = f % render_context(ctx) 24 for k, v in ctx.iteritems(): 25 c += "%s: %s<br />\n" % (k, v) 26 return Response(c, content_type="text/html") Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Kontext im Client Generiertes Formular Cookies Generiertes Formular Verstecke Eingabefelder für Schlüssel/Wert-Paare name als Schlüssel value als Wert Werden automatisch durch Formular submit übertragen Formular selbst hat keine sichtbaren Elemente außer dem Knopf 1 <form> 2 <input type="hidden" name="a" value="a" /> 3 <input type="hidden" name="b" value="b" /> 4 <input type="hidden" name="z" value="17" /> 5 <input type="submit" name="ok" value="ok"/> 6 </form> 7 a: A<br /> 8 b: B<br /> 9 z: 17<br /> Ziel Lokale Datenablage Daten im Browser speichern Über Neustart des Browsers Verwaltet durch Browser Server setzt, Browser sendet automatisch zurück Missbrauch, Ad-Tracking Cookies Namen: beliebig, max. 300 Cookies Wert: max. 4KB/Cookie (inkl. Namen) Verfallsdatum (Expires): Nach Verfallsdatum ungültig, wird gelöscht Domain (Pfad): Nur an diese Domain, max. 20 Cookies je Server/Domain secure: nur wenn gesichert übertragen Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

16 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Cookies Übertragung Übertragung HTTP, RFC 2109/6265 Teil des HTTP-Headers Set-Cookie: <Name>=<Wert>, Cookie: <Name>=<Wert> PATH=<path> SECURE (optional) URL-encodiert (cgi.escape), %FF Ablauf Beispiel Server schickt Set-Cookie-Header als Teil der Antwort auf eine Anfrage Ab da schickt der Browser immer wieder das Cookie in der Anfrage mit Cookie-Header Mehrere Cookies in dem einen Header-Feld Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Cookies setzen und lesen Manuell CGI Header Set-Cookie Auslesen aus Umgebungsvariable HTTP_COOKIE Inhalt sind Schlüssel=Wert Paare Mit Standardbibliothek Cookies auf dem Server mit Cookie Cookie.SimpleCookie als einfache Abstraktion Schreiben und Lesen Mehrere Schlüsselwert-Paare im Beispiel Set-Cookie: jetzt=" :52: "; Path=/ Löschen: Leerer Inhalt und überschrittenes Verfallsdatum setcookie.cgi 1 #!/usr/bin/python 2 from datetime import datetime 3 print "Set-Cookie: jetzt="+ str(datetime.now()) 4 print "Content-Type: text/html\n" 5 import cgi, cgitb 6 cgitb.enable() 7 import os 8 print "Cookie is: "+str(os.environ["http_cookie"]) 1 #!/usr/bin/python 2 from datetime import datetime 3 import os, cgi, Cookie 4 cookie = Cookie.SimpleCookie() 5 cookie["jetzt"] = str(datetime.now()) 6 cookie["jetzt"]["path"] = "/" 7 print cookie.output() 8 print "Content-Type: text/html\n" 9 rc = Cookie.SimpleCookie(os.environ["HTTP_COOKIE"]) 10 print "Cookie is: "+rc["jetzt"].value 11 print cookie.output() Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Kontext im Client Cookies Kontext im Client Sichere Cookies Cookie als Träger des Anwendungskontextes Schlüssel/Wert-Paare in Cookies Alternativ zusammenpacken als Query-String in einem Cookie möglich Weitergabe zum Browser set_cookie Automatisch, über Header Auswertung/Wiederherstellung Mit request.cookies 1 from werkzeug.wrappers import Request, Response 2 import cgi, Cookie 3 4 def render_context(content, context): 5 response = Response(content, 6 content_type="text/html") 7 for k,v in context.iteritems(): 8 v = cgi.escape(unicode(v), True) 9 response.set_cookie(k, v) 10 return response def application(request): 14 ctx, args = {}, request.cookies 15 ctx[ a ] = args[ a ] if a in args else A 16 ctx[ b ] = args[ b ] if b in args else B 17 ctx[ z ] = int(args[ z ]) if z in args else 0 18 ctx[ z ] += c = [] 20 response = render_context(c, ctx) 21 c.append( <form><input type="submit" ) 22 c.append( name="ok" value="ok"/> ) 23 c.append( </form> ) 24 for k,v in request.cookies.iteritems(): 25 c.append("%s: %s<br />\n" % (k, v)) 26 return response Verschlüsseln der Daten auf dem Client Schwierig zu lesen, zu manipulieren Einfache Sicherung von Manipulation: Fingerabdruck Verhindern von Manipulationen Wenn Daten verändert wurden, dann stimmt der Fingerabdruck der Daten nicht mehr Standardalgorithmus SHA1 Eingabe ist beliebiger String (Zahl) Ergebnis ist ein 160-Bit Message-Digest (meist als Hex-String dargestellt) Alternativen: MD5, SHA256, SHA512 Python und SHA1 (und andere) hashlib.sha1(message).hexdigest() RFC 3174 The SHA-1 is called secure because it is computationally infeasible to find a message which corresponds to a given message digest, or to find two different messages which produce the same message digest. Any change to a message in transit will, with very high probability, result in a different message digest, and the signature will fail to verify. Geheimes Salz Nachricht muss (teilweise) geheim sein, sonst kann Digest berechnet werden Lösung: Hinzufügen eines geheimen Salzes (Salt), ein beliebiger String a99219f952208c68c30cb4a99cf9d7902e Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

17 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Kontext im Client Sichere Cookies, Beispiel Kontext im Client Sichere Cookies, werkzeug ctxlib.py 1 import urllib, hashlib, urlparse 2 3 SALT="secret" 4 CONTEXT, FP = "context", "fingerprint" 5 def render_context(response, context): 6 ctx = urllib.urlencode(context) 7 response.set_cookie(context, ctx) 8 fp = hashlib.sha1(ctx+salt).hexdigest() 9 response.set_cookie(fp, fp) def restore_context(request): 12 if CONTEXT not in request.cookies: 13 return {} 14 if FP not in request.cookies: 15 raise Exception("Security Error") 16 ctx = request.cookies[context] 17 fp = hashlib.sha1(ctx+salt).hexdigest() 18 if fp!= request.cookies[fp]: 19 raise Exception("Security Error") 20 ret = urlparse.parse_qs(ctx) 21 for k in ret: # nur ein Wert 22 ret[k] = "".join(ret[k]) 23 return ret 1 from werkzeug.wrappers import Request, Response 2 import cgi, Cookie, ctxlib 3 4 form = """<form><input type="submit" name="ok" 5 value="ok"/></form>""" 6 8 def application(request): 9 ctx = ctxlib.restore_context(request) 10 if a not in ctx: # uninitialisiert 11 ctx[ a ], ctx[ b ] = A, B 12 ctx[ z ] = 0 13 c = [form] 14 for k,v in ctx.iteritems(): 15 c.append("%s: %s<br />\n" % (k, "".join(v))) 16 ctx[ z ] = int(ctx[ z ]) # Typkonversion 17 ctx[ z ] += 17 # Zustandsfortschritt 18 response = Response(c,content_type="text/html") 19 ctxlib.render_context(response, ctx) 20 return response SecureCookie in werkzeug Teil der Erweiterungen Verfolgt vorgestelltes Prinzip Leeres Dictionary bei Manipulation ctxlibwerkzeug.py 1 import werkzeug.contrib.securecookie as sc 2 3 SALT="secret" 4 CONTEXT="context" 5 def render_context(response, ctx): 6 scs = sc.securecookie(ctx, SALT).serialize() 7 response.set_cookie(context, scs) 8 9 def restore_context(request): 10 if CONTEXT not in request.cookies: 11 return {} 12 scs = request.cookies[context] 13 ctx = sc.securecookie.unserialize(scs, SALT) 14 if not ctx: 15 raise Exception("Security Error") 16 return ctx 1 from werkzeug.wrappers import Request, Response 2 import cgi, Cookie, ctxlibwerkzeug as ctxlib 3 4 form = """<form><input type="submit" name="ok" 5 value="ok"/></form>""" 6 8 def application(request): 9 ctx = ctxlib.restore_context(request) 10 if a not in ctx: # uninitialisiert 11 ctx[ a ], ctx[ b ] = A, B 12 ctx[ z ] = 0 13 c = [form] 14 for k,v in ctx.iteritems(): # Typ bleibt int 15 c.append("%s:%s<br />\n"%(k,"".join(str(v)))) 16 # keine Typkonversion mehr notwendig 17 ctx[ z ] += 17 # Zustandsfortschritt 18 response = Response(c,content_type="text/html") 19 ctxlib.render_context(response, ctx) 20 return response Serialisierung nicht als Querystring, default pickle Typinformation bleibt erhalten Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Anwendungskontext im Server Verwalten des Anwendungskontextes in der Web-Anwendung im Server Ein Datensaz je Session Session-Identifikation über Browser notwendig Vorteile HTTP ist zustandslos Unabhängig(er) von Client Schwieriger zu manipulieren Persistenz Nachteile Hohe Belastung des Servers Session-Zuordnung trotzdem notwendig im Browser Session-Id Session-ID Anwendungskontext Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Session-Identifikation im Web-Browser Session-Identifikation (Session-ID) Ein eineindeutiger Bezeichner je Session Nicht vorhersagbar IP-Adresse, Benutzerkennung und Zeit weder ausreichend noch hinreichend Internet-Café, anonymer Mehrbenutzerbetrieb Dynamisches Ändern der IP-Adresse Meist Hash einer Zufallszahl plus IP-Adresse (99,9...%-Lösung) Verwalten der Session-ID Bevorzugt im Cookie Oft optional im GET-String Falls Cookie verboten Navigation mit location: geht schief (und ist verboten!) Session-ID in Python erzeugen import uuid, OpenSSL r = OpenSSL.rand.bytes(16) sessionid = uuid.uuid(bytes=r) #38e9aa97-fe49-2ea2-4d92-4aa a0 Gute Zufallszahl Ausreichend eindeutig Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

18 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Session-Verwaltung auf Server Session-Verwaltung auf Server mit Python Zusammenspiel Session-ID und Kontext Anwendungskontext Verwendung Inhalte des Anwendungskontextes werden auf Server gehalten Assoziation von Session-ID mit Anwendungskontext Session-Objekte, Middleware Middleware entscheidet über Ort und Art der Speicherung Session-ID Datenhaltung auf Server, Alternativen Hauptspeicher/Prozesskontext: Bei CGI/WSGI nicht (einfach) möglich, Zuordnung Anfrage auf Prozess bei CGI immer neu oder durch Web-Server gesteuert Datei: Aufwändig, viele kleine Dateien schreiben, Session-ID ist Dateiname Datenbank: Sicher, aufwändig, unabhängig von Web-Server Web-Server/Skriptumgebung Server/Host Bevorzugt mit sicheren Cookies Ablage zwischen den Seitenaufrufen Prozesskontext des Skripts hat keine Bedeutung! Je Anfrage andere Python Instanz möglich oder (CGI) immer neu Serialisierung meist mit pickle, beliebige Python-Objekte möglich Ablageort meist Dateisystem und Datenbank; Client (Cookie) oder Hauptspeicher (Shared Memory, memcached) möglich Shared Memory Hauptspeicher/ Prozesskontext Dateisystem Datenbank Dateisystem Datenbank Web-Server/Skriptumgebung Server/Host Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Session-Verwaltung auf Server Session-ID Session-ID Wenn schon vorhanden, dann einfach als String zurückgeben Wenn nicht, dann vorher erzeugen Session-ID in einem Cookie Header setzen beim Erzeugen Antwort muss also schon zur Verfügung stehen Holen und gegebenenfalls erzeugen Verwendung Vor jeder Anfrage: Inhalte auslesen Nach jeder Anfrage: Inhalte speichern Ablageort beliebig: Schlüssel (zum Beispiel Dateiname) ist die Session-ID session_id 1 import os, uuid, OpenSSL 2 import werkzeug.contrib.securecookie as sc 3 4 SESCOOKIE, SALT = "session_cookie", "secure" 5 6 def get_sid(request, response): 7 "session_id aktueller session, ggf. neu" 8 if SESCOOKIE not in request.cookies: # new 9 r = OpenSSL.rand.bytes(16) 10 sid = str(uuid.uuid(bytes=r)) 11 cd = {SESCOOKIE: sid} 12 c = sc.securecookie(cd, SALT).serialize() 13 response.set_cookie(sescookie, c) 14 else: 15 c = request.cookies[sescookie] 16 cd = sc.securecookie.unserialize(c, SALT) 17 sid = cd[sescookie] 18 return sid Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Session-Verwaltung auf Server Dateisystem Sessions selbst gemacht (Verständnis) Session-Objekt einfaches Dictionary mit Eintrag _SID auf Session-ID Ablage in Dateisystem Keine Überprüfung ob Kollision (schon vorhandene Session) Kein Aufräumen alter Sessions Verwendung, als Middleware response erzeugen, Session-Objekt mit load_session erhalten Die Anwendung manipuliert das Session-Objekt (nicht _ * ) save_session am Ende zum Speichern aktualisierter Session Inhalte kill_session Session technisch beenden (vermeiden) session_fs 1 import os, cpickle 2 3 STORAGE, SID = "/tmp", "_SID" 4 def load_session(session_id): 5 fpath = os.path.join(storage, session_id) 6 try: 7 return cpickle.load(file(fpath, "r")) 8 except (IOError, EOFError) as e: 9 return {SID: session_id} def save_session(session): 12 fpath = os.path.join(storage, session[sid]) 13 cpickle.dump(session, file(fpath, "w")) def kill_session(session): 16 fpath = os.path.join(storage, session[sid]) 17 try: 18 os.unlink(fpath) 19 except OSError: 20 pass Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

19 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Session-Verwaltung auf Server Beispiel Achtung beim Schreiben Nebenläufigkeit! Anforderung Anwendung Hochzählen Zähler je Anfrage, Start 17, je Benutzer unabhängig Umsetzung, wie beschrieben Anwendung selbst in doit ausgelagert Sessionverwaltung ist Middleware 1 from werkzeug.wrappers import Request, Response 2 from session_id import get_sid 3 from session_fs import load_session, save_session 4 5 page = file("page.tpl").read() 6 7 def doit(request, session): 8 if "zahl" not in session: 9 session["zahl"] = session["zahl"] += 1 11 lis = [] 12 for k,v in session.iteritems(): 13 if not k.startswith("_"): 14 lis.append("%s = %s" % (str(k), str(v))) 15 return "<br />\n".join(lis) def application(request): 19 c = [] 20 response = Response(c, content_type="text/html") 21 sid = get_sid(request, response) 22 session = load_session(sid) 23 content = doit(request, session) 24 save_session(session) 25 dic = { title : Sessions, content : content} 26 c.append(page % dic) 27 return response Parallele Zugriffe Dateien liegen auf einem Server Mehrere Zugriffe auf die Datei zur selben Zeit ist möglich Selbst bei einer Session-Datei, zum Beispiel bei <iframe> (böse) Lesender/schreibender Zugriff Konflikte Unklares Verhalten Gleichzeitiges Schreiben und Lesen Was wird gelesen? Halb/halb? Was wird geschrieben? Noch konsistent? Lösung Sperren Verwaltung exklusiver Zugriffsrechte Web- Server Dateisystem Server/Host Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Zustandsverwaltung über Anfrage hinaus Zustandsverwaltung über Anfrage hinaus Sperren mit Dateien Exklusiver Zugriff auf Datei, fnctl flock(fd, operation) für Sperrverwaltung, nur Unix fd File descriptor, offene Datei Konstanten LOCK_ * in fnctl Operationen (Auszug) LOCK_EX (2): Exklusiver Zugriff, warten wenn (eine) Sperre noch vergeben LOCK_UN (8): Sperre freigeben Verwendung Klammer um Anfang/Ende der Anwendung (kompletter Request ist kritischer Bereich aus Session-Sicht) lockf, thread-sicher Sperre erhalten _ * -Schlüssel, interne Merker ToDo: Schließen im Fehlerfall,... session_fslock 1 import os, cpickle, fcntl 2 from session_fs import STORAGE, SID, kill_session 3 4 FKEY, LOCKFKEY = "_file", "_lockfile" 5 def load_session(session_id): 6 fpath = os.path.join(storage, session_id) 7 lockf = file(fpath, "a") # force open file 8 fcntl.flock(lockf, fcntl.lock_ex) 9 f = file(fpath, "r+") # lock to read and write 10 try: 11 session = cpickle.load(f) 12 except EOFError: 13 session = {} 14 session[sid] = session_id 15 session[lockfkey] = lockf 16 session[fkey] = f 17 return session def save_session(session): 20 f = session[fkey]; del session[fkey] 21 lockf = session[lockfkey]; del session[lockfkey] 22 f.seek(0) # Anfang von Datei 23 cpickle.dump(session, f) 24 f.close() 25 fcntl.flock(lockf, fcntl.lock_un) 26 lockf.close() Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Sessions mit werkzeug Realisieren von Sessions Komplexe, fehleranfällige Middleware Vorgefertigte Lösungen verwenden Beispiel: werkzeug.contrib.sessions werkzeug.contrib.sessions Vorgefertigte Bibliothek, kümmert sich um Cookies und Storage Eine Option ist Dateisystem zum speichern (Z23) Als Middleware einfach zwischen Aufruf und Ergebnis setzen ToDo Aufräumen abgelaufener Sessions Weitere Konfiguration möglich 1 from werkzeug.wrappers import Request, Response 2 import werkzeug.contrib.sessions as sessions 3 4 page = file("page.tpl").read() 5 6 def doit(request, session): 7 if "zahl" not in session: 8 session["zahl"] = 16 9 session["zahl"] += 1 10 lis = [] 11 for k,v in session.iteritems(): 12 lis.append("%s = %s" % (str(k), str(v))) 13 return "<br />\n".join(lis) def app(request): 17 session = request.environ["werkzeug.session"] 18 content = doit(request, session) 19 dic = { title : Sessions, content : content} 20 return Response(page%dic,content_type="text/html") # haenge die Middleware dazwischen 23 fsstore=sessions.filesystemsessionstore() 24 application=sessions.sessionmiddleware(app,fsstore) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

20 Zustandsverwaltung über Anfrage hinaus Bibliotheken Sessions Integration von Datenbanken Sessions Umsetzung Serialisieren häufig notwendig Versuchen wenig Daten in der Session zu halten Keine Frames, kein <iframe>, konkurrierende Zugriffe Datenbanken für Web-Anwendungen Mehrbenutzeranw., immer mit dabei Alle Anwendungsdaten, auch Session-Daten möglich Dateien als Ablage und sperren häufig nicht beste Wahl Datenbanken und Python Funktioniert nur gut auf einem Dateisystem auf einem Rechner (/tmp), nicht gut bei Network File System (NFS) Skaliert nicht immer wie gewünscht, ursprünglich nicht gebaut für sehr viele Anfragen/Dateien gleichzeitig Einsatzgebiete: Sessions, Zugriffszähler, Kommentare in Blogs,... Alternativen für Speicher-Backend tmpfs, shared memory mit locking Datenbanken Sichere Ablage von Daten Design für gleichzeitigen schreibenden und lesenden Zugriff Ausgefeilte Sperrverwaltung, Transaktionskonzept (ACID) Anbindung aller wichtigen DBMS Python DB-API 2.0 (PEP 249) definiert DB-unabhängige Schicht (Pythons JDBC) Treiber für spezifische DBMS Postgresql und Python Treiber psycopg2, pygresql Postgresql wie gewohnt (auch auf ZuHause-Image) Frameworks: Tools, ORM,... Datenbank Python DB-API 2.0 psycopg2 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Bibliotheken Bibliotheken Web-Seite mit Python und Postgresql Beispiel Verwendung, wie gewohnt Verbindungsaufbau connect cursor-konzept, je Verbindung Anfragen mit execute, Parameter verwenden! peps/pep-0249/ initd.org/psycopg/ 1 from werkzeug.wrappers import Request, Response 2 import psycopg2 as pg 3 4 page = file("page.tpl").read() 5 keys = ["vorname", "name", "matnr"] 6 tline = "<tr> %s </tr>" 7 thead, tdata = "<th>%s</th> ", "<td>%s</td> " 8 9 def doit(request): 10 conn = pg.connect(host="localhost", database="medieninf", 11 user="medieninf", password="medieninf") 12 curs = conn.cursor() 13 curs.execute("select "+", ".join(keys)+" FROM studi") 14 lis = [tline%"".join(map(lambda k:thead%k,keys))] 15 for row in curs.fetchall(): 16 lis.append(tline%"".join(map(lambda k:tdata%k,row))) 17 return "<table>\n" + "\n".join(lis) + "</table>\n" def application(request): 21 content = doit(request) 22 dic = { title : Namen, content : content} 23 return Response(page%dic,content_type="text/html") Sicheres Parametrisieren von Anfragen Externe Daten sind bedrohlich Benutzereingabe, Datei, DB,... Verhindere SQL-Injection Umsetzung mit execute Wie %-Operator, extra Argument Tupel oder Dictionary 1 import psycopg2 as pg 2 3 keys = ["vorname", "name", "matnr"] 4 tline = "<tr> %s </tr>" 5 thead, tdata = "<th>%s</th> ", "<td>%s</td> " 6 7 def doit(request): 8 conn = pg.connect(host="localhost", database="medieninf", 9 user="medieninf", password="medieninf") 10 curs = conn.cursor() 11 sql = "SELECT "+", ".join(keys)+" FROM studi " 12 if "matnr" in request.args: 13 sql += "WHERE matnr = %s" 14 curs.execute(sql, (request.args["matnr"], )) 15 elif "vorname" in request.args: 16 sql += "WHERE vorname LIKE %(vorname)s" 17 like = "%%" + request.args["vorname"] + "%%" 18 curs.execute(sql, { vorname : like}) 19 else: 20 curs.execute(sql) 21 lis = [tline%"".join(map(lambda k:thead%k,keys))] 22 for row in curs.fetchall(): 23 lis.append(tline%"".join(map(lambda k:tdata%k,row))) 24 return "<table>\n"+"\n".join(lis)+"</table>\n" Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

21 Bibliotheken Bibliotheken Sicheres Parameterisieren von Anfragen Ernst gemeint Postgresql und Python Hinweise/1 initd.org/psycopg/docs/usage.html Spalten-/Tabellennamen Schlüssel vorname, name, matnr sind keine Variablen, kommen im Quelltext vor Falls Spalten-/Tabellennamen dynamisch gesetzt werden, dann müssen diese per String-Operation integriert werden Dann manuell prüfen zum Beispiel mit Dictionary, wobei Schlüssel die Benutzereingabe ist und der Wert im Quelltext steht Ergebnisse als Dictionary Spaltenname statt Position in Anfrage für Wertzugriff Verständlicherer Quellcode psycopg2.extras.dictcursor Unicode Daten Unicode-Daten kann Encoding-Probleme hervorrufen Datenbank Unicode statt ASCII liefern lassen extensions.register_type Aktueller cursor liefert statt String immer unicode Wenn alles immer Unicode ist, dann gibt es keine Probleme >>> import psycopg2.extras as extras >>> curs=conn.cursor(cursor_factory=extras.dictcursor) >>> curs.execute("select * FROM studi") >>> row = curs.fetchone() >>> row [815, Susi, Sinnlos ] >>> row["vorname"] Susi >>> import psycopg2.extensions as extensions >>> curs = conn.cursor() >>> sql = "INSERT INTO studi (matnr, vorname, name) " >>> sql += " VALUES (%s, %s, %s)" >>> curs.execute(sql, (1, u Jörg, u Üßgärö )) >>> conn.commit() >>> curs.execute("select * FROM studi WHERE matnr=1") >>> curs.fetchone() (1, J\xc3\xb6rg, \xc3\x9c\xc3\x9fg\xc3\xa4r\xc3\xb6 ) >>> curs = conn.cursor() >>> extensions.register_type(extensions.unicode, curs) >>> curs.execute("select * FROM studi WHERE matnr=1") >>> curs.fetchone() (1, u J\xf6rg, u \xdc\xdfg\xe4r\xf6 ) >>> curs.execute("select * FROM studi WHERE matnr=1") >>> print(", ".join(curs.fetchone()[1:])) Jörg, Üßgärö Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Bibliotheken Bibliotheken Postgresql und Python Hinweise/2 Web-Anwendungen und Transaktionen Thread-Sicherheit Sowohl Datenbankverbindung als auch Cursor ist thread-sicher Connection-Pools separat Praktikum: eine Verbindung conn je Anfrage Transaktionen Eine Transaktion je Verbindung Start automatisch, beenden mit commit oder rollback >>> curs = conn.cursor() >>> curs.execute("insert INTO studi (matnr,vorname,name)"+ " VALUES (777, Votan, Wahnwitz )") >>> conn.rollback() >>> sql = "SELECT vorname FROM studi WHERE matnr=777" >>> curs.execute(sql) >>> curs.fetchall() [] >>> curs.execute("insert INTO studi (matnr,vorname,name)"+ " VALUES (777, Votan, Wahnwitz )") >>> conn.commit() >>> curs.execute(sql) >>> curs.fetchall() [( Votan,)] Transaktion DB-Sicht Alles zwischen Begin (auto) und Ende DBMS kümmert sich um transaktionale Sicherung Transaktion Anwendersicht, Logical Unit of Work Formular-Feld gesehen, geändert, gespeichert Formular-Feld darf sich zwischenzeitlich nicht geändert haben Mindestens zwei! Anfragen: Lesen in erster (Formular aufbauen), Schreiben in zweiter (Formular auswerten) Mit einer Transaktion alleine nicht durchführbar Aufgabe: Transaktional sicher arbeiten Lesen in erster Anfrage, sichern Werte in Session Vor Schreiben Kontroll-Lesen in zweiter Anfrage, Abbruch bei Änderung Kontrolllesen innerhalb Transaktion Hinweis FOR UPDATE nicht vergessen Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

22 Bibliotheken Bibliotheken Hochladen von Dateien Spezielles HTML-Formular enctype="multipart/form-data", POST, <input type="file» Verarbeiten mit werkzeug, request.files Schlüssel name von file FileStorage-Attribute, lesen von stream fileupload.tpl 1 <form enctype="multipart/form-data" method="post"> 2 Datei: <input type="file" name="binarydata" /><br /> 3 <input type="submit" value="hochladen" /> 4 </form> 1 from werkzeug.wrappers import Request, Response 2 page = file("page.tpl").read() 3 form = file("fileupload.tpl").read() 4 KEY="binarydata" 5 def doit(request): 6 if request.method == "GET": return form 7 if not request.files[key]: 8 return u"<p>keine Datei</p>"+form 9 ls, fs = [], request.files[key] 10 ls.append("content-type: %s"%fs.content_type) 11 ls.append("dateiname (Client): %s"%fs.filename) 12 ls.append("len: %d (meist 0)"%fs.content_length) 13 blob = fs.stream.read() 14 lines.append("content-length: %d " % len(blob)) 15 return "<br />".join(ls) 17 def application(request): 18 content = doit(request) 19 dic = { title : File Upload, content : content} 20 return Response(page%dic,content_type="text/html") Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Speichern Binärdatei in Datenbank Passende Datenbank-Struktur Tabelle mit Referenzinformation id, zum Wiederfinden name, mime, size sind Extras Datei als BLOB (Binary Large Object) mit lobject in Datenbank ablegen CREATE TABLE bin ( id OID PRIMARY KEY, name TEXT, mime TEXT, size INT );... medieninf=> SELECT * FROM bin; id name mime size fileupload1.png image/png fileupload2.png image/png medieninf=> \lo_list Large objects ID Owner Description medieninf medieninf 1 import psycopg2 as pg 2 3 KEY="binarydata" 4 def doit(request): # wenn POST 5 fs = request.files[key] 6 blob = fs.stream.read() 7 conn = pg.connect(host="localhost", database="medieninf", 8 user="medieninf", password="medieninf") 9 lo = conn.lobject(0, "wb") 10 lo.write(blob) 11 sql = "INSERT INTO bin VALUES " 12 sql += "(%(loid)s, %(name)s, %(type)s, %(size)s)" 13 data = { loid : lo.oid, name : fs.filename, 14 type : fs.content_type, size : len(blob)} 15 curs = conn.cursor() 16 curs.execute(sql, data) 17 conn.commit() 18 return "uploaded " + str(lo.oid) Hochladen mit POST Anlegen large object, id Eintragen Meta-Information in Tabelle Muss in Transaktion sein Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Bibliotheken Bibliotheken Laden Binärdatei von Datenbank Bilder erzeugen mit Image Download Datei von DBMS Verwaltungsinformationen anhand von id lesen, zum Beispiel aus Query-Parameter id Lesen des BLOB mit lobject Rückgabe von Inhalt der kompletten Datei mit passenden mimetype zur Ausgabe 1 from werkzeug.wrappers import Request, Response 2 from dbdownloaddoit import doit 3 page = file("page.tpl").read() 4 img = <img src="?id=%(id)d" /> 6 def application(request): 7 if "id" in request.args: # das Bid selbst 8 c,mime = doit(int(request.args["id"])) 9 return Response(c, content_type=mime) 10 else: # Rahmen fuer ein Beispielbild 11 c = img % { id : 31693} 12 dic={ title : Image Show, content :c} 13 return Response(page%dic,content_type="text/html") 1 import psycopg2 as pg 2 3 def doit(id): # get image 4 conn = pg.connect(host="localhost", database="medieninf", 5 user="medieninf", password="medieninf") 6 sql = "SELECT mime FROM bin WHERE id = %s" 7 curs = conn.cursor() 8 curs.execute(sql, (id, )) 9 res = curs.fetchone() 10 if not res: 11 return "Kein Image", "text/plain" 12 lo = conn.lobject(id, "rb") 13 blob = lo.read() 14 return blob, res[0] Alle bekannten Bibliotheken verwendbar Beispiel Image Zeichnen mit ImageDraw, Fonts mit ImageFont Anzeige eines selbstgebauten Buttons Laden eines Templates button.png Füllen des Templates mit Text, Text in spezifischem Font (Vera) und Größe (16) Ausgabe in String über cstringio da nur save möglich Beispiel button.png 1 from werkzeug.wrappers import Request, Response 2 import Image, ImageDraw, ImageFont, cstringio 3 fp = "/usr/share/fonts/truetype/" 4 fp += "ttf-bitstream-vera/vera.ttf" 5 fontsize = 16 7 def application(request): 8 text = "Button" 9 if "text" in request.args: 10 text = request.args["text"] 11 im = Image.open("button.png") 12 draw = ImageDraw.Draw(im) 13 font = ImageFont.truetype(fp, fontsize) 14 twidth, theight = font.getsize(text) 15 imwidth, imheight = im.size 16 x, y = imwidth/2-twidth/2, imheight/2-(theight/2) 17 draw.text((x, y), text, font=font, fill="black") 18 output = cstringio.stringio() 19 im.save(output, format="png") 20 content = output.getvalue() 21 return Response(content,content_type="image/png") Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

23 Bibliotheken Bibliotheken PDF erzeugen mit reportlab reportlab Bibliothek (frei) zum Erzeugen von PDF Auch Formulare und Textsatz möglich Einfaches Beispiel mit absoluter Positionierung (auf Canvas zeichnen), Quadratzahlen 1 from werkzeug.wrappers import Request, Response 2 import cstringio 3 from reportlab.pdfgen import canvas 4 6 def application(request): 7 output = cstringio.stringio() 8 c = canvas.canvas(output) 9 i = 0 10 for x in range(50, 500, 85): 11 c.drawstring(x, 810, "Zahl") 12 c.drawstring(x+33, 810, "Quadrat") 13 for y in range(50, 800, 15): 14 c.drawstring(x, 842-y, "%d"%i) 15 c.drawstring(x+33, 842-y, "%d"%(i*i)) 16 i += 1 17 c.save() 18 content= output.getvalue() 19 mime = "application/pdf" 20 return Response(content,content_type=mime) XML verarbeiten mit lxml lxml etree, Elementree, einfaches DOM Einfacher Zugriff auf Unterelemente mit find, auf Attribute mit get Viel mehr möglich 1 from werkzeug.wrappers import Request, Response 2 from lxml import etree 3 5 def application(request): 6 xmlstring = file("adressen.xml").read() 7 addrs = etree.fromstring(xmlstring) 8 l = [] 9 for addr in addrs: 10 anrede = addr.find("anrede").get("bez") 11 name = addr.find("name").text 12 l.append("%s %s" % (anrede, name)) 13 c = "<br />\n".join(l) 14 return Response(c,content_type="text/html") <?xml version="1.0" encoding="utf-8" standalone="no"?> <!DOCTYPE adressen SYSTEM "adressen.dtd"> <adressen> <adresse> <anrede bez="frau"/> <name>hanna Mustermann</name> <strasse>seestr. 5</strasse> <plz land="d">20000</plz> <ort>hamburg</ort> </adresse> <adresse> <anrede bez="firma"/> <name>demo</name> <postfach> </postfach> <plz>10000</plz> <ort>berlin</ort> </adresse> </adressen> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Bibliotheken Bibliotheken Frameworks Beispiel django Fazit django Das Fullstack Framework Alles dabei was man braucht Objekt-Relationaler Mapper Admin-Oberfläche Aussagekräftige URLs, Routing Templating Caching Internationalisierung... Weit verbreitet Man ist sehr schnell sehr produktiv! Alternativen wiki.python.org/moin/webframeworks, Dutzende in Python Andere Sprachen: Ruby (on Rails), PHP (Zend), Java (JavaEE, JSF), C (-) Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Was passiert wirklich (in Frameworks) HTTP, CGI/WSGI, Request/Reponse-Zyklus Templating, Routing Sessions, Cookies Zustandsmanagement (Anwendungskontext) auf Client und Server Eine konkrete Middleware (werkzeug) aber noch kein Framework Integration von Datenbanken und anderer Bibliotheken Verwendung Immer, wenn auch versteckt in Frameworks Immer, wenn man durchgreifen will oder muss Immer, wenn man bei der Fehlersuche verstehen will was passiert Als nächstes Ein Framework (leider nicht django :-) und ein Container JavaEE Web Profile Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

24 Web-Anwendungen im Container JavaEE Übersicht Wiederkehrende Probleme, unabhängig von der Anwendung Performance, Skalierbarkeit Verfügbarkeit Sicherheit Integration, zum Beispiel von Datenbanken Programmiermodelle Ziel Abstraktion: Entwickler von wiederkehrenden Problemen entlasten Verbesserte Implementierung: Effiziente, skalierbare,... Ablaufumgebung Lösungsansatz Plattform Plattform abstrahiert/löst wiederkehrende Probleme Framework/APIs für Dienste Laufzeitumgebung (Container) in der Web-Anwendung läuft Festlegung Programmiermodell(e) Beispiele: JavaEE, Grails, Play, Rails (Ruby), Django (Python), Zend (PHP),... Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JavaEE Java Enterprise Edition Aktuell Version 7 (6/13) Version 6 verbreitet Plattform für Unternehmensanwendungen Tonnen von APIs Container von verschiedenen Herstellern Mehrschichtenarchitektur doc/img/overview-multitieredapps.gif, Fig. 1-1 Web Tier in dieser Veranstaltung Servlets CGI für Java Java Server Pages (JSP) Template-Umgebung (JSF) Framework, Programmiermodell, Präsentation Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JavaEE, Web Tier Tomcat Installieren und Verwenden Servlet Archiv extrahieren Java-Klasse, die Servlet-Schnittstelle implementiert In beliebigem Verzeichnis auspacken Für Verarbeitung von (HTTP-)Anfragen tar zxvf apache-tomcat tar.gz Servlet-Umgebung Laufzeitumgebung des Web Tier, Container Ausführen von Servlets, Übersetzen von JSP in Servlets Konfiguration (conf) nicht notwendig Starten und Stoppen (bin) Starten: bin/startup.sh Stoppen: bin/shutdown.sh HTTP-Server, Port 8080, Servlet-Container, lokal Weiterleiten einer Anfrage an passendes Servlet Logging (logs) Session-Verwaltung Tomcat (vormals) Referenzimplementierung, weit verbreitet Aktuelle Version 8, wir verwenden JavaEE 7: Servlet 3.1, JSP 2.3 Ablaufumgebung Catalina, JSP-Compiler Jasper, integrierter HTTP-Server HTTP Server AJP Connector Servlet Catalina HTTP Connector JSP Jasper logs/catalina log Anschauen! Web-Anwendungen (webapps) Ihre Web-Anwendungen Spezielle Struktur Default: Beispiele, Doku Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

25 Web-Anwendungen im Container Servlet Lebenszyklus Container Beherbergt mehrere Web-Anwendungen Web-Anwendung Besteht aus mehreren Servlet-Klassen und anderen Ressourcen Laufzeit Für jede Anwendung ein Servletkontext Nur eine Instanz eines jeden Servlets in einem Servletkontext Eine Instanz behandelt mehrere Anfragen (auch parallel!) (Sessions separat) Servlet1 Servlet1.class Servlet Servlet2 Servletkontext zur Laufzeit statisch Res1 Web-Anw1 (webtest) Web-Anw2 Container Voraussetzung Klasse geladen, Instanz erzeugt Meist bei erster Anfrage Initialisierung init() Eine Instanz für alle Anfragen Einmal für Lebensdauer Container, oder bei neu instanziieren Service service() Weiterleitung Zuweisung Arbeits-Thread je Anfrage Ein Methodenaufruf je Anfrage Freigabe destroy() Am Ende der Lebensdauer Container, oder vor neu instanziieren durch Änderung Servlet Request Response Initialisierung init() Service service(request,response) doget(req,res) dopost(req,res) doput(req,res)... Freigabe destroy() Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Servlet Hello World Framework-Idee Erben von vordefinierter Klasse HttpServlet Statt Servlet Meist nur HTTP doget Statt überschreiben von service Default-Implementierung von service ruft passend doget, dopost,... auf Kein Rückgabewert 1 package webanw; 2 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import java.io.*; Parameter HttpServletRequest und HttpServletResponse 6 7 public class HelloServlet extends HttpServlet { 9 public void doget(httpservletrequest request, 10 HttpServletResponse response) 11 throws ServletException, IOException { 12 PrintWriter out = response.getwriter(); 13 out.print("hello Servlet World"); 14 } 15 } HttpServletRequest: Instanz repräsentiert aktuelle Anfrage, stellt alle notwendigen Informationen zur Verfügung HttpServletResponse: Instanz repräsentiert Ergebnis, erlaubt Manipulation/Erstellen des Ergebnisses Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Eingabe-Parameter, Enumeration Zugriff auf Parameter getparameter(name) bei gegebenem Namen getparameternames() gibt Enumeration vorhandener Namen zurück Nur GET-Parameter Bei dopost die POST-Parameter Ausgabeformat Vorgabe ist text/html HTML-Rahmen ausgeben Beispiel URL-Ende:?name=Susi&var1=wert1 1 package webanw; 2 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import java.io.*; 6 import java.util.*; 7 8 public class ParameterServlet extends HttpServlet { 10 public void doget(httpservletrequest request, 11 HttpServletResponse response) 12 throws ServletException, IOException { 13 PrintWriter out = response.getwriter(); 14 out.println("<html><body>"); 15 String name = request.getparameter("name"); 16 out.println("hallo " + name + "<br />"); 17 Enumeration<String> e = 18 request.getparameternames(); 19 while (e.hasmoreelements()) { 20 String key = e.nextelement(); 21 String value = request.getparameter(key); 22 out.println(key + " = " + value + "<br />"); 23 } 24 out.println("</body></html>"); 25 } 26 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

26 Eingabe-Parameter, Map Zugriff auf Parameter getparametermap() gibt Map statt Enumeration zurück Schlüssel/Wert Paare, aber mehrere Werte möglich (erlaubt bei HTTP) Verwenden erweiterte For-Schleife möglich Generics seit Servlet 3.0 Bei Servlet 2.5 (noch weit verbreitet) keine Typ-Spezifikation, expliziter Cast notwendig Beispiel URL-Ende:?name=Susi&var1=wert1 Imports ab sofort weggelassen 1 public class ParameterServletMap extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 PrintWriter out = response.getwriter(); 7 out.println("<html><body>"); 8 String name = request.getparameter("name"); 9 out.println("hallo " + name + "<br />"); 10 Map<String, String[]> map = 11 request.getparametermap(); 12 for (String key : map.keyset()) { 13 String[] values = map.get(key); 14 out.println(key + " = "); 15 if (values.length == 1) { 16 out.println(values[0] + "<br />"); 17 } else { 18 out.print("[ "); 19 for (String value : values) { 20 out.print(value + " "); 21 } 22 out.print("]"); 23 } 24 } 25 out.println("</body></html>"); 26 } Prof. Dr. Peter Barth (HS-RheinMain) 27 } Web-basierte Anwendungen 6. Juli / 295 Weitere request-methoden getcookies(): Feld mit allen Cookies getheader(name): Wert des Headers mit Schlüssel name getheadernames(): Enumeration der Schlüssel der Header getheaders(): Enumeration der Werte mit Schlüssel name getintheader(name): Wie getheader, nur Rückgabe einer ganzen Zahl (Konvertierung)... Dokumentation lesen: Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Ausgabe-Möglichkeiten Zugriff Ausgabestrom Manipulieren der Antwort, Beispiele: Abbruch Ausgabe, Fehlermeldung mit HTTP-Statuscode Weitere response-methoden, Doku 1 public class FehlerServlet extends HttpServlet { 3 public void doget(httpservletrequest request, getwriter() liefert PrintWriter-Instanz 4 HttpServletResponse response) 5 throws ServletException, IOException { Verwenden wie System.out 6 response.setcontenttype("text/html"); 7 response.setcharacterencoding("utf-8"); 8 PrintWriter out = response.getwriter(); Setzen des Inhaltstyps 9 out.print("hello Feher Servlet World"); 10 // Abbruch, Ausgabe/Einstellungen Setzen des Zeichensatz (Encoding) 11 // bis hier werden verworfen 12 response.senderror(404, "nix gefunden"); 13 } 14 } Ausgabe Binärdaten Button generieren Button mit gut aussehendem Text Generieren eines Bilds Bibliothek von Java, Graphics2D Text als Parameter Beispiele...?...?text=Ok... 1 public class ButtonServlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 ServletOutputStream sos = 7 response.getoutputstream(); 8 response.setcontenttype("image/png"); 9 String text = 10 request.getparameter("text"); 11 if (text == null) { 12 text = "Button"; 13 } 14 BufferedImage img = renderbutton(text); 15 ImageIO.write(img, "PNG", sos); 16 } ServletOutputStream statt PrintWriter ImageIO von javax.imageio Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

27 Generieren Binärdaten Weiterleitung Server Bilder awt, awt.image Graphics2D-API Alle Java Bibliotheken nutzbar Bilder Audio-, Video-Streaming PDF... 1 final static int WIDTH = 100; 2 final static int HEIGHT = 20; 3 public BufferedImage renderbutton(string text) { 4 BufferedImage img = 5 new BufferedImage(WIDTH, HEIGHT, 6 BufferedImage.TYPE_INT_RGB); 7 Graphics2D g2d = img.creategraphics(); 8 g2d.setcolor(color.white); 9 g2d.fillrect(0, 0, WIDTH, HEIGHT); 10 g2d.setcolor(color.black); 11 g2d.drawroundrect(0, 0, WIDTH-2, HEIGHT-2, 6, 6); 12 Font font = new Font(Font.SERIF, Font.PLAIN, 12); 13 g2d.setfont(font); 14 FontMetrics metrics = g2d.getfontmetrics(font); 15 g2d.setrenderinghint( 16 RenderingHints.KEY_TEXT_ANTIALIASING, 17 RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 18 int adv = metrics.stringwidth(text); 19 int hgt = metrics.getheight(); 20 g2d.drawstring(text, 21 (WIDTH-adv)/2, 22 (HEIGHT/2)-2+(hgt/2)); 23 g2d.dispose(); 24 return img; 25 } Ziel: Ein Quellcode für GET und POST Weiterleitung der Anfrage im Zeile 15, Methodenaufruf GET POST 1 public class GetPostServlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 PrintWriter out = response.getwriter(); 7 out.println("das ist GET"); 8 } 10 public void dopost(httpservletrequest request, 11 HttpServletResponse response) 12 throws ServletException, IOException { 13 PrintWriter out = response.getwriter(); 14 out.println("das ist zuerst POST"); 15 doget(request, response); 16 } 17 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Weiterleitung Client sendredirect(url) Weiterleitung der Anfrage über Client Der Client erhält eine spezielle Antwort Der Client schickt daraufhin eine neue Anfrage encoderedirecturl(url) berücksichtigt gegebenenfalls Sessions Nachteil Zwei Anfragen, aufwendig und langsam Ziel Weiterleitung innerhalb des Containers Einfach und schnell 1 public class RedirectServlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 String url = "HelloServlet"; 7 url = response.encoderedirecturl(url); 8 response.sendredirect(url); 9 } 10 } Redirect Servlet redirect auf HelloServlet Web Browser Hello Servlet Web Server HTML von HelloServlet Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Weiterleitung Server, RequestDispatcher Weiterleitung im Server an anderes Servlet getrequestdispatcher(url), URL-Pfad wie von außen Alternativ: getnameddispatcher, servlet-name des Servlets forward(request, response), Weiterleiten der Anfrage, Ersatz der Ausgaben in out Alternativ: include, Hinzufügen statt Ersatz Typisches Einsatzgebiet: Controller (keine Ausgaben) Beispiel: Falls GET-Parameter name gesetzt, dann an ParameterServlet weiterleiten, ansonsten Ausgabe einer Meldung 1 public class WantNameServlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 if (request.getparameter("name")!= null) { 7 RequestDispatcher rd = 8 request.getrequestdispatcher("/parameterservlet"); 9 rd.forward(request, response); 10 } else { 11 PrintWriter out = response.getwriter(); 12 out.println("bitte name als GET-Parameter"); 13 } 14 } 15 } WantName Servlet Want Name Parameter Web Browser HTML von ParameterServlet Web Server Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

28 Struktur Web-Anwendung Deployment Web-Anwendung Mapping? Web-Anwendung deployen Woher weiß Tomcat was bei einem Request (URL) passieren soll? Web-Anwendung auf dem Container bereit stellen Beispiel: /jee/helloservlet Spezifisch je nach Container Struktur Webanwendung Deployment mit tomcat In eigenem Verzeichnis, beliebiger Name, meist erster Teil der URL Verzeichnisbaum der Web-Anwendung unter webapps kopieren Statische Ressourcen (und JSP) auf oberster Ebene, direkt zugreifbar Verzeichnis WEB-INF Nicht zugreifbar, Konfiguration in Datei web.xml Java.class-Dateien in classes Java.jar-Dateien (Libraries) in lib WAR-Datei (.war), Web Archive Paketierung Dateibaum als ZIP-Archiv Inhalt von jee.war Alle Servlets in Java-Paket webanw Sehr sinnvoll für Entwicklung Tomcat erkennt Änderungen (meistens), notfalls neu starten WAR-Archiv unter webapps kopieren Tomcat packt Archiv aus Deployment-Manager Tools verwenden Für Produktionsumgebungen sinnvoll, siehe Dokumentation Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Konfiguration mit web.xml Wichtigste Tags web.xml Mapping Zuordnung von URL auf Servlet 1. Servlets erhalten Namen 2. URL-Pattern auf Namen mappen Beispiel Ziel: Anfrage /jee/helloservlet auf Servlet-Klasse webanw.helloservlet mappen Konvention Tomcat, Unterordner Web-App als erster Teil der URL Verbleibendes Ziel: Anfrage /HelloServlet auf Servlet-Klasse webanw.helloservlet mappen web.xml 1 <?xml version="1.0" encoding="utf-8"?> 2 <web-app xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 4 xsi:schemalocation="http://java.sun.com/xml/ns/javaee 5 6 version="3.0"> 7 <servlet> 8 <servlet-name>helloservlet</servlet-name> 9 <servlet-class>webanw.helloservlet</servlet-class> 10 </servlet> 11 <servlet-mapping> 12 <servlet-name>helloservlet</servlet-name> 13 <url-pattern>/helloservlet</url-pattern> 14 </servlet-mapping> 15 </web-app> XML-Datei mit Schema (nicht abtippen, ausnahmsweise Copy&Paste ok, aber nicht von diesem Foliensatz (Zeichensatz)) Erst Namen vergeben mit <servlet> Dann URL-Pattern auf einen Namen (damit Servlet) mappen mit <servlet-mapping> servlet-name: Eindeutiger Name für jedes Servlet servlet-mapping: Zuordnung von ein oder mehreren URL-Patterns an ein Servlet (per Name) Mehrere URLs können auf einund dasselbe Servlet gemappt werden Achtung: In Beispielen wurde bisher immer der Klassenname des Servlets auf das jeweilige Servlet gemappt nur für Beispiele url-pattern Möglichkeiten rechts Exaktes Pattern: /<pfad> Start mit /, danach beliebiger Pfad <pfad> Ein exakter Pfad für ein Servlet /HelloServlet Erweiterungs-Pattern: *.<ext> Alle Pfade mit spezifischer Endung <ext> bei letzter Pfadkomponente Nur ein Stern am Anfang erlaubt Intern: *.jsp auf Jasper *.rst Pfad-Pattern: /<pfad>/* Alle Pfade mit festem Anfang /<pfad> Matcht alles unterhalb Nur ein Stern am Ende erlaubt, beginnt mit / /foo/bar/* Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

29 Weitere Tags web.xml Annotationen ab Servlet 3.0 welcome-file-list Liste von Dateien in absteigender Priorität, die ohne weitere URI-Angabe im Kontext der Web-Anwendung angezeigt werden Beispiel: Anzeige von welcome.html, wenn nicht vorhanden, dann index.html 1 <welcome-file-list> 2 <welcome-file>welcome.html</welcome-file> 3 <welcome-file>index.html</welcome-file> 4 </welcome-file-list> context-param Parameter für die gesamte Web-Anwendung session-config Konfiguration von Sessions mime-mapping Welche Datei-Erweiterung liefert welchen Mime-Typ error-page Welche Seite bei welchem Fehlercode... und vieles mehr Wird bei Bedarf ergänzt Vollständige Referenz in der Dokumentation Servlet-API 3.0, JSR 315 Konfiguration mit web.xml XML, verbose, komplex Trennung von Konfiguration und Code (prinzipiell gut, aber aufwendig) Häufig muss Mapping nicht konfigurierbar sein, beziehungsweise ein Default-Mapping wäre schön Default-Konfiguration im Code mit Annotationen Seit Servlet 3.0 Annotation WebServlet mit name und urlpatterns Annotationsverarbeitung abschaltbar wenn nicht benötigt 1 <web-app...> 2 <servlet> 3 <servlet-name>helloservlet</servlet-name> 4 <servlet-class>webanw.helloservlet</servlet-class> 5 </servlet> 6 <servlet-mapping> 7 <servlet-name>helloservlet></servlet-name> 8 <url-pattern>/hello</url-pattern> 9 </servlet-mapping> 10 </web-app> 1 package webanw; 2 import javax.servlet.*; 3 import javax.servlet.http.*; 4 import java.io.*; 5 import javax.servlet.annotation.*; 6 8 urlpatterns={"/hello"}) 9 public class HelloServlet extends HttpServlet { } 1 <web-app... 2 metadata-complete="true"> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Weitere Annotationen ab Servlet 3.0 Beispiel Konfiguration eines Servlets mit Anlegen eines Initialisierungsparameter von Servlet mit Mime-Attachments... Doku für Details, Parameter, etc. Annotation versus web.xml Einträge in web.xml überschreiben Konfiguration per Annotation Einfach bei der Entwicklung, sinnvolle Vorgabewerte ohne XML Nachträgliche Konfiguration ohne Code-Änderung bei Deployment Konventionen in Veranstaltung Wir verwenden einheitlich die Konfiguration in web.xml Kompatibilität zu Servlet 2.5 Konfiguration bleibt unabhängig von Source-Code Keine weiteren Neuerungen von Servlet 3.0 Fragmente zur Inklusion in web.xml Asynchrone Anfragebearbeitung... Ziel Deployment Parameter Servlet konfigurierbar Parameter ändern ohne Quellcode-Anpassung oder neu übersetzen Ändern der web.xml ServletConfig Zugriff auf Konfiguration Spezifisch für Servlet getinitparameter zum Zugriff auf Parameter init-param Innerhalb Servlet-Tag Name/Wert Paare Mehrere möglich 1 public class GrussServlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 ServletConfig sc = getservletconfig(); 7 String gruss = sc.getinitparameter("gruss"); 8 PrintWriter out = response.getwriter(); 9 out.print(gruss + " Welt!"); 10 } 11 } 1 <servlet> 2 <servlet-name>grussservlet</servlet-name> 3 <servlet-class>webanw.grussservlet</servlet-class> 4 <init-param> 5 <param-name>gruss</param-name> 6 <param-value>guude</param-value> 7 </init-param> 8 </servlet> 9 <servlet-mapping> 10 <servlet-name>grussservlet</servlet-name> 11 <url-pattern>/grussservlet</url-pattern> 12 </servlet-mapping> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

30 Beispiel Konfiguration Datenbankzugriff, Zugriff 1 public class DBServlet extends HttpServlet { 2 private Connection con = null; // in init 4 public void doget(httpservletrequest request, 5 HttpServletResponse response) 6 throws ServletException, IOException { 7 PrintWriter out = response.getwriter(); 8 out.print("<html><body><h3>db-benutzer</h3>"); 9 String query = "SELECT usename, usesysid FROM pg_user"; 10 try { Skaliert nicht gut, fix gleich Statement stmt = con.createstatement(); 12 ResultSet rs = stmt.executequery(query); 13 out.println("<table>"); 14 out.print("<tr><th>usename</th>"); 15 out.println("<th>usesysid</th></tr>"); 16 while (rs.next()) { 17 String usename = rs.getstring("usename"); 18 String usesysid = rs.getstring("usesysid"); 19 out.print("<tr><td>"+usename+"</td>"); 20 out.print("<td>"+usesysid+"</td></tr>"); 21 } 22 out.println("</table>"); 23 } catch (SQLException e) { 24 out.println("db-fehler"); 25 log("sql-fehler mit Anfrage " + query, e); 26 } 27 out.println("</body></html>"); 28 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Datenbankverbindung als Instanzvariable In init initialisiert Für alle Anfragen während der Lebensdauer des Servlets verfügbar Logging Mit log, in log/localhost... Stacktrace zeigen Beispiel Konfiguration Datenbankzugriff, Initialisierung Treiber laden JAR-Datei des Treibers in das Verzeichnis WEB-INF/lib kopieren, machen wir immer so Bei Produktivbetrieb auch in lib des Containers möglich Konfiguration ServletConfig Parameter in web.xml 1 <init-param> 2 <param-name>dbhost</param-name> 3 <param-value> 4 db.intern.mi.hs-rm.de 5 </param-value> 6 </init-param> 7 <! > 2 public void init() { 3 try { 4 Class.forName("org.postgresql.Driver"); 5 } catch (ClassNotFoundException e) { 6 log("postgresql driver did not load"); 7 return; 8 } 9 ServletConfig sc = getservletconfig(); 10 String dbhost = sc.getinitparameter("dbhost"); 11 String dbname = sc.getinitparameter("dbname"); 12 String dbuser = sc.getinitparameter("dbuser"); 13 String dbpassword = sc.getinitparameter("dbpassword"); 14 if (dbhost == null dbname == null 15 dbuser == null dbpassword == null) { 16 log("not all parameters for database set"); 17 return; 18 } 19 String url = "jdbc:postgresql://"+dbhost+":5432/"+dbname; 20 try { 21 con = DriverManager.getConnection(url, dbuser, dbpassword); 22 } catch (SQLException e) { 23 log("could not connect"); 24 return; 25 } 26 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Instanzvariablen? Achtung! Instanzvariable Eine offene Datenbankverbindung als Instanzvariable im Servlet Initialisierung bei Erstellung Servlet Es gibt nur eine Instanz des Servlets für alle Benutzer/Anfragen Probleme Threadsicherheit: Mehrere Threads (Container) greifen gleichzeitig auf Datenbank zu Skalierung: Mehrere Threads des Containers greifen über eine Verbindung auf Datenbank zu Instanzvariablen Ziel: Aufwand je Anfrage verringern Beispiel: Verbindungsaufbau zur DB Threadsicherheit Nur eine Servlet-Instanz (nicht verteilt) Alle Anfragen gegen eine Verbindung Funktioniert nur, wenn der JDBC-Treiber threadsicher ist Skalierung Ok bei PostgreSQL Aber Serialisierung der Anfragen Datenbankverbindung wird Engpass Lösung: eine Datenbankverbindung je Thread, ThreadLocal Instanzvariablen vermeiden Meist falsch eingesetzt (Lebenszyklus) Meist anderer Scope richtig Korrekte Nutzung komplex Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Datenbankzugriff Verbindung je Anfrage Eine neue Datenbankverbindung je Anfrage Verbindung aufmachen Verbindung nutzen Verbindung schließen Auslagern in DBServletUtil getconnection(servletconfig): Holt sich eine neue Datenbankverbindung genhtml(connection): Generiert die Ausgabe (Tabelle der Benutzer) bei gegebener Datenbankverbindung 1 public class DBServletPerRequest extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 ServletConfig sc = getservletconfig(); 7 Connection con = DBServletUtil.getConnection(sc); 8 PrintWriter out = response.getwriter(); 9 out.print(dbservletutil.genhtml(con, "PerRequest")); 10 try { 11 con.close(); 12 } catch (SQLException ignore) { } 13 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

31 Datenbankzugriff Verbindung je Thread Datenbankzugriff Übersicht Idee Eine Datenbankverbindung je Thread Java Feature ThreadLocal Aufbau Bei Anfrage Wenn für Thread noch keine Verbindung, dann öffnen und merken Abbau Am Ende der Servlet-Lebensdauer Alle Verbindungen schließen Treiber entladen, sonst Speicherleck 1 public class DBServletPerThread extends HttpServlet { 2 private ThreadLocal<Connection> tcon = 3 new ThreadLocal<Connection>(); 4 private List<Connection> cons = 5 new ArrayList<Connection>(); 6 public Connection getconnection() { 7 if (tcon.get() == null) { 8 ServletConfig sc = getservletconfig(); 9 tcon.set(dbservletutil.getconnection(sc)); 10 synchronized (cons) { cons.add(tcon.get()); } 11 } 12 return tcon.get(); 13 } 15 public void doget(httpservletrequest request, 16 HttpServletResponse response) 17 throws ServletException, IOException { 18 PrintWriter out = response.getwriter(); 19 Connection con = getconnection(); 20 out.print(dbservletutil.genhtml(con, "PerThread")); 21 } public void destroy() { 23 try { 24 for (Connection con: cons) { con.close(); } 25 Driver driver = DriverManager.getDriver("jdbc:postgresql://x/y"); 26 DriverManager.deregisterDriver(driver); 27 } catch (SQLException ignore) { } 28 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Optionen Eine Verbindung je Anfrage: Früher sehr teuer (bei teurem Verbindungsaufbau), heute akzeptabel, skaliert nicht gut Eine Verbindung: Wiederverwendung der Verbindung, effizient, aber skaliert nicht, potentiell anfällig für Nebenläufigkeit, vermeiden (Instanzvariable, Anti-Pattern) Eine Verbindung je Thread: Sehr guter Match von notwendigen und zur Verfügung gestellten Verbindungen, effizient und skaliert, etwas komplex zu realisieren Mini-Benchmark siege -b -c 42 -t 10s 42 Benutzer gleichzeitig, so schnell wie möglich (-b) für 10 Sekunden Wieviele Anfragen wurden geschafft? Achtung, nur einfache cachebare Anfrage, nicht aussagekräftig Lies, damn lies, statistics, benchmarks Option Anzahl Anfragen One per request 1529 One One per thread Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Scopes Übersicht Anfrage-Scope Attr. forward Sessionattribut Instanzvariable* Achtung: Anfragen potenziell parallel Synchronisation, wenn notwendig, Aufgabe des Entwicklers Attribut Lebensdauer Anwendung Servlet Servlet ServletContext Anfrage Session Servlet Anwendung Anfrage-Scope Objekt für die Dauer einer Anfrage vorhalten request.setattribute, request.getattribute Länger als Block (Programmiersprache) 1 public class Anfrage1Servlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 request.setattribute("answer", "fortytwo"); 7 RequestDispatcher rd = 8 request.getrequestdispatcher("/anfrage2servlet"); 9 rd.forward(request, response); 10 } 11 } 1 public class Anfrage2Servlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 PrintWriter out = response.getwriter(); 7 String wert = (String) request.getattribute("answer"); 8 out.println("answer = " + wert); 9 } 10 } * zum Beispiel für Caching, Datenverbindung, Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

32 Session-Scope Anwendungs-Scope Session-Scope HttpSession nur mit HTTP verfügbar request.getsession() assoziiert mit aktueller Anfrage, erzeugt neue Session falls noch keine vorhanden Achtung: Bei Links in gleiche Web-Anwendung encodeurl verwenden (URL-Rewriting, Anhängen Session-ID) Vorteil gegenüber zum Beispiel werkzeug; Ablage im Hauptspeicher (JVM), kein (De-)Serialisieren 1 public class SessionServlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 HttpSession session = request.getsession(); 7 Object o = session.getattribute("zaehler"); 8 Integer zaehler = (Integer) o; 9 if (zaehler == null) { 10 zaehler = Integer.valueOf(0); 11 } 12 zaehler += 1; 13 session.setattribute("zaehler", zaehler); 14 PrintWriter out = response.getwriter(); 15 out.print("session " + zaehler); 16 out.println(" mal geklickt"); 17 } 18 } Attribute: get/setattribute, getattributenames, removeattribute Lebensdauer Session: get/setmaxinactiveinterval, isnew, getcreationtime, getlastaccessedtime Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Anwendungs-Scope Objekte leben während der Lebensdauer der Anwendung Instanzvariable Servlet kann kürzer sein, und nur von Servlet zugreifbar ServletContext getservletcontext() Für alle Servlets gleiches Objekt (im Gegensatz zu getservletconfig, nur dieses Servlet, nur lesen) Attribute: get/setattribute, getattributenames removeattribute siege -b -c 1 -r public class Anwendung1Servlet extends HttpServlet { 2 public void doget(httpservletrequest request, 3 HttpServletResponse response) 4 throws ServletException, IOException { 5 ServletContext app = getservletcontext(); 6 Object o = app.getattribute("zaehler"); 7 Integer zaehler = (Integer) o; 8 if (zaehler == null) 9 zaehler = Integer.valueOf(0); 10 zaehler += 1; 11 app.setattribute("zaehler", zaehler); 12 PrintWriter out = response.getwriter(); 13 out.println("app1 wurde geklickt"); 14 } 15 } 1 public class Anwendung2Servlet extends HttpServlet { 2 public void doget(httpservletrequest request, 3 HttpServletResponse response) 4 throws ServletException, IOException { 5 ServletContext app = getservletcontext(); 6 int z = (Integer) app.getattribute("zaehler"); 7 PrintWriter out = response.getwriter(); 8 out.println("app1-klicks: " + z); 9 } 10 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Anwendungs-Scope Synchronisiert Threadsicherheit Code letzte Folie nicht threadsicher Kritischer Wettlauf bei Aktualisierung zaehler Synchronisation AtomicLong, threadsicherer Zähler in java.util.concurrent.atomic Initialisierung in init, Garantiert noch kein (nebenläufiger) Zugriff incrementandget garantiert atomar Ausgabe nur lesen siege -b -c 100 -r public class Anwendung1ServletTS extends HttpServlet { 2 public void init() { 3 AtomicLong al = new AtomicLong(0); 4 getservletcontext().setattribute("al", al); 5 } 6 public void doget(httpservletrequest request, 7 HttpServletResponse response) 8 throws ServletException, IOException { 9 ServletContext app = getservletcontext(); 10 AtomicLong al = 11 (AtomicLong) app.getattribute("al"); 12 al.incrementandget(); 13 PrintWriter out = response.getwriter(); 14 out.println("app1 wurde geklickt"); 15 } 16 } 1 public class Anwendung2ServletTS extends HttpServlet { 2 public void doget(httpservletrequest request, 3 HttpServletResponse response) 4 throws ServletException, IOException { 5 ServletContext app = getservletcontext(); 6 AtomicLong al = 7 (AtomicLong) app.getattribute("al"); 8 PrintWriter out = response.getwriter(); 9 out.println("app1-klicks: " + al.get()); 10 } 11 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 ServletContext getinitparameter Zugriff auf Parameter definiert in web.xml Definition auf web-app Ebene, unabhängig von Servlets getresourceasstream Zugriff auf zum Beispiel statische Inhalte wie Bilder oder ähnliches Liegen nicht unbedingt im Dateisystem, sondern in einer WAR-Datei (Zip-Archiv) log Eintrag in Log-Datei Optionaler zweiter Parameter Throwable für Stacktrace weiteres in der Dokumentation 1 <context-param> 2 <param-name>admin</param-name> 3 <param-value>nobody in his right mind</param-value> 4 </context-param> 1 ServletContext app = getservletcontext(); 2 String admin = app.getinitparameter("admin"); 1 ServletContext app = getservletcontext(); 2 String admin = app.getinitparameter("admin"); NIE auf Dateisystem im web-app Pfad versuchen zuzugreifen 1 java.io.inputstream is; 2 // ab Wurzelverzeichnis der web-app 3 // URL wäre.../<web-app>/images/hsrm.png 4 is = app.getresourceasstream("/images/hsrm.png"); 5 BufferedImage img = ImageIO.read(is); 1 log("alles klar"); Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

33 Verhalten anpassen Servlet Filter Problem Einheitliches Verhalten für verschiedene Servlets Jedes Servlet muss dies separat implementieren Wunsch ist konfigurierbares Verhalten Beispiel: Bilder komprimieren, loggen und tracen, validieren, authentifizieren, dispatchen, Konvertierung,... Lösung Servlet Filter Anfrage und Antwort durchläuft eine konfigurierbare Serie von Filtern Filter (Java-Klasse) kann Inhalte verändern, Anfragen verändern/blocken,... Request Response Filter Filter Filter Servlet Filter Erstellen Filter Schnittstelle, für einen konkreten Filter zu implementieren init: Direkt nach Erstellung dofilter: Anfragebearbeitung, weiter in der Filterkette mit chain.dofilter destroy: Am Ende der Lebenszeit des Filters Lebenszyklus wie bei Servlets Konfiguration in web.xml <filter>, <filter-mapping> Wie bei Servlets 1 public class MachtNixFilter implements Filter { 2 public void init(filterconfig filterconfig) { } 3 public void dofilter(servletrequest request, 4 ServletResponse response, 5 FilterChain chain) 6 throws ServletException, IOException { 7 // hier Anfrage manipulieren 8 // request.getservletcontext().log("machtnixfilter"); 9 chain.dofilter(request, response); 10 // hier Antwort manipulieren 11 } 12 public void destroy() { } 13 } web.xml 1 <filter> 2 <filter-name>machtnix</filter-name> 3 <filter-class>webanw.machtnixfilter</filter-class> 4 </filter> 5 <filter-mapping> 6 <filter-name>machtnix</filter-name> 7 <url-pattern>/*</url-pattern> 8 <!-- Alternativ mit Servletnamen --> 9 </filter-mapping> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Antwort Aufsammeln zur Manipulation Beispielmanipulation Fette Medieninformatik Ausgabe abfangen und aufsammeln Ein Objekt, das sich wie eine Antwort verhält Ein Objekt, das (noch) nichts an den Ausgabestrom zurück gibt HttpServletResponseWrapper Klasse um eine Antwort (response) einzupacken Verwenden durch erben und Methoden anpassen Beispiel In Puffer schreiben Später auslesen Nur für Zeichen, Byte-Ströme separat 1 public class ResponseWrapper extends 2 HttpServletResponseWrapper { 3 private CharArrayWriter buffer; 4 5 public ResponseWrapper( 6 HttpServletResponse response) { 7 super(response); // default durchleiten 8 buffer = new CharArrayWriter(); 9 } // Verwender erhält Fake, keine richtige Antwort 12 public PrintWriter getwriter() { 13 return new PrintWriter(buffer); 14 } // Filter kann Inhalt auslesen, manipulieren 17 // und weitergeben 18 public String getcontent() { 19 return buffer.tostring(); 20 } 21 } Medieninformatik fett machen Unverändertes Weiterleiten der Anfrage Auslesen der Antwort Jedes Vorkommen von Medieninformatik mit <strong>-tag umrahmen Manipulationsergebnis in erhaltene Antwort schicken 1 public class MIFilter implements Filter { 2 public void init(filterconfig filterconfig) { } 3 public void dofilter(servletrequest request, 4 ServletResponse response, 5 FilterChain chain) 6 throws ServletException, IOException { 7 HttpServletResponse httpres = 8 (HttpServletResponse) response; 9 ResponseWrapper wrap = 10 new ResponseWrapper(httpres); 11 chain.dofilter(request, wrap); 12 PrintWriter out = response.getwriter(); 13 for (String s: wrap.getcontent().split("[\r\n]+")) { 14 s = s.replace("medieninformatik", 15 "<strong>medieninformatik</strong>"); 16 out.println(s +"\n"); 17 } 18 out.close(); 19 } 20 public void destroy() { } 21 } 1 <html><body> 2 Die Medieninformatik ist cool. <br /> 3 Die Medieninformatik ist die Beste. <br /> 4 Medien-informatik ist nicht Medieninformatik 5 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

34 Filterketten Konfigurieren Hinweis für Entwicklung Vermeiden von Caching Mehrere Filter für ein Servlet/JSP/... konfiguriert Reihenfolge ist die Reihenfolge der passenden <filter-mapping>-einträge in web.xml Erst die url-pattern-mappings, dann die servlet-name-mappings Ausführung automatisch Durch Aufruf von dochain der Klasse FilterChain FilterChain-Instanz wird von Container bereitgestellt /seite.bla /p1/s.bla /p1/i.html Seite bleibt alt Code (HTML-Seite, Bilder,... ) geändert, aber alte Seite/Fehler wird noch angezeigt Grund: Irgendwelche Infrastrukturkomponenten (Browser, Proxy, Cache,... ) versuchen erfolgreich zu cachen Cachen ausreden Versuchen mit Header-Informationen die Infrastrukturkomponenten zu überzeugen nicht zu cachen Ein möglicher Versuch anbei Während Entwicklung Auf lokalem Rechner arbeiten Nur Tomcat und Browser als Infrastrukturkomponenten 1 response.addheader("pragma", "no-cache"); 2 response.setheader("cache-control", 3 "no-cache, no-store, must-revalidate"); 4 response.addheader("cache-control", 5 "pre-ceck=0, post-check=0"); 6 response.setdateheader("expires", 0); /* *.bla /p1/* Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Java Server Pages Eclipse-Unterstützung Web Tools Platform (WTP) Templating mit Java Server Pages (JSP) Eclipse-Unterstützung Sinnvoll für JavaEE Trotzdem web.xml, etc. manuell erstellen und konfigurieren Vermeide Wizards (macht blöd), nutze Vervollständigung (vermeidet auswendig lernen) Features Struktur vorgegeben Vervollständigung Templates (Java, JSP,... ) Servlet-Engine (Tomcat) Integration Screencasts: barth/hsrm/webanw/info Web-Entwicklung mit Servlets Grundlegende Technik, Probleme wie CGI Schwierig korrektes Markup zu erzeugen Tendenz zu Spaghetti-Code Java Server Pages (JSP) Templating für JavaEE Fokus auf Präsentationsschicht Nicht Ersatz, sondern Ergänzung zu Servlets JSP Umsetzung Laufzeitumgebung ist Servlet-Container, zum Beispiel Tomcat JSP werden vor Ausführung in Servlets übersetzt, zum Beispiel mit Jasper Lebenszyklus wie bei Servlet Andere Methoden, nicht direkt verwendet Request Response Initialisierung jspinit() Service jspservice( request, response) Freigabe jspdestroy() Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

35 Java Server Pages Java Server Pages Hello JSP World Struktur Markup/HTML Tags in <%... %> für Java-Code, in <%=... %> für Wertausgabe Achtung: Verleitet zu bösem Spaghetti-Code hello_jsp.java 1... JSP Scripting Tags 2 public final class hello_jsp extends org.apache.jasper.runtime.httpjspbase 3 implements org.apache.jasper.runtime.jspsourcedependent { 4... Scriptlets <%... %> Beliebiger Java Code, mehrere Anweisungen Mit Semikolon jede Anweisung abschließen 5 public void _jspservice(final javax.servlet.http.httpservletrequest request, final javax.servlet.http.httpservletresponse response) 6 throws java.io.ioexception, javax.servlet.servletexception Wird { direkt in die Servlet-Methode _jspservice übernommen 7 final javax.servlet.jsp.pagecontext pagecontext; Integration in Container 8 javax.servlet.http.httpsession session = null; Ausdrücke <%=... %> 9 final javax.servlet.servletcontext application; Ablage innerhalb Web-App auf 10 final javax.servlet.servletconfig config; Nur ein Java Ausdruck, keine Anweisungen, kein Semikolon am Ende 11 oberster Ebene, wie statischer Inhalt javax.servlet.jsp.jspwriter out = null; Wert des Ausdrucks wird im Markup ausgegeben 12 final java.lang.object page = this; (nicht unterhalb WEB-INF) 13 javax.servlet.jsp.jspwriter _jspx_out = null; Wird in _jspservive in out.print Methodenaufruf übernommen 14 javax.servlet.jsp.pagecontext _jspx_page_context = null; Wird automatisch bei Änderung von 15 try { Deklarationen <%!... %> Container in Servlet übersetzt und 16 response.setcontenttype("text/html"); 17 pagecontext = _jspxfactory.getpagecontext(this, request, Beliebiger response, Java Code, Methoden und Variablen Deklarationen automatisch deployed 18 null, true, 8192, true); 19 _jspx_page_context = pagecontext; Wird in die Servlet-Klasse übernommen Direktiven %> Nachrichten an den Servlet-Container Definition von Seiten-Attributen, inkludieren von Seiten,... 6 </body> 26 out.write("<head><title>hello World</title></head>\n"); Wird in die Datei der Servlet-Klasse außerhalb des Servlets übernommen 7 </html> 27 out.write("<body>\n"); Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / out.write("hallo Welt <br />\n"); 29 out.print( new java.util.date() ); Java Server Pages Java Server Pages 30 out.write("\n"); Scriptlet, Beispiel Ausdrücke, Beispiel 34 if (!(t instanceof javax.servlet.jsp.skippageexception)){ quadratzahlen.jsp 35 out = _jspx_out; 1 <html><body> Java Code innerhalb von <%... %> 361 <html><body> if (out!= null && out.getbuffersize()!= 0) Java Ausdruck innerhalb von <%=... %> 2 <h3> Quadratzahlen </h3> 372 <h3> Quadratzahlen try { out.clearbuffer(); </h3> } catch (java.io.ioexception e) {} 3 <table> Beliebiger Code, der innerhalb einer 38 if (_jspx_page_context!= null) _jspx_page_context.handlepageexception(t); 3 <table> Ein Java-Ausdruck der zu einem Wert 4 <tr><th>zahl</th><th>quadratzahl</th></tr> 39 Methode erlaubt ist 4 <tr><th>zahl</th><th>quadratzahl</th></tr> else throw new ServletException(t); evaluiert 5 <% 405 <% } 6 int wieviel = 9; Vordefinierte Variablen, viele, von 416 int} wieviel finally = { 9; Wird mit tostring() zu String 7 String p = request.getparameter("wieviel"); 427 _jspxfactory.releasepagecontext(_jspx_page_context); Servlet bekannt, spart Code String p = request.getparameter("wieviel"); 8 if (p!= null) { 43 } konvertiert, wenn notwendig 8 if (p!= null) { 9 wieviel = Integer.parseInt(p); PrintWriter out 449 } wieviel = Integer.parseInt(p); 10 } Korrekte Konvertierung von HttpServletRequest request } 11 for (int i=1; i <= wieviel; i+=1) { 11 for (int i=1; i <= wieviel; i+=1) { Grundtypen 12 %> HttpServletResponse response 12 out.print("<tr><td>"+i+"</td>"); 13 <tr><td><%= i %></td> ServletConfig config 13 out.print("<td>"+(i*i)+"</td></tr>"); Ausgabe mit out.print 14 <td><%= i*i %></td></tr> 14 } 15 <% } %> ServletContext application 15 %> Nutzen vordefinierter Variablen 16 </table> HttpSession session 16 </table> möglich 17 </body></html> 17 </body></html> hello.jsp <head><title>hello World</title></head> Hallo Welt <br /> out.write("</body>\n"); session = pagecontext.getsession(); _jspx_out = out; <body> <%= new java.util.date() %> out.write("</html>\n"); application = pagecontext.getservletcontext(); out = pagecontext.getout(); out.write("<html>\n"); 1 33 <html> } catch (java.lang.throwable t) { 21 config = pagecontext.getservletconfig(); Verwendung Markup kann im Editor erstellt und überprüft werden Wird meist zusammen mit Scriptlets verwendet Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

36 Java Server Pages Java Server Pages Deklaration, Beispiel Quadratzahlen Pager mit Session Java Deklaration innerhalb <%!... %> Beliebiger Methoden und Variablen Deklarationen Vordefinierte Variablen der Anfrage stehen natürlich nicht zur Verfügung Verwendung Deklaration spezifischer Methoden, Code Strukturierung Achtung: Instanzvariablen nicht zum Merken eines Session-Zustands verwenden Instanzvariable ist nur für Servlet-Instanz gültig, was keinem sinnvollen Scope entspricht 1 <%! 2 final static int DEFAULT_WIEVIEL = 9; 3 int getwieviel(httpservletrequest request) { 4 String p = request.getparameter("wieviel"); 5 if (p!= null) 6 return Integer.parseInt(p); 7 return DEFAULT_WIEVIEL; 8 } 9 %> 10 <html><body> 11 <h3> Quadratzahlen </h3> 12 <table> 13 <tr><th>zahl</th><th>quadratzahl</th></tr> 14 <% 15 for (int i=1; i <= getwieviel(request); i+=1) { 16 %> 17 <tr><td><%= i %></td> 18 <td><%= i*i %></td></tr> 19 <% } %> 20 </table> 21 </body></html> Sessioninhalte in Session Bei Neuladen die nächsten 9 Quadratzahlen Wie weit ist Session-spezifisch, in Session merken Nicht in den Instanzvariablen des Servlets merken session vordefiniert, einfach nutzen 1 <html><body> 2 <h3> Quadratzahlen </h3> 3 <table> 4 <tr><th>zahl</th><th>quadratzahl</th></tr> 5 <% 6 Integer akt = (Integer) session.getattribute("akt"); 7 akt = (akt == null)? 1 : akt; 8 for (int i=akt; i < akt+9; i+=1) { 9 %> 10 <tr><td><%= i %></td> 11 <td><%= i*i %></td></tr> 12 <% } 13 session.setattribute("akt", akt + 9); 14 %> 15 </table> 16 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Java Server Pages Java Server Pages Kommentare Kommentare innerhalb <% %> Beliebiger Text innerhalb des Kommentars Der Kommentar wird nicht im Markup generiert Verwendung Reduktion der Netzwerklast, kleinere Seite Keine potenziell kritischen Informationen übermitteln comment.jsp 1 <html> 2 <body> 3 <!-- HTML-Kommentar, sieht man im Markup --> 4 <%-- JSP-Kommentar, sieht man im Markup nicht --%> 5 Hallo HTML Welt <br /> 6 <% 7 out.println(" Hallo JSP Welt <br />"); // Java Kommentar 8 %> 9 </body> 10 </html> 1 <html> 2 <body> 3 <!-- HTML-Kommentar, sieht man im Markup --> 4 5 Hallo HTML Welt <br /> 6 Hallo JSP Welt <br /> 7 8 </body> 9 </html> Direktive, Beispiel Direktive innerhalb <directive> [<attr>="<value>"] %> Nachrichten an den Servlet-Container Verschiedene Direktiven <directive> Wichtigste Direktive: page Je nach Direktive verschiedene Attribut (<attr>) / Wert <value> Paare Attribut/Wert Paare von Direktive page, Beispiel UTF-8 einstellen language: zur Zeit nur java contenttype: HTTP-Header, darin charset-attribut für Browser pageencoding: Zeichensatz des Quelltexts der Seite Redundant im HTML-Quelltext UTF-8 Information an Browser 1 page language="java" 2 contenttype="text/html; charset=utf-8" 3 pageencoding="utf-8" 4 %><html> 5 </head> 6 <meta http-equiv="content-type" 7 content="text/html; charset=utf-8"> 8 <title> Insert title here </title> 9 <head> 10 <body> 11 <h3> Default Template </h3> 12 Dann klappt es auch mit XäöüßÄÖÜX im Markup 13 <%= new String("und mit XäöüßÄÖÜX im Code.") %> 14 </body> 15 </html> Alles UTF-8, alles gut Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

37 Java Server Pages Java Server Pages Weitere Attribute der Direktive page import Importieren von Paketen Wie import in Java errorpage Bei Fehler auf angegebene Seite weiterleiten iserrorpage Diese Seite ist eine Fehlerseite Neue vordefinierte Variable exception noch mehr Attribute session, default true buffer, default 8k autoflush, default true... 1 page import="java.util.*" 2 errorpage="fehler.jsp" 3 %><html> 4 <body> 5 <h3> Direktive </h3> 6 Es ist <%= new Date() %>. 7 <% 8 if (request.getparameter("bumm")!= null) { 9 throw new RuntimeException("bumm"); 10 } 11 %> 12 <br /><%= request.getquerystring() %> 13 </body></html> fehler.jsp 1 page iserrorpage="true" 2 %><html> 3 <body> 4 Uuuuups: <%= exception.getmessage() %> 5 <br /><%= request.getquerystring() %> 6 </body></html> Direktive, include Direktive include Inkludieren von anderen JSP-Fragmenten bei Übersetzung zu Servlet Deklarierte Methoden und Variablen können überall verwendet werden Effizient, nur ein Servlet wird erzeugt Automatisches Neukompilieren klappt eventuell nicht immer Quell-Code Abhängigkeiten müssen erkannt werden header.jsp 1 <head> 2 page language="java" 3 contenttype="text/html; charset=utf-8" 4 pageencoding="utf-8" 5 %></head> 6 <meta http-equiv="content-type" 7 content="text/html; charset=utf-8"> 8 <title> Allgemeiner Titel </title> 9 <head> 1 <html> 2 include file="header.jsp" %> 3 <body> 4 <h3> Hello </h3> 5 world. 6 include file="footer.jsp" %> 7 </body> 8 </html> footer.jsp 1 <p> <center> <strong> 2 <%= new java.util.date() %> 3 </strong> <center> </p> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Java Server Pages Java Server Pages Tag, <jsp:include> Tag <jsp:include> Tag mit besonderer Bedeutung bei der Verarbeitung auf dem Server Inkludieren von anderen JSP-Fragmenten Bei Ausführung, Übersetzung in unabhängige Servlets Deklarierte Methoden und Variablen nur in aktuellem Fragment Bei Aufruf werden Servlets aller inkludierten Fragmente angefragt Automatisches Neukompilieren klappt header.jsp 1 <head> 2 page language="java" 3 contenttype="text/html; charset=utf-8" 4 pageencoding="utf-8" 5 %></head> 6 <meta http-equiv="content-type" 7 content="text/html; charset=utf-8"> 8 <title> Allgemeiner Titel </title> 9 <head> 1 <html> 2 <jsp:include page="header.jsp" /> 3 <body> 4 <h3> Hello </h3> 5 world. 6 <jsp:include page="footer.jsp" /> 7 </body> 8 </html> footer.jsp 1 <p> <center> <strong> 2 <%= new java.util.date() %> 3 </strong> <center> </p> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JSP-Tags, Inkludieren und Weiterleiten Form <jsp:action...> Verschiedene action, zum Beispiel include Ein Tag-Bibliothek, unterschiedliches Verhalten auf dem Server <jsp:forward page="..."> Weiterleiten der Anfrage Parameter innerhalb include/forward <jsp:param name="name" value="wert"> Setzen von Parametern für inkludierte oder neue Seite Beispiel?weiter=jawohl Achtung: Einfache Anführungszeichen in HTML falls doppelte in Java verwendet werden jspforwardedto.jsp 1 page import="java.util.*" %> 2 <html><body> 3 Die Seite auf die weitergeleitet wurde. <br /> 4 <% 5 Map<String, String[]> params = 6 request.getparametermap(); 7 for (String key : params.keyset()) { 8 out.print(key + " = " + params.get(key)[0]); 9 out.println("<br />"); 10 } 11 %> 12 </body></html> 1 <html><body> 2 Die aufgerufene Seite. <br /> 3 <% if (request.getparameter("weiter")!= null) { %> 4 <jsp:forward page="jspforwardedto.jsp"> 5 <jsp:param name="neu" value="wert" /> 6 <jsp:param name= wl 7 value= <%= request.getparameter("weiter") %> /> 8 </jsp:forward> 9 <% } %> 10 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

38 Java Server Pages Java Server Pages Vordefinierte Variablen für Scopes ServletContext application request response Attr. forward HttpSession session Sessionattribut Instanzvariable* Servlet (aus JSP) Attribut Lebensdauer Anwendung ServletConfig config ServletContext Anfrage Session Servlet (JSP) Aktuelle Seite, pagecontext Aktuelle Seite Variable pagecontext Einstieg um auf alle anderen Scopes zuzugreifen Selten gebraucht Beispiel Alle Attribute in allen Scopes Zugriff per Methode auf vordefinierte Variablen 1 <html><body> 2 <h3> PageContext </h3> 1 <html><body> 2 <h3> Alle Attribute </h3> 3 <%= "request "+(request == pagecontext.getrequest()) %><br /> 4 <%= "response "+(response == pagecontext.getresponse()) %><br /> 5 <%= "page "+(this == pagecontext.getpage()) %><br /> 6 <%= "page "+(page == pagecontext.getpage()) %><br /> 7 <%= "session "+(session == pagecontext.getsession()) %><br /> 8 <%= "config "+(config == pagecontext.getservletconfig()) %><br /> 9 <%= "application "+(application == pagecontext.getservletcontext()) %><br /> 10 </body></html> 3 <% int scopes[] = { PageContext.PAGE_SCOPE, 4 PageContext.REQUEST_SCOPE, 5 PageContext.SESSION_SCOPE, 6 PageContext.APPLICATION_SCOPE }; 7 for (int scope : scopes) { 8 java.util.enumeration<string> e = 9 pagecontext.getattributenamesinscope(scope); 10 while (e.hasmoreelements()) { 11 String name = e.nextelement(); 12 out.print("scope "+scope+" "+name+" = "); 13 out.print(pagecontext.getattribute(name)+"<br />"); 14 } 15 } 16 %> 17 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Java Server Pages Java Server Pages Servlets und Java Server Pages Typische Aufgabenteilung JSP für die Präsentation, Darstellung der Daten und Abfragen Servlet als Controller Controller Servlet Meist ein zentrales Servlet, das alle Anfragen erhält, FrontController Aufgaben Beispiel Ablaufkontrolle, Seitenfolgesteuerung Pflegen von Daten, Zustand aktualisieren, persistente Änderungen Wenn noch nicht eingeloggt, einloggen > 20 rauf, sonst runter um 1, 3, 10 Drei JSP-Seiten plus ein Controller login.jsp POST rauf.jsp GET runter.jsp Controller Servlet forward Controller Servlet Anwendung Seitenfolgesteuerung Wenn nicht eingeloggt, login.jsp Wenn Wert > 20, runter.jsp Sonst, rauf.jsp Umsetzung Update Session Zustand forward dopost gleich Controller.java 1 protected void doget(httpservletrequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 HttpSession session = request.getsession(); 4 if (request.getparameter("login")!= null) 5 session.setattribute("login", request.getparameter("login")); 6 if (session.getattribute("login") == null) { 7 RequestDispatcher rd = request.getrequestdispatcher("/login.jsp"); 8 rd.forward(request, response); 9 return; 10 } 11 if (session.getattribute("zaehler") == null) 12 session.setattribute("zaehler", 0); 13 if (request.getparameter("diff")!= null) { 14 int diff = Integer.parseInt(request.getParameter("diff")); 15 int z = ((Integer) session.getattribute("zaehler")) + diff; 16 session.setattribute("zaehler", z); 17 } 18 int zaehler = (Integer) session.getattribute("zaehler"); 19 if (zaehler > 20) { 20 RequestDispatcher rd = request.getrequestdispatcher("/runter.jsp"); 21 rd.forward(request, response); 22 } else { 23 RequestDispatcher rd = request.getrequestdispatcher("/rauf.jsp"); 24 rd.forward(request, response); 25 } 26 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

39 Java Server Pages JavaBeans JSP Seiten Anfragen auf Servlet leiten Alle Verweise auf Servlet Konfiguration von ctrl auf Servlet Controller notwendig Direkter Zugriff auf JSP (leider) noch möglich, vermeiden Wenig Scriptlet-Code Gut Nichts in login.jsp Ausschließlich Ausgaben in rauf.jsp und runter.jsp Zugriff auf Attribute, Manipulation der Attribute nur durch Servlet login.jsp 1 <html><body> 2 <form action="ctrl" method="post"> 3 User: <input type="text" name="login" /> 4 <input type="submit" name="ok" value="login" /> 5 </form> 6 </body></html> rauf.jsp 1 <html><body> 2 Hallo <%= session.getattribute("login") %> <br /> 3 Der Wert ist <%= session.getattribute("zaehler") %> <br /> 4 Es geht 5 <a href="ctrl?diff=1" >eins</a>, 6 <a href="ctrl?diff=3" >drei</a>, oder 7 <a href="ctrl?diff=10" >zehn</a> rauf. 8 </body></html> runter.jsp 1 <html><body> 2 Hallo <%= session.getattribute("login") %> <br /> 3 Der Wert ist <%= session.getattribute("zaehler") %> <br /> 4 Es geht 5 <a href="ctrl?diff=-1" >eins</a>, 6 <a href="ctrl?diff=-3" >drei</a>, oder 7 <a href="ctrl?diff=-10" >zehn</a> runter. 8 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JavaBeans Komponentenmodell für Java Ursprünglich für GUI-Komponenten entworfen Heute eine beliebige Java-Klasse, die Konventionen gehorcht Einsatz als Abstraktionsschicht für Logik und Datenzugriff JavaBean-Konventionen Parameterloser Konstruktor, einfach erzeugbar Zugriff auf Eigenschaften (Properties) mit Getter und Setter Methoden Eigenschaft nach Java-Namenskonvention, beginnt mit Kleinbuchstaben Zugriff/Änderung durch Voranstellen von get/set vor Eigenschaftsname und erster Buchstabe der Eigenschaft groß geschrieben Instanzen sind serialisierbar, Persistenz Implementieren die Schnittstelle java.io.serializable Stark empfohlen: Einsatz in einem Paket Gewähltes Komponentenmodell für JSP Unterstützung in JSP für JavaBeans Einfache Verwendung, einfache Syntax, Tool-Unterstützung Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JavaBeans JavaBeans Beispiel-Anwendung mit Bean Beispiel Bean NameBean Bean mit Daten einer Person Getter und Setter Überprüfung ob Daten ok Formularseite mit Eingabefelder für Daten Auf der Seite bleiben bis alles ok Fehlerseite bei Typfehler Abschließende Ausgabeseite Typfehler ungültig alles ok Bean Parameterloser Konstruktor, sinnvolle Default-Werte Getter und Setter Setter mit Logik möglich, vermeiden Zusätzliche Convenience Getter Logik 1 public class NameBean implements Serializable { 2 String vorname; String nachname; 3 String mittelname; int alter; 4 public NameBean() { // parameterloser Konstruktor 5 vorname = "Max"; mittelname="m."; 6 nachname = "Mustermann"; alter = 0; 7 } 8 public String getvorname() { return vorname; } 9 public void setvorname(string vorname) { this.vorname = vorname; } 10 public String getmittelname() { return mittelname; } 11 public void setmittelname(string mittelname) { this.mittelname = mittelname; } 12 public String getnachname() { return nachname; } 13 public void setnachname(string nachname) { this.nachname = nachname; } 14 public int getalter() { return alter; } 15 public void setalter(int alter) { this.alter = alter<0? 0 : alter; } 16 public String getname() { // Convenience, lesend 17 return vorname+" "+mittelname+" "+nachname; 18 } 19 public boolean gueltig() { // Logik 20 return alter > 0 && 21 (vorname+mittelname+nachname).length() >= 4; 22 } 23 } Erzeugte class-datei unter WEB-INF/classes mit Pakethierachie Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

40 JavaBeans JavaBeans JavaBeans und JSP Beispiel Formular, Header, Fehler <jsp:usebean>: Bean-Instanz in JSP-Seite verfügbar id: Der Variablenname der Bean class: Die Klasse mit Paketangabe aus der die Instanz wenn notwendig erzeugt wird type: Alternativ zu class, gibt Instanz anderen Typ (Ober-/Unter-klasse), ohne class wird die Instanz nicht erzeugt sondern muss schon existieren scope: Lebensdauer der Bean (page, request, session, application) <jsp:getproperty>: Property-Zugriff, als String name: Variablenname, wie unter id vergeben property: Name der Eigenschaft <jsp:setproperty>: Property setzen name, property (wie getproperty) value: Zu setzender Wert 1 <jsp:usebean 2 id="nb" 3 class="webanw.namebean" 4 scope="session" /> <jsp:getproperty 10 name="nb" 11 property="vorname" /> <%= 14 nb.getvorname().tostring() 15 %> <jsp:setproperty 21 name="nb" 22 property="vorname" 23 value="max" /> <% 26 nb.setvorname("max"); 27 %> Zeile 3: NameBean unter nb verfügbar machen Komische Formatierung? Keine Leerzeichen an Browser schicken Fehlerbehandlung bei Typkonversion Manuell Ausnahme fangen und aussagekräftigere (anwendungsbezogen) werfen Weiterleiten auf deklarierte Fehlerseite automatisch 1 page language="java" contenttype="text/html; charset=utf-8" 2 pageencoding="utf-8" errorpage="namebeanerror.jsp" 3 %><jsp:usebean id="nb" class="webanw.namebean" scope="session"/><% 4 if (request.getparameter("ok")!= null) { 5 if (request.getparameter("alter")!= null) { 6 try { 7 Integer.valueOf(request.getParameter("alter")); 8 } catch (NumberFormatException e) { 9 throw new RuntimeException("alter sollte eine Zahl sein " + 10 " und nicht " + request.getparameter("alter")); 11 } 12 } 13 %> namebeanerror.jsp 1 page language="java" contenttype="text/html; charset=utf-8" 2 pageencoding="utf-8" iserrorpage="true" %> 3 <html><head><title>fehler-seite</title></head> 4 <body><h3> Fehler </h3> 5 Hey, pass besser auf: <br /> 6 <%= exception.getmessage() %> <br /> 7 <%--for (StackTraceElement ste : exception.getstacktrace()) { 8 out.println(ste); } 9 --%> <br /> 10 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JavaBeans JavaBeans Beispiel Formular, Verarbeitung setproperty, Übernahme aus Formular Mit value hantieren ist unangenehm Übernahme mit param, optional wenn Parameter-/Eigenschafts-name gleich Automatische Typkonversion von String nach Grundtypen/Wrapper 1 <jsp:setproperty name="nb" property="vorname" value= <%= request.getparameter("vorname") %> /> 2 <jsp:setproperty name="nb" property="mittelname" param="mittelname"/> 3 <jsp:setproperty name="nb" property="nachname"/> 4 <jsp:setproperty name="nb" property="alter" param="alter"/> 5 <% } if (nb.gueltig()) { 6 %><jsp:forward page="namebeanok.jsp" /><% } %><html> 7 <head><title>namebean Eingabe</title></head><body> 8 Hallo <jsp:getproperty name="nb" property="name"/>, 9 <form method="post"> 10 <table><tr><td>vorname</td><td> 11 <input type="text" name="vorname" value="<jsp:getproperty name="nb" property="vorname"/>"> 12 </td></tr> Ausgabe ab Ende Zeile 6, vorher Verarbeitung Eingabe/neuer Zustand Zeile 11: Nach JSP-Verarbeitung ist das wieder ein String Falls Parametername gleich Eigenschaftsname: <jsp:setproperty name="nb"property="*"/> Beispiel, Ausgabe Ausgabe Zeile 3: Zur Verfügung stellen von Namebean unter Name nb Es wird Whitespace an Browser ausgegeben Nur ausgeben von Daten namebeanok.jsp 1 page language="java" contenttype="text/html; charset=utf-8" 2 pageencoding="utf-8"%> 3 <jsp:usebean id="nb" class="webanw.namebean" scope="session"/> 4 <html><head><title>name Bean OK</title></head><body> 5 Hallo <jsp:getproperty name="nb" property="name"/>. <br /> 6 Sie sind 7 <jsp:getproperty name="nb" property="alter"/> 8 Jahre alt. <br /> 9 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

41 Expression Language Expression Language Expression Language Motivation Problem mit Scriptlets Selbst einfache Ausdrücke nur mit Scriptlets möglich, zum Beispiel Addition Fehlende vordefinierte Variablen, zum Beispiel Cookies Komplexe Formulierung, zum Beispiel Zugriff auf Properties Ziel Vermeiden von Scriptlets Wichtige Variablen vordefiniert Einfache Ausdrücke Lösung: Expression Language 1 <h3> Ohne Expression Language </h3> 2 <%= %> <br /> 3 <%= ((Cookie) request.getcookies()[0]).getvalue() %> 4 <br /> 5 <jsp:getproperty name="nb" property="vorname" /> 6 <jsp:getproperty name="nb" property="nachname" /> 1 <h3> Mit Expression Language </h3> 2 ${ }<br /> 3 ${cookie.jsessionid.value}<br /> 4 ${nb.vorname} ${nb.nachname} Syntax und Operationen Spezielle Ausdrücke ${<expr>} Werden an aktueller Stelle im Text ersetzt 1 Syntax: Ausdruck <expr> zwischen ${ und } Unterstützung für Literale: Zahlen, Boolesche Werte, String, null Operatoren Arithmetische Operationen : +, -, *, /, div, %, mod Vergleichsoperationen : ==,eq,!=,ne, <,lt, >,gt, <=,le, >=,ge Test ob leer (wahr bei null und leerem String, Array, Map, Collection) : empty Funktionsaufruf (taglib) : <func>(<args>) Konditionaler Ausdruck : <expr>? <wert-true> : <wert-false> Gruppieren von Ausdrücken : () Zugriff Feld, Liste : [<index>] Zugriff Map, Bean-Eigenschaft :.<key/propertyname> 1 Wir sehen später, dass man besser <c:cout value="${<expr>}"/> verwenden sollte Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Expression Language Expression Language Operatoren, Beispiele Beans Stehen nach usebean zur Verfügung Feldzugriff Bean gibt String[] mit Maps getstringarray() zurück Dot-Notation cookie ist Map von String (Name) nach Cookie <jsp:usebean id="t" class="webanw.testbean"/> Cookie hat Methode getvalue() cookie ist eine Map, cookies ein Array Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Vordefinierte Variablen, Maps Maps, Kollektionen Variablen des jeweiligen Scopes : pagescope, requestscope, sessionscope, applicationscope Anfrage-Parameter, Wert ein String : param Anfrage-Parameter, Wert String-Array (bei : paramvalues mehreren je Schlüssel sinnvoll) Anfrage-Header (HTTP) : header, headervalues Map von Cookies : cookies Initialisierungsparameter Anwendung, : initparam Wert ein String Seitenkontext Zum Zugriff auf alle anderen Werte Zugriff auf Maps Dot-Notation Alternativ mit [], muss bei Sonderzeichen (zum Beispiel - im Propertynamen) verwendet werden pagecontext ${cookie.jsessionid.value} ${cookie[ JSESSIONID ][ value ]} Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

42 Standard Tag Library (JSTL) Standard Tag Library (JSTL) Standard Tag Library (JSTL) JSTL Einbinden Standard JSP Tags Vordefinierte Tags, spezielle Bedeutung Fester Namensraum (jsp) mit Tags (usebean) Custom Tags, Custom Tag Library Tags selbst entwickeln, Scriplets vermeiden (Anwendungs-)Java-Code statt Tags ausführen Java Standard Tag Library (JSTL) Häufig gebrauchte Tags, vereinheitlicht JSTL Spez. für JSP 2.2/Servlet 3.0 (auch Tomcat 8) Core (c), XML-Processing (x), I18N-Formatierung (fmt), Datenbanken (sql), Funktionen (fn) Wichtigster Teil Core Ausgabe, Verzweigung, Schleifen, URL-Manipulation, Importieren,... Implementierung nicht Teil des Servlet-Containers <jsp:usebean /> id="nb" class= "webanw.namebean" <c:foreach var="v" items="${header}" > <c:out value= /> "${v.key}=${v.value}" </c:foreach> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JSTL Implementierung JAR-Dateien, javax.servlet.jsp.* jstl jar, jstl-api jar Zielordner Web-Anwendung WEB-INF/lib Auch in Eclipse an diese Stelle (unterhalb WebContent) Wird von selbst sichtbar in Web App Libraries Verwenden mit taglib-direktive uri: Identifikation Tag-Library prefix: Namensraum für Tags Danach mit Präfix (c) verwenden taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <c:out value="hallo"/> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Standard Tag Library (JSTL) Standard Tag Library (JSTL) JSTL Core, <c:out> Tag <c:out> Ausgabe Wert an aktueller Stelle Attribute value: Auszugebender Wert, muss escapexml: Sonderzeichen konvertieren, Vorgabe "true" default: Falls value==null, kann auch Body des Tags sein Beispiel Ausgabe von Text mit Tags Expression Language in Tags verwenden jsp 1 taglib prefix = "c" 2 uri="http://java.sun.com/jsp/jstl/core" 3 %><html><body> 4 <c:out value="hallo Welt" /><br /> 5 <c:out value="<c:out>" /><br /> 6 <c:out value="<c:out>" escapexml="false" /><br /> 7 <c:out value="${cookie.jsessionid.value}" /><br /> 8 <c:out value="${request.bla}"> 9 bla-parameter nicht definiert. 10 </c:out></body></html> html 1 <html><body> 2 Hallo Welt<br /> 3 <c:out><br /> 4 <c:out><br /> 5 <br /> 6 bla-parameter nicht definiert.</body></html> JSTL Core, <c:set> Tag <c:set> Setzen von Attributen von Maps, Beans Attribute var: Variablenname value: Wert scope: Gültigkeitsbereich (page, request, session, application) target: Zielobjekt, Map oder Bean property: Schlüssel oder Eigenschaft Tag <c:remove> möglich 1 <c:set var="i" value="1" /> 2 <c:out value="i=${i}" /><br /> 3 <c:set var="text" value="hallo Welt" scope="page" /> 4 <c:out value="text=${text}" /><br /> 5 <!-- t ist eine Bean --> 6 <c:set target="${t}" property="name" value="hallo Welt" /> 7 <c:out value="text=${t.name}" /><br /> 8 <!-- t.getmapstring() liefert Map<String, Object> --> 9 <c:set var="a" value="${t.mapstring}" scope="page" /> 10 <c:set target="${a}" property="foo" value ="bar" /> 11 <c:out value="a.foo=${a.foo}" /><br /> 12 <!-- bei Sonderzeichen wären [] notwendig --> 13 <c:out value="a[ foo ]=${a[ foo ]}" /><br /> 14 <c:out value="a[3]=${a[ 3 ]}" /><br /> 15 <c:set target="${a}" property="3" value="42" /> 16 <c:out value="a[3]=${a[ 3 ]}" /> 17 <c:remove var="text" scope="page"/> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

43 Standard Tag Library (JSTL) Standard Tag Library (JSTL) JSTL Core, <c:foreach> JSTL Core, <c:foreach>, Statusvariable Tag <c:foreach> (Erweiterte) for-schleife Verschachteln erlaubt Attribute items: Iterierbares Objekt (Collection, Iterator, Enumeration, Map, Object[], int[],... var: Name der Laufvariable, der Elemente aus items zugewiesen werden Keine Expression Language erlaubt begin, end, step: Alternative, klassische for-schleife 1 <c:foreach var="var" items="${header}"> 2 <c:out value="${var.key} = ${var.value}" /><br /> 3 </c:foreach> 4 <c:foreach var="var" items="${headervalues}"> 5 <c:foreach var="val" items="${var.value}"> 6 <c:out value="${var.key} = ${val}" /><br /> 7 </c:foreach> 8 </c:foreach> 9 <c:foreach var="i" begin="1" end="4"> 10 <c:out value="${i}*${i} = ${i*i}" /><br /> 11 </c:foreach> Zusatzinformationen Optionales Attribut varstatus Typ LoopTagStatus Eigenschaften der Statusvariablen begin, end, step: Wie angegeben oder null first, last: Boolesch, am ersten, letzten? count: Das wievielte current: Aktuelles Element index: Aktueller Index 1 <c:foreach var="i" begin="1" end="10" step="3" 2 varstatus="stat"> 3 <c:out value="${i}=${stat.current}" /> 4 <c:out value="schleife von ${stat.begin} bis" /> 5 <c:out value=" ${stat.end} step ${stat.step}" /> 6 <c:out value=" first=${stat.first} last=${stat.last}" /> 7 <c:out value=" count=${stat.count} index=${stat.index}" /> 8 <br /> 9 </c:foreach> 10 <c:foreach var="prim" items="${t.intarray}" 11 varstatus="stat"> 12 <c:out value="${stat.index}: ${prim}" /> 13 </c:foreach> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Standard Tag Library (JSTL) Standard Tag Library (JSTL) JSTL Core, <c:if> Tag <c:if> Verzweigung Kein else Attribute test: Ausdruck, der zu true oder false evaluiert var: Variablenname der neuen Booleschen Variable mit Ergebnis des Tests, optional scope: Scope für die neue Variable aus var Alternative <c:choose>, wie switch <c:when>: test-attribut, wie case mit break <c:otherwise>: wie default 1 <c:if test="${t.name eq TestBean }"> 2 Name Property der TestBean ist noch TestBean 3 </c:if><br /> 4 <c:if test="${t.name ne TestBean }"> 5 Name Property der TestBean ist 6 <c:out value="${t.name}" /> 7 </c:if><br /> 8 <c:set target="${t}" property="name" 9 value="hello World" /> 10 <c:if test="${t.name ne Hallo Welt }"> 11 Name Property der TestBean ist 12 <c:out value="${t.name}" /> 13 </c:if><br /> Weitere Standard Tags Auszug <c:fortoken var="v" items="a,b,c" delims=",">...: Einfache for-schleife, wie for v in [ a, b, c ] <c:catch var="exception"/>: Ausnahme fangen <c:import url="http://www.mi.hs-rm.de/portal" />: Inkludieren von Inhalten, wie <jsp:include />, aber auch externe Ressourcen möglich <c:redirect url="http://www.mi.hs-rm.de" />: Redirect über Browser <c:url value="http://www.mi.hs-rm.de" />: Ausgabe einer URL, passende Konvertierung der Zeichen <c:param name="arg1" value="val1" />: Innerhalb von <c:import>, <c:redirect>, <c:url>; zum Anhängen von GET-Parametern Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

44 Standard Tag Library (JSTL) i18n, l10n JSTL Funktionen für Expression Language Internationalisierung, Lokalisierung 1 taglib prefix = "c" 2 uri="http://java.sun.com/jsp/jstl/core" %> 3 taglib prefix = "fn" 4 uri="http://java.sun.com/jsp/jstl/functions" %> 5 <c:if test="${fn:contains(header[ User-Agent ], MSIE )}"> 6 Ieee, IE. 7 </c:if> 8 <c:if test="${fn:containsignorecase(header[ User-Agent ], firefox )}"> 9 Aaaa, Firefox. 10 </c:if><br /> 11 <c:if test="${fn:endswith(header.referer, jstl/ )}"> 12 jstl/ am Ende beim referer 13 <c:out value="${header.referer}" /> 14 </c:if> Funktionen (functions) Verwendung durch separate taglib-deklaration, URL Üblicher Präfix, fn Einsatz innerhalb von EL Meist zusammen mit Core verwendet, meist in Attributen Convenience-Funktionen +escapexml, indexof, join, length, replace, split, startswith, substring, substringafter, substringbefore, tolowercase, touppercase, trim weitgehend selbsterklärend, Doku Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 internationalization (i18n), localization (l10n) Abkürzung, 18/10 Buchstaben ersetzt Internationalisierung Anwendung so entwickeln, dass sie international eingesetzt werden kann Vorbereiten/Ermöglichen der Lokalisierung, zum Beispiel Verwenden von Schlüssel/Wert-Paaren für die Verwaltung der Texte Lokalisierung Anwendung an lokale Gegebenheiten anpassen Übersetzung der Texte, zum Beispiel Menüs, Label,... Formatierungskonventionen Zahldarstellung: ,00 oder 100, Maßeinheiten: Euro oder Dollar, Meter oder Inch Zeit: 13:00 oder 1:00 pm Datumsangaben: 6/1/2014 oder , Januar oder Jänner Passender Zeichensatz Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 i18n, l10n i18n, l10n und i18n/l10n Auswahl Lokalisierung mit Locale Auswahl der Sprache und Formatierung Web-Browser, Accept-Language Locale: Java-Klasse für Sprache/Länder Locale Repräsentation welche Sprache und welche Region Nutzen der passenden Sprache Ressource-Dateien Schlüssel/Wert-Paare für Übersetzungen Nutzen der passenden Texte und Formate Tag <fmt:...> der JSTL Für Formatierungen Für Textauswahl in richtiger Sprache Alternative Aufspaltung in verschiedene Seiten je Sprache/Region Sehr aufwendig, meist Ergebnis von sinnlosem Copy & Paste Vermeiden HTTP-Header Komma-separierte Liste aus Sprachkürzel (RFC 3066), de für Deutsch, en für Englisch Sprach-/Länderkürzel (RFC 1766), de-de für Deutschland, de-ch für Schweiz Optional Gewichtung mit ; 1 public class LocaleServlet extends HttpServlet { 3 public void doget(httpservletrequest request, 4 HttpServletResponse response) 5 throws ServletException, IOException { 6 Locale locale = request.getlocale(); 7 PrintWriter out = response.getwriter(); 8 out.println("<html><body>"); 9 out.print("sprache: "); 10 out.print(locale.getdisplaylanguage() + "<br />"); 11 out.println("spracheinstellungen Browser: <ul>"); 12 Enumeration<Locale> e = request.getlocales(); 13 while (e.hasmoreelements()) { 14 locale = e.nextelement(); 15 out.println("<li>"+locale+"</li>"); 16 } 17 out.println("</ul>\naccept-language:"); 18 out.println(request.getheader("accept-language")); 19 out.println("</body></html>"); 20 } 21 } Dokumentation lesen, große Teile schon in JavaSE Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

45 i18n, l10n i18n, l10n Ressourcedateien Verwendung von Ressourcedateien mit <fmt:...> Ressourcedateien auf dem Server Festes Namensschema <name>_<sprache>_<land>_<variante>.properties Alles außer name optional Inhalt sind ASCII Schlüssel/Wert- Paare, Unicode Escape erlaubt (native2ascii) Ablage unterhalb WEB-INF/classes In Paketstruktur, JavaSE Klasse java.util.resourcebundle Repräsentation Dateiinhalt in Java Siehe Dokumentation für Methoden Nicht mit JSP, geht da einfacher Suchreihenfolge Alles passt genau Dann alles außer Variante,... Property-Dateien für texte Zwei Schlüssel, hello und ciao Unterhalb von Paket webanw mitparam.properties texte_de_ch.properties texte_de.properties texte_en.properties texte.properties texte.properties, texte_en.properties 1 hello=hello 2 ciao=bye texte_de.properties 1 hello=hallo 2 ciao=tsch\u00fc\u00df texte_de_ch.properties 1 hello=gr\u00fcezi 2 ciao=auf Wiederlurge Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Verwenden mit <fmt:...> Einbinden mit taglib Nutzen mit message Ressourcebundle wählen Default ist Browser-Locale Manuell mit <fmt:setbundle> und Attribut basename, vollqualifizierter Name Gültig für die ganze Seite Gültigkeit für Bereich mit <fmt:bundle></..> Text-Ausgaben 1 taglib prefix="fmt" 2 uri="http://java.sun.com/jsp/jstl/fmt" %> 3 <html><body> 4 <fmt:bundle basename="webanw.texte"> 5 <fmt:message key="hello" /><br /> 6 <fmt:message key="ciao" /><br /> 7 </fmt:bundle> 8 <fmt:setbundle basename="webanw.texte" /> 9 <fmt:message key="hello" /> + 10 <fmt:message key="ciao" /><br /> 11 <fmt:setlocale value="de_ch" /> 12 <fmt:setbundle basename="webanw.texte" /> 13 <fmt:message key="hello" var="start"/> 14 <fmt:message key="ciao" var="stop" /> 15 ${start} + ${stop} <br /> 16 </body></html> <fmt:message> Attribute key und optional bundle Attribut var, in Variable statt Seite Im Eclipse-Editor werden Ressourcedateien automatisch konvertiert (keine Unicode-Escapes notwendig) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 i18n, l10n i18n, l10n Ressourcen und Formatierungsparameter Formatierung für Länder, Regionen und Zeitzonen Problem: fixe Texte Schlüssel/Wert Paare geht nur für feste Textfragmente Parametrisierte Texte, wie zum Beispiel ein personalisierter Gruß, ist nicht darstellbar 1 hello=hallo 2 ciao=ciao 3 pershello=hi {0}, wie geht s? 1 <c:set var="name" value="susi" /> 2 <fmt:message key="pershello"> 3 <fmt:param value="${name}" /> 4 </fmt:message> Formatierungen spezifisch für eine Region Zeit- und Datumsangaben, Aussehen und Werte Zahldarstellung Beispiel 2, $, 4/1/2014 versus 1.435,00 e, Greenwich Mean Time (GMT) versus Universal Time Coordinated (UTC) Wiesbaden: GMT+1 Lösung: Parameter Parameter in Texten in Ressourcendateien {n}, Zahlen n ab 0 für zu ersetzende Stellen Parameterübergabe bei Verwenden von <fmt:message> Währungsdarstellung und Geldbeträge <fmt:param value="<wert>"/> Reihenfolge bestimmt Verwendung als 0tes, 1tes, 2tes,... Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

46 i18n, l10n i18n, l10n Datums- und Zeitangaben Datum und Zeit Wie in Java Tag fmt:formatdate, Attribute value: Ein Date-Objekt type: date oder time datestyle/timestyle: vordefinierter Stil pattern: spezifisches Ausgabepattern timezone: statt aktueller Zeitzone java.util.timezone (.getavailableids()) var: Ausgabe in eine Variable 1 <c:set var="jetzt" 2 value="<%= new java.util.date() %>" /> 3 <c:fortokens var="stil" 4 items="default,short,medium,long" delims=","> 5 <c:out value="${stil}" />: 6 <fmt:formatdate value="${jetzt}" type="date" 7 datestyle="${stil}" /> 8 <fmt:formatdate value="${jetzt}" type="time" 9 datestyle="${stil}" /><br /> 10 </c:fortokens> 11 US-Datum: 12 <fmt:formatdate value="${jetzt}" type="date" 13 pattern="mm/dd/yyyy" /><br /> 14 In New York ist es jetzt 15 <fmt:formatdate value="${jetzt}" type="date" 16 pattern="hh:mm:ss a" 17 timezone="america/new_york" /> Zahlen und Geldbeträge Siehe Beispiel value immer US-Stil ohne Gruppierung, wie in Programmiersprachen Default Einstellungen nach Locale currencycode nach ISO-4217 Tag fmt:parsenumber analog 1 <fmt:formatnumber value=" "/><br /> 2 <fmt:formatnumber value=" " maxfractiondigits="1"/><br /> 3 <fmt:formatnumber value=" " maxintegerdigits="3"/><br /> 4 <fmt:formatnumber value=" " groupingused="false"/><br /> 5 <fmt:formatnumber value=" " minfractiondigits="5"/><br /> 6 <fmt:formatnumber value=" " pattern="###.#####"/><br /> 7 <fmt:formatnumber value=" " pattern="###.00000"/><br /> 8 <fmt:formatnumber value=" " type="number"/><br /> 9 <fmt:formatnumber value="0.1234" type="percent"/><br /> 10 <fmt:formatnumber value="0.1234" type="percent" minfractiondigits="2"/><br /> 11 <fmt:formatnumber value=" " type="currency"/><br /> 12 <fmt:formatnumber value=" " type="currency" currencycode="usd"/><br /> 13 <fmt:formatnumber value=" " type="currency" currencysymbol="$"/><br /> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 i18n, l10n Custom Tags Zeichensätze Zeichensätze, Character Encoding Vorgabe ist ISO (Western-European), latin-1 Standard in HTTP (Das Web kommt von den Europäern ;-) Alternative: UTF-8, präferiert UTF-8 Spezieller kompakter Unicode, wenn möglich nur 8 Bit Im Gegensatz zu latin-1 sind nicht alle Zeichen nur 8 Bit groß, wie zum Beispiel die deutschen Umlaute In Java wird Unicode verwendet, allerdings nicht unbedingt UTF-8 Vorteil von UTF-8: (Fast) alle Zeichen darstellbar Was verwenden? Empfehlung? UTF-8 An der Hochschule UTF-8, LANG=de_DE.UTF8, in der Shell echo $LANG Ist Vorgabe in Eclipse-Template Alle Browser können es, meist keine Problem Nie Nie Nie Nie Nie MacRoman oder cp1252 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Custom Tags Problem Gleichartige Teile Darstellung von Teilen häufig gleich(artig) auf verschiedenen Seiten Kopieren jeweiliger JSP Code-Blöcke Bei Änderungen alle Kopien ändern Makro -Feature notwendig Lösungsansatz Custom Tags JSP-Fragmente wiederverwenden Benutzen als eigene (custom) Tags Tag-Dateien: JSP-Fragmente plus Syntax Je Custom Tag separate Datei unter WEB-INF/tags oder Unterordner Tag-Klassen: Java-Code Java-Klassen, erben von CustomTag Bereitstellung über web.xml 1 <center> 2 Copyleft 3 <jsp:usebean id="jetzt" 4 class="java.util.date" scope="session" 5 /><fmt:formatdate var="year" value="${jetzt}" 6 pattern="yyyy" 7 /><c:out value="${year}" /> 8 </center> <center> Copyleft 2015 </center> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

47 Custom Tags Custom Tags Copyleft Tag als Tag-Datei Tag-Datei Ablageort WEB-INF/tags/copyleft.tag Direktive tag, keinen Body (viele Tags haben keinen Body) Verwendung Direktive taglib, Angabe von Verzeichnis mit tagdir, immer WEB-INF/tags verwenden Eigenes Tag, ersetzt durch Inhalt Tag-Datei Eclipse-Unterstützung nicht umfassend copyleft.tag 1 tag body-content="empty" %> 2 <jsp:usebean id="jetzt" 3 class="java.util.date" scope="session" /> 4 taglib prefix="c" 5 uri="http://java.sun.com/jsp/jstl/core" %> 6 taglib prefix="fmt" 7 uri="http://java.sun.com/jsp/jstl/fmt" %> 8 <fmt:setlocale value="de_de" /> <!-- don t ask --> 9 <center> 10 Copyleft 11 <fmt:formatdate var="year" value="${jetzt}" 12 pattern="yyyy" 13 /><c:out value="${year}" /> 14 </center> usecopyleft.jsp 1 taglib prefix="my" tagdir="/web-inf/tags" %> 2 <html><body> 3 <my:copyleft /> 4 </body></html> Tag-Dateien Ablage Datei mit Endung.tag, unter /WEB-INF/tags Unterordner für separate Tag-Bibliotheken ok Können in JAR-Dateien verpackt werden Definieren mit Tag-Direktive empty: Kein Body im Tag erlaubt /WEB-INF/tags/...tag tag body-content="..."%> scriptless: Keine Scriptlets erlaubt (default), aber sonst alles (Direktiven, Tag-Libraries, JSTL, EL) tag-dependant: Text bleibt wie er ist (keine Direktiven, keine JSTL, kein EL) Verwenden In beliebiger JSP-Datei mit Taglib-Direktive taglib prefix="my"tagdir="/web-inf/tags"%> Beliebiger Präfix, Überschneidung mit JSTL vermeiden Pfad, eventuell mit Unterordner, zur Ablage Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Custom Tags Custom Tags Attribute in Custom Tags, Beispiel Konfigurierbares Bild Ein Bild über eine URL einbinden, Muss-Attribut Visualisierung mit Titel im Template/Tag Angabe des Titels als Attribut, wenn nicht angegeben, dann??? Verwendung 1 taglib prefix="c" 2 uri="http://java.sun.com/jsp/jstl/core" 3 taglib prefix="my" tagdir="/web-inf/tags" 4 %><html><body> 5 <c:url var="url" value="/images/rabbit.png" /> 6 Mit Titel <br /> 7 <my:image url="${url}" title="ein Hase" /> 8 Ohne Titel <br /> 9 <my:image url="${url}" /> 10 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Attribute in Custom Tags, Beispiel, Tag-Datei Attribute Eine Direktive je Attribut Nach der Tag-Direktive Attribut-Direktive attribute name="..." required="..." %> name: Der Bezeichner des Attributs required: true oder false, bei true Fehler, falls Attribut bei Verwendung nicht angegeben wird Lebenszeit der Attribute Wird der Variablen von name zugewiesen PageScope, aber nur innerhalb der Tag-Datei, eigentlich TagScope image.tag, Bilder Beispiel 1 tag body-content="empty" %> 2 attribute name="url" required="true" %> 3 attribute name="title" required="false" %> 4 taglib prefix="c" 5 uri="http://java.sun.com/jsp/jstl/core" %> 6 <table> 7 <tr><td><img alt="${title}" src="${url}"> 8 </td></tr><tr><td align="center"> 9 <c:out value="${not empty title? title :??? }" 10 /></td></tr> 11 </table> Kann in Expression Language verwendet werden Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

48 Custom Tags Custom Tags Nicht deklarierte Attribute verwenden Nicht deklarierte Attribute Attribute, die nicht per Direktive angegeben wurden Erlauben mit neuem Attribut Tag-Direktive, dynamic-attributes dynamic-attributes: Variablenname, Map in der alle weiteren Attribute gesammelt werden Explizite Attribute zusätzlich erlaubt, erscheinen nicht in Map Beispiel Alle Attribute mit Namen und Wert ausgeben dynatts.tag 1 tag body-content="empty" 2 dynamic-attributes="attrs"%> 3 taglib prefix="c" 4 uri="http://java.sun.com/jsp/jstl/core" %> 5 <c:foreach var="attr" items="${attrs}"> 6 <c:out value="${attr.key}=${attr.value}" /><br /> 7 </c:foreach> 1 taglib prefix="my" tagdir="/web-inf/tags" %> 2 <html><body> 3 <my:dynatts hallo="hallo" var="wert" foo="bar" /> 4 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Tag Body verarbeiten, jsp:dobody Tag Body verarbeiten In Tag-Direktive erlauben tag body-content="scriptless" %> Body auslesen mit jsp:dobody Beispiel var: Body des Tags in eine Variable varreader: Alternativ als Eingabestrom Mini Wiki Darstellung von Code codeformat.tag 1 tag body-content="scriptless" %> 2 taglib prefix="c" 3 uri="http://java.sun.com/jsp/jstl/core" %> 4 taglib prefix="fn" 5 uri="http://java.sun.com/jsp/jstl/functions" %> 6 <jsp:dobody var="text0" /> 7 <c:set var="text1" 8 value="${fn:escapexml(text0)}" /> 9 <c:set var="text2" 10 value="${fn:replace(text1, [code], <pre> )}" /> 11 <c:set var="text3" 12 value="${fn:replace(text2, [/code], </pre> )}" /> 13 ${text3} 1 taglib prefix="my" tagdir="/web-inf/tags" %> 2 <html><body> 3 <my:codeformat> 4 Das ist ein normaler Text mit <tags>, 5 die angezeigt werden. Man kann Code 6 [code] 7 for s in [ Hallo, Welt ]: 8 print s 9 [/code] 10 mit speziellen Tags formatieren. 11 </my:codeformat> 12 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Custom Tags Custom Tags Attribut-Fragmente und sichtbare Variablen Ziel Mischen von Tag-Code und Seiten-Code Tag-Code in Seiten und Seiten-Code in Tag Attribut-Fragmente attribute name="..." fragment="true"... %> Attribute im Tag-Datei als Fragmente deklarierbar Stehen in Tag-Datei unter dem Namen zur Verfügung Attribute in Tag-Datei verwenden <jsp:invoke name="..." /> Attribute in JSP-Datei deklarieren <jsp:attribute name="..." > Sichtbare Variablen Variablen in Tag-Datei für JSP-Datei sichtbar machen Mit variable-direktive...</jsp:attribute> variable name-given="..." variable-class="..." scope="..." %> name-given: Name der Variable in der JSP-Datei variable-class: Java-Typ der Variablen, Object meist ok scope: Sichtbarkeit, AT_BEGIN nach Tag-Start, AT_END nach dem Tag, NESTED im Tag Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Fragmente & sichtbare Variablen, Beispiel Tableformat Ziel - Bunte Tabelle Man unterscheidet zwischen geradzahligen Zeilen und ungeradzahligen Der Benutzer legt die Inhalte fest, im Beispiel sollen ungeradzahlige Zeilen fett werden Der Tag-Entwickler legt die Farben fest, im Beispiel Freddy Kröger Design* freddytable.jsp 1 taglib prefix="my" tagdir="/web-inf/tags" 2 %><html><body><my:table 3 items="eine,schicke,bunte,tabelle" 4 ><jsp:attribute name="even" 5 >${current}</jsp:attribute><jsp:attribute name="odd" 6 ><strong> ${current} </strong></jsp:attribute 7 > 8 </my:table></body></html> <html><body> <table> <tr bgcolor="lightgreen"> <td><strong> eine </strong></td></tr> <tr bgcolor="red"> <td>schicke</td></tr> <tr bgcolor="lightgreen"> <td><strong> bunte </strong></td></tr> <tr bgcolor="red"> <td>tabelle</td></tr> </table> </body></html> *Bunte Tabellen sind weder schön, noch sollte man direkt mit HTML formatieren, also nur für das Beispiel Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

49 Custom Tags Custom Tags Fragmente & sichtbare Variablen, Beispiel Tag Attribute des Tags items: Was wird angezeigt even: Wie werden geradzahlige Zeilen formatiert odd:... Sichtbare Variablen des Tags current: Der Inhalt der Zeile Für alle Zeilen table.tag 1 tag body-content="scriptless" 2 attribute name="items" required="true" 3 attribute name="even" fragment="true" required="true" 4 attribute name="odd" fragment="true" required="true" 5 variable name-given="current" 6 variable-class="java.lang.object" scope="nested" 7 taglib prefix="c" 8 uri="http://java.sun.com/jsp/jstl/core" %> 9 <table> 10 <c:foreach var="current" items="${items}" varstatus="status"> 11 <c:choose><c:when test="${status.count % 2 == 0}" 12 ><tr bgcolor="red"> 13 <td><jsp:invoke fragment="even"/></td></tr> 14 </c:when><c:otherwise 15 ><tr bgcolor="lightgreen"> 16 <td><jsp:invoke fragment="odd" 17 /></td></tr></c:otherwise 18 ></c:choose></c:foreach></table> Wenn gerade, hole even -Fragment in rote, sonst odd -Fragment in hellgrüner Zeile Tag-Dateien Verpacken Tag-Dateien in JAR-Datei verpacken Optional Verzeichnis in JAR-Datei, beginnt mit /META-INF/tags/ JAR-Datei unter /WEB-INF/lib deployen Muss Tag Library Descriptor enthalten Datei mit Endung *.tld Beispiel: jstl jar Ein Tag Library Descriptor der JSTL 1 <?xml version="1.0" encoding="utf-8"?> 2 <taglib xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 4 xsi:schemalocation="http://java.sun.com/xml/ns/javaee 5 6 version="2.1"> 7 <tlib-version>1.2</tlib-version> 8 <short-name>c</short-name> 9 <uri>http://java.sun.com/jsp/jstl/core</uri> </taglib> Inhalt Tag Library Descriptor tlib-version: Eigene Versionsnummer Optional short-name: Vorschlag, präferiert uri: Eindeutiger Bezeichner Tag-File Elemente Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Custom Tags Custom Tags Tag Library Descriptor Tag-File Elemente Tag-Klassen Tag-Files in Tag Library Descriptor Tag tag-file Kind name: Name des Tags, meist Dateiname Kind path: Pfad zu der Tag-Datei in der Web-Anwendung Ablage der TLD-Datei TLD-Datei unter META-INF/ ablegen innerhalb der JAR-Datei TLD-Datei auch ohne JAR möglich, dann unter WEB-INF/tlds/ Tag-File Element in TLD-Datei 1 <tag-file> 2 <name>copyleft</name> 3 <path>/web-inf/tags/copyleft.tag</path> 4 </tag-file> Tag-Klassen, Alternative zu Tag-Dateien Java statt JSP zur Definition von Tags Vorgehen, ähnlich zu Servlets Von vordefinierter Klasse TagSupport erben Methoden dostarttag, doinitbody, doafterbody, doendtag überschreiben, Rückgabewerte bestimmen nächsten Aufruf Einbinden Verpacken wie Tag-Datei mit TLD-Dateien, verpflichtend Verwenden wie gehabt Alle Möglichkeiten vorhanden Attribute, Variablen zur Verfügung stellen Tag Body manipulieren Mehr Features, zum Beispiel Zugriff auf umgebendes Tag Einsatz: Strukturelle Tags, zum Beispiel <c:foreach> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

50 Model 1 / Model 2 Architektur Model 1 / Model 2 Architektur Review Model 1 Architektur Review Model 2 Architektur Nur JSPs und Beans Model 1 plus Controller Daten und Logik in Beans, Model JSP für die Präsentation, Views Vorteile Auslagern der Datenhaltung Auslagern eines großen Teils der Logik Auslagern in Standard, Beans Verbesserungsbedarf Vermischung von Anwendungslogik und Präsentation Steuerung der Abfolge der Web-Seiten in JSPs JSP JSP JSP JSP Zentrales Servlet verarbeitet Eingaben, Controller Daten und Logik in Beans, Model JSP für die Präsentation, Views Zusätzliche übergreifende Aspekte mit Filter, z. B. Logging, Authentifizierung Vorteile, Model 1 plus Vermeidet hart realisierte Links Auslagern der Ablauflogik in Servlet Ok, aber weiterer Verbesserungsbedarf Ablauflogik in Java hart realisiert request Controller Servlet update forward response JSP JSP retrieve Hart realisierte Links... Keine vordefinierten UI-Komponenten, händisches HTML, kein Tooling Keine Events und kein Event-Handling, händische Anfrageauswertung Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Übersicht Übersicht Features, Architektur Ziele Konfiguration und Folgeseitensteuerung UI-Framework für interaktive Web-Anwendungen Deklarative Konfiguration Wiederverwendbare UI-Komponenten nutzen und erstellen Kein Java-Code Datenbindung zwischen Logik (Beans) und UI-Komponenten Event-Modell um Browser-Events auf Server-Methoden abzubilden Konfigurierbare Ablaufsteuerung Komponentenbaum Abstraktion der Ansicht Wie klassische UI-Komponente request response facelet JSP JSP Tooling ( zusammenklicken ) möglich machen Historie : JSF 1.x, Servlet 2.5, JSP 2.1 Erfahrungen aus Struts-Framework, Fokus UI in JSF 2009: JSF 2.0, Servlet 2.5/3.x, Facelets Ajax, Partial Updates / Single-Page Anwendungen 2010: JSF 2.1, Maintenance Release : JSF 2.2, Servlet 3.x, Facelets HTML5, Faces Flows (wizards), File upload,... Datenbindung UI-Daten und Bean-Properties Deklarative Assoziation Hilfsmittel Konvertierung, Validierung Fehlermeldungen Lokalisierung Expression Language,... facesconfig. xml update Faces Servlet render faces Komponentenbaum retrieve Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

51 Übersicht Übersicht FacesServlet Komponentenbaum Fest vorgegebenes Controller Servlet Abstraktion der Präsentation / View FacesServlet Komponentenbaum Front-Controller, Teil des Frameworks Für alle Anwendungen gleich Konfiguration separat faces-config.xml Seitenfolgesteuerung: anhand Rückgabewerte von Methoden Beans: Initialisierung, Scope... Features Klassischer UIs Action-Handler facesconfig. xml request update Faces Servlet response retrieve facelet JSP JSP render faces Komponentenbaum Deklaration der Komponentenhiearchie in Facelets statt nur HTML-Ansicht Automatischer interner Aufbau als Baumstruktur UI-Komponenten UI-Komponenten als Widgets Nutzung über Tags Ersetzt HTML-Tags HTML rendern eine mögliche Ansicht Komposition facesconfig. xml request update Faces Servlet response retrieve facelet JSP JSP render faces Komponentenbaum Event-Listener Zusammenbau von Seiten aus Teilkomponenten Wiederverwendbare UI-Bausteine Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Übersicht JSF einrichten Datenbindung JSF Bibliotheken Datenbindung JSF Implementierung Binden von Daten einer UI-Komponente an Bean-Properties Bei Request werden Werte aus UI-Komponente automatisch in Bean-Property gesetzt Für Response werden Werte für UI-Komponente automatisch aus Bean-Property gelesen Lebenszyklusmanagement Konfiguration, initiale Werte Einheitlicher Namen und Sichtbarkeit nur noch an einer Stelle facesconfig. xml request update Faces Servlet response retrieve facelet JSP JSP render faces Komponentenbaum Mojarra: Referenzimplementierung von Oracle Open Source, stabil, Standard Alle grundlegenden Komponenten Verwenden wir Später: Alternativen mit mehr Widgets und mehr Features und mehr fancy... möglich Einbinden Zielordner WEB-INF/lib Datei javax.faces jar Nur noch eine Datei (API und Implementierung) Deklaration Scope, dann Initialisierung, halten und entfernen automatisch Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

52 JSF einrichten JSF einrichten Zentrales Servlet Konfigurieren Zentrales Servlet javax.faces.webapp.facesservlet Front-Controller Klassenhierarchie und Klassenname in JSF-Standard vorgegeben Von der konkreten JSF-Implementierung realisiert Konfiguration Servlet-Name beliebig, FacesServlet wird gerne genommen Mapping auf Dateien mit Endung.jsf Andere Mappings (Pfad, andere Endungen) möglich, häufig *.xhtml web.xml 1 <servlet> 2 <servlet-name>facesservlet</servlet-name> 3 <servlet-class> 4 javax.faces.webapp.facesservlet 5 </servlet-class> 6 <load-on-startup>1</load-on-startup> 7 </servlet> 8 <servlet-mapping> 9 <servlet-name>facesservlet</servlet-name> 10 <url-pattern>*.jsf</url-pattern> 11 </servlet-mapping> 12 <context-param> 13 <param-name>javax.faces.project_stage</param-name> 14 <param-value>development</param-value> 15 </context-param> Optionale Besonderheiten load-on-startup, Instanz bei Start, kein Warten bei erstem Klick Kontextparameter PROJECT_STAGE auf Development erhöht Anzahl der Log-Ausgaben, gut bei Entwicklung Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JSF-Konfiguration in faces-config.xml faces-config.xml Konfigurationsdatei für Unter WEB-INF, neben web.xml Initial leer außer faces-config Tag faces-config.xml 1 <faces-config 2 xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 4 xsi:schemalocation="http://xmlns.jcp.org/xml/ns/javaee 5 6 version="2.2">... 1 </faces-config> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JSF einrichten JSF einrichten Eclipse JSF Tooling / Ermöglichen Eclipse JSF Klicki Bunti JSF Tooling in Eclipse verwenden wir Projekt-Facette JSF, Version 2.2 einrichten Further Configuration Required/Available Disable Library Configuration Wir verwalten das Hinzufügen der JSF-Implementierung selbst im Projekt und nicht in Abhängigkeit von Eclipse JSF Klicki Bunti in Eclipse, Manipulation faces-config.xml vermeiden wir Wir editieren XML direkt (mit Completion) ohne Klicki-Bunti!!! Wir wählen also den rechten Tab Source Nur zum Anschauen sinnvoll, wer denn unbedingt will Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

53 JSF Erstes Beispiel JSF Erstes Beispiel Erstes Beispiel NameBean Wie in JSP Properties: vorname, mittelname, nachname, alter Nur lesen Properties: name, status status prüft ob Werte gültig sind Formulare mit Facelets Beschreibung des Komponentenbaums, statt Generierung von Markup Eingabeformular für Properties, form.xhtml bei Aufruf form.jsf Solange im Formular bis gültig Dann Ausgabe Ausgabe mit Begrüßung, show.xhtml bei Aufruf show.jsf wenn gueltig ok ist form.jsf show.jsf Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 NameBean Wiederholung webanw.namebean Normale Bean, nichts JSF spezifisches Fast wie bei JSP-Beispiel Unterschiede Rückgabewert String bei Nur Lesen Property 1 public class NameBean implements Serializable { 2 String vorname; String nachname; 3 String mittelname; int alter; 4 public NameBean() { // parameterloser Konstruktor 5 vorname = "Max"; mittelname="m."; 6 nachname = "Mustermann"; alter = 0; 7 } 8 public String getvorname() { return vorname; } 9 public void setvorname(string vorname) { this.vorname = vorname; } 10 public String getmittelname() { return mittelname; } 11 public void setmittelname(string mittelname) { this.mittelname = mittelname; } 12 public String getnachname() { return nachname; } 13 public void setnachname(string nachname) { this.nachname = nachname; } 14 public int getalter() { return alter; } 15 public void setalter(int alter) { this.alter = alter<0? 0 : alter; } gueltig 16 public String getname() { // Convenience, lesend 17 return vorname+" "+mittelname+" "+nachname; 18 } 19 public String gueltig() { // Logik 20 if (alter > 0 && status 21 (vorname+mittelname+nachname).length() >= 4) { 22 return "ok"; 23 } else { 24 return "fehler"; 25 } 26 } 27 public String getstatus() { return gueltig(); } 28 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JSF Erstes Beispiel JSF Erstes Beispiel Bean Registrieren Beans registrieren Beans über Konfiguration dem Framework bekannt geben Namen mit Instanz einer Klasse assoziieren Scope festlegen Beispiel webanw.namebean namebean ist Instanz von webanw.namebean Je Session eine Instanz für die Dauer einer Session faces-config.xml 1 <managed-bean> 2 <managed-bean-name> 3 namebean 4 </managed-bean-name> 5 <managed-bean-class> 6 webanw.namebean 7 </managed-bean-class> 8 <managed-bean-scope> 9 session 10 </managed-bean-scope> 11 </managed-bean> Vorteile Framework verwaltet Lebenszyklus, Vermeidung von wiederholtem Initialisierungscode in Java In Facelet-Seite keine wiederholte Deklaration der Bean notwendig Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Bean Registrieren Alternative mit Annotationen Annotationen Direkt an der Bean optionales Attribut name statt managed-bean-name Default Name ist Klassenname, aber erster Buchstabe klein, im Beispiel Andere Scopes verfügbar Annotation und faces-config.xml Bei zusätzlicher Konfiguration in faces-config.xml überschreibt diese die Annotationen Verwendung der Annotationen als Default Werte NameBean.java 1 package webanw; 2 import javax.faces.bean.*; 3 6 public class NameBean 7 implements Serializable { } Vorteile Alles an einem Ort, einfacher Philosophie seit JavaEE 6 Nachteile Bean wird abhängig von JSF Bei Datenbeans kritisch, bei Backingbeans ok Verwendung in Ordnung Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

54 JSF Erstes Beispiel JSF Erstes Beispiel Navigationsregel zur Folgeseitensteuerung Navigationsregeln Folgeseitensteuerung mit Strings Explizit oder aus Rückgabewerten von Methodenaufrufen Festlegung Folgeseite per Konfiguration, ohne Java Code Identifikation der Seite über (innerhalb der Anwendung) absoluten Pfad der XHTML-Seite Beispiel Wenn von der Seite /form.xhtml das Ergebnis ok zurückgegeben wird dann gehe zur Seite /show.xhtml Wenn nicht, dann auf der Seite bleiben (Default, aber mit Warnung) faces-config.xml 1 <navigation-rule> 2 <from-view-id>/form.xhtml</from-view-id> 3 <navigation-case> 4 <from-outcome>ok</from-outcome> 5 <to-view-id>/show.xhtml</to-view-id> 6 </navigation-case> 7 </navigation-rule> Vorteile Java Code unabhängig von Navigation View unabhängig von Navigation Alternative ohne Navigationsregel Outcome String ist nächste Seite Im Beispiel show oder /show.xhtml Outcome null auf gleicher Seite bleiben Vermeiden Grober Ablauf Name-Beispiel Anfrage form.jsf Endung.jsf Wegen web.xml-konfiguration auf FacesServlet umleiten FacesServlet form.xhtml ist zugehöriges Facelet Komponentenbaum aus form.xhtml Aktualisierung UI-Komponenten/Bean aus Anfrageparameter Festlegung Folgeseite Antwort HTML-Seite rendern aus Komponentenbaum Aktualisierte Werte aus Beans in Komponentenbaum facesconfig. xml request update Faces Servlet namebean response retrieve form.xhtml render Komponentenbaum Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JSF Erstes Beispiel JSF Erstes Beispiel Facelets Rahmen XHTML-Seite 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml" 4 xmlns:f="http://xmlns.jcp.org/jsf/core" 5 xmlns:h="http://xmlns.jcp.org/jsf/html" 6 xmlns:ui="http://xmlns.jcp.org/jsf/facelets"> 7 <h:head> 8 <title>der Titel</title> 9 10 </h:head> 11 <h:body> 12 Anzeigeseite Facelet show.xhtml show.xhtml 1 <h:body> 2 <h3>eingabe akzeptiert</h3> 3 Hallo <h:outputtext value="#{namebean.name}" />.<br /> 4 Status der Eingabe #{namebean.status} 5 <h:panelgrid columns="2"> 6 <h:outputtext value="vorname" /> <h:outputtext value="#{namebean.vorname}" /> 7 <h:outputtext value="mittelname" /> <h:outputtext value="#{namebean.mittelname}" /> 8 <h:outputtext value="nachname" /> <h:outputtext value="#{namebean.nachname}" /> 9 <h:outputtext value="alter" /> <h:outputtext value="#{namebean.alter}" /> 10 </h:panelgrid> 11 </h:body> </h:body> 15 </html> XHTML, Fokus auf Festlegung Komponentenbaum, nicht HTML-Generierung Tag-Libraries von JSF einbinden: h: HTML-Ersatz, f: Core JSF, ui: Facelet-spezifisch Statt xmlns.jcp.org häufig noch java.sun.com <h:head> und <h:body> erlauben Framework einzugreifen Seitenspezifische Inhalte innerhalb <h:head> und <h:body> <h:outputtext> für Ausgabe kann weggelassen werden, sollte aber verwendet werden Zugriff auf Properties mit #, inzwischen $ wieder erlaubt, aber bei # bleiben <h:panelgrid> als erstes UI-Widget, zweispaltiges Layout Angezeigte URL bei JSF meist ohne Bedeutung Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

55 JSF Erstes Beispiel JSF Erstes Beispiel Eingabeseite Facelet form.xhtml form.xhtml 1 <h:body> 2 <h:form> 3 <h:panelgrid columns="2"> 4 <h:outputlabel value="vorname" /> <h:inputtext value="#{namebean.vorname}" /> 5 <h:outputlabel value="mittelname" /> <h:inputtext value="#{namebean.mittelname}" /> 6 <h:outputlabel value="nachname" /> <h:inputtext value="#{namebean.nachname}" /> 7 <h:outputlabel for="age" value="alter" /> 8 <h:inputtext id="age" value="#{namebean.alter}" /> 9 </h:panelgrid> 10 <h:commandbutton action="#{namebean.gueltig}" value="abschicken" /> 11 </h:form> 12 </h:body> <h:form>, notwendig bei Eingaben, wird gerne vergessen Komponentenbaum aus form.xhtml generiertes HTML aus form.xhtml 1 <body><form id="j_idt6" name="j_idt6" method="post" action="/jsf/form.jsf" enctype="application/x-www-form-urlenc 2 <input type="hidden" name="j_idt6" value="j_idt6"> 3 <table><tbody> 4 <tr><td><label>vorname</label></td> 5 <td><input type="text" name="j_idt6:j_idt9" value="susi"></td></tr> 6 <tr><td><label>mittelname</label></td> 7 <td><input type="text" name="j_idt6:j_idt11" value="s."></td></tr> 8 <tr><td><label>nachname</label></td> 9 <td><input type="text" name="j_idt6:j_idt13" value="sinnlos"></td></tr> 10 <tr><td><label for="j_idt6:age">alter</label></td> 11 <td><input id="j_idt6:age" type="text" name="j_idt6:age" value="17"></td></tr> 12 </tbody></table> 13 <input type="submit" name="j_idt6:j_idt15" value="abschicken"> 14 <input type="hidden" name="javax.faces.viewstate" id="j_id1:javax.faces.viewstate:0" 15 value=" : " autocomplete="off"> 16 </form></body> <h:inputtext> für Text-Eingabezeile Komponentenbaum, auf Server form:6 <h:outputlabel> als Info für Eingaben, Assoziation über for und id Attribute <h:commandbutton> statt submit, namebean.gueltig() in action als gerufene Methode, String als Outcome Automatische Vergabe IDs Ausgabeelemente werden ignoriert Anspringen zentrales Servlet Flacher Pfad für HTML-Ausgabe input:9 input:11 input:13 input:17 submit:15 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JSF Erstes Beispiel JSF Erstes Beispiel Optionale Darstellung von UI-Komponente Problem: UI-Komponente ausblenden UI-Komponente je nach Wert angezeigen oder nicht In JSTL mit <c:if>, <c:if> verboten in JSF Lösung Änderung würde andere ID-Vergabe in Komponentenbaum erzwingen Chaos beim Aktualisieren rendered Attribut: Vorgabe true, ausschalten false UI-Komponente ist dann nicht sichtbar, aber immer noch vorhanden Gleiche IDs, gleicher Komponentenbaum Beispiel: Alter nicht anzeigen bei Vorname Susanne 1 <h:outputlabel for="age" value="alter" 2 rendered="#{namebean.vorname eq Susanne? false : true}"/> 3 <h:inputtext id="age" value="#{namebean.alter}" 4 rendered="#{namebean.vorname eq Susanne? false : true}"/> Allgemein: Kein JSTL in JSF verwenden! Navigationsregeln <navigation-rule> Haupt Tag <from-view-id> Ausgangsseite Absoluter Pfad in Web-Anwendung Pattern (/*) erlaubt <navigation-case> Fallunterscheidung Optional und falls von Methode <from-action>, vermeiden Falls <from-outcome> Dann gehe zu <to-view-id> Abarbeitung Von oben nach unten Erster Treffer faces-config.xml 1 <navigation-rule> 2 <from-view-id>/form.xhtml</from-view-id> 3 <navigation-case> 4 <from-outcome>ok</from-outcome> 5 <to-view-id>/show.xhtml</to-view-id> 6 </navigation-case> 7 </navigation-rule> faces-config.xml 1 <navigation-rule> 2 <from-view-id>/form.xhtml</from-view-id> 3 <navigation-case> 4 <from-action>#{namebean.gueltig}</from-action> 5 <from-outcome>fehler</from-outcome> 6 <to-view-id>/form.xhtml</to-view-id> 7 </navigation-case> 8 </navigation-rule> 9 <navigation-rule> 10 <from-view-id>/*</from-view-id> 11 <navigation-case> 12 <from-outcome>home</from-outcome> 13 <to-view-id>/home.xhtml</to-view-id> 14 </navigation-case> 15 </navigation-rule> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

56 JSF Erstes Beispiel JSF Erstes Beispiel Navigation Festlegung der Folgeseite Fehlermeldungen Abhängig von Outcome, action-attribut Statisch Anforderungen Statisch oder dynamisch Erst Navigationsregel, dann Wert +.xhtml direkt als Seite oder bleibt (Warnung) Statischer Outcome Angabe String im action-attribut Immer gleiche Seite/Regel Beispiel: Knopf drücken ok Dynamischer Outcome Angabe Methode im action-attribut 1 <h:form> <h:commandbutton 4 action="ok" 5 value="abschicken" /> </h:form> Dynamisch 1 <h:form> <h:commandbutton 4 action="#{namebean.gueltig}" 5 value="abschicken" /> </h:form> Formular überprüfen Fehlermeldungen passend anzeigen Validierung Eingabefelder im Tag-Body <f:validate...> Beispiel: Wert zwischen 0 und 128 Messages <h:messages /> zeigt alle Fehlermeldungen an Sonst nur im Log 1 <h:outputlabel for="age" value="alter" /> 2 <h:inputtext id="age" value="#{namebean.alter}"> 3 <f:validatelongrange minimum="0" maximum="128" /> 4 </h:inputtext> Rückgabewert der Methode Beispiel: Ergebnis von namebean.gueltig() Method-Binding ohne Klammern/Parameter Method-Expression mit... vermeiden Alternative während Entwicklung, PROJECT_STAGE auf Development in web.xml Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 JSF Erstes Beispiel Ablauf einer JSF-Anfrage Fehlermeldungen an Passender Stelle Ablauf einer JSF-Anfrage Fehlermeldung an passender Stelle Fehlermeldung im Formular An passender Stelle Beispiel: Neben dem falschen Wert Vorgehen Dritte Spalte aufmachen Wenn kein Fehler, dann leer lassen Verknüpfen über id <h:message for=... /> 1 <h:panelgrid columns="3"> 2 <h:outputlabel value="vorname" /> 3 <h:inputtext value="#{namebean.vorname}" /> 4 <h:column /> 5 <h:outputlabel value="mittelname" /> 6 <h:inputtext value="#{namebean.mittelname}" /> 7 <h:column /> 8 <h:outputlabel value="nachname" /> 9 <h:inputtext value="#{namebean.nachname}" /> 10 <h:column /> 11 <h:outputlabel for="age" value="alter" /> 12 <h:inputtext id="age" value="#{namebean.alter}"> 13 <f:validatelongrange minimum="0" maximum="128" /> 14 </h:inputtext> 15 <h:message for="age" /> 16 </h:panelgrid> Komponentenbaum (wieder-) herstellen Antwort generieren, rendern Werte UI-Komp. mit Anfrageparam. aktualisieren direkt rendern Anwendung ausführen (action) Anfragebehandlung stoppen* Konvertierung und Validierung Fehler direkt rendern Werte in Beans aktualisieren (setproperty) Anfragebehandlung stoppen* Ereignisbehandlung * wurde anderweitig behandelt, z.b. forward Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

57 Ablauf einer JSF-Anfrage Ablauf einer JSF-Anfrage JSF-Ablauf Komponentenbaum JSF-Ablauf Werte Konvertieren und Validieren Komponentenbaum (wieder-)herstellen Seite zum ersten Mal angefragt? Für <name>.jsf die Facelet-Sicht <name>.xhtml Aus Facelet den Komponentenbaum erstellen, keine Anzeige Vergabe der IDs und Aufbau der inneren Struktur Registrieren von Events und Validatoren Mit Werten bestücken Seite schon einmal angefragt? Richtigen Komponentenbaum heraussuchen Werte aktualisieren Anfrage-Parameter auslesen Passende Werte in jeweilige UI-Komponente setzen (submitted value), für den ganzen Baum Konvertierung und Validierung für Komponenten mit immediate-flag Sinnvoll für Änderungen die passieren sollen obwohl Formular insgesamt noch nicht funktioniert Beispiel: Auswahl eines Landes, dazu passend Städte, obwohl Alter noch nicht stimmt Falls etwas schief geht, merken und Status auf ungültig Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Jede UI-Komponente validiert und konvertiert ihren Wert Aufruf registrierter oder automatischer Konvertierer Beispiel: Automatischer Konvertierer von String nach Integer oder Datum Aufruf registrierter oder automatischer Validierer Beispiel: Alter zwischen 0 und 128 Bei Fehler wird Fehlermeldung (Message) in Fehlerliste eingetragen Bei Fehlern wird die Anfragebehandlung gestoppt und direkt zur Ausgabe gesprungen Werte sind nur im Komponentenbaum Die Werte sind nur in den UI-Komponenten im Komponentenbaum Die Werte sind noch nicht in den (Backing-)Beans Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Ablauf einer JSF-Anfrage Ablauf einer JSF-Anfrage JSF-Ablauf Werte in den Beans aktualisieren, Aktion JSF-Ablauf Antwort Generieren Werte aktualisieren Voraussetzung, alles konvertiert und validiert Setter der an die UI-Komponenten gebundenen Properties der Beans anwenden Data-binding: #{bean.property} Beispiel: #{namebean.vorname} Aufruf in Beispiel: namebean.setvorname("susi") Bei Fehler Abbruch Es sollte kein (Eingabe-) Fehler geben Eingabevalidierung in der vorherigen Phase machen Nur dann ist Werteaktualisierung ganz oder gar nicht Aktuellen Stand des passenden Komponentenbaums ausgeben Voraussetzung: Werte in UI-Komponenten sind aktualisiert mit Werten aus Beans oder bei Fehler submitted value Durchlauf des Baums Je UI-Komponente wird (HTML-)Renderer aufgerufen Fertig generierte Seite an Browser schicken Anwendung ausführen Aktion, die an Ereignis gebunden ist ausführen Verarbeitungslogik in Methoden Meist im action-attribut angegeben Beispiel: action="#{namebean.gueltig}" Arbeitet auf aktualisierten Werten in den (Backing-)Beans Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

58 Ablauf einer JSF-Anfrage Aktionen und Kommandos Ablage der Daten für Komponentenbaum Auf dem Server Vorgabe, empfohlen Komponentenbaum wird aufgebaut und auf Server mit Werten vorgehalten Werte immer wieder aktualisiert Werte sicher auf dem Server, braucht Speicher Auf dem Client Alternative, wenn, dann nur bei Entwicklung Werte des Komponentenbaums werden auf dem Client (hidden fields) gespeichert Füllen des Komponentenbaums bei Anfrage Einfach zu löschen (Entwicklung) faces-config.xml 1 <!-- 2 <context-param> 3 <param-name> 4 javax.faces.state_saving_method 5 </param-name> 6 <param-value> 7 client 8 </param-value> 9 </context-param> 10 --> Vorteil Weniger Speicher auf dem Server Einfach zu löschen (Entwicklung) Nachteil Werte sichtbar (Quelltext, Browser) Datenübertragung Hoher Aufwand (Serialisierung, Base64, optional Verschlüsselung) Vermeiden Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Aktionen und Kommandos Aktion Binden einer Schaltfläche oder eines Links an Aktion Methode ohne Parameter mit Rückgabe String; oder nur ein String String wegen Navigationsregeln Darstellung Kommandos statt Submit <h:commandbutton> <h:commandlink> Beispiel Darstellung mit Bild möglich Schaltknopf, Textlink, Imagelink An Methode kommando von bb gebunden Aufruf bb.kommando(), Rückgabe String 1 <h:form> 2 <h:commandbutton action="#{bb.kommando}" 3 value="commandbutton"/> <br /> 4 <h:commandlink action="#{bb.kommando}" 5 value="commandlink"/> <br /> 6 <h:commandlink action="#{bb.kommando}"> 7 <h:graphicimage alt="knopf" 8 url="/button.png"/> 9 </h:commandlink> <br /> 10 </h:form> 1 public String kommando() { 2 FacesContext fc = FacesContext.getCurrentInstance(); 3 FacesMessage msg = 4 new FacesMessage("kommando ausgeführt"); 5 fc.addmessage("kommando", msg); 6 return "weiter"; 7 } Instanz einer passenden Bean unter dem Namen bb vorausgesetzt Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Aktionen und Kommandos Aktionen und Kommandos ActionListener Problem action, rufendes Widget unbekannt Parameterübergabe nicht erlaubt Man will aber je nach Widget unterschiedlich reagieren Lösung ActionListener wie bei klassischen GUIs Separates Tag-Attribut Spezielle Methode, Übergabe ActionEvent-Parameter, keine Rückgabe Parameter vom Framework gesetzt Über Parameter rufendes Widget Beispiel: Nachricht mit ID 1 <h:form> 2 <h:commandbutton id="weiter" 3 actionlistener="#{bb.handlekommando}" 4 value="commandbutton-actionlistener"/> 5 <h:commandbutton id="ende" 6 actionlistener="#{bb.handlekommando}" 7 value="commandbutton-actionlistener"/> 8 </h:form> 1 public void handlekommando(actionevent e) { 2 UIComponent cmd = e.getcomponent(); 3 FacesContext fc = 4 FacesContext.getCurrentInstance(); 5 String s = "handlekommando mit " + cmd.getid(); 6 FacesMessage msg = new FacesMessage(s); 7 fc.addmessage("handlekommando", msg); 8 } bei Klick auf linken Button ActionListener, Backing-Bean, Ausdrücke Backing-Bean Durch ActionEvent-Parameter Abhängigkeit von JSF Unterscheidung Backing -Beans und Daten/Logik-Beans Für Backing-Beans, die UI stützen/backen, ist Abhängigkeit OK FacesContext Für Kommunikation mit Framework Aktuelle Instanz mit statischer Methode getcurrentinstance(), wenn im JSF-Ablauf aufgerufen 1 public void handlekommando(actionevent e) { 2 UIComponent cmd = e.getcomponent(); 3 FacesContext fc = 4 FacesContext.getCurrentInstance(); 5 String s = "handlekommando mit " + cmd.getid(); 6 FacesMessage msg = new FacesMessage(s); 7 fc.addmessage("handlekommando", msg); 8 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

59 Aktionen und Kommandos UI-Komponenten Ausdrücke in Java Auflösen Problem Expression Language Resolver UI-Komponentenhierarchie, Auszug UIComponent Ausdrücke in Java auflösen Notwendig, um auf registrierte Beans über Namen zuzugreifen Lösung zwei Alternativen Mit Expression Language Resolver, Cast notwendig Mit evaluateexpressionget und Angabe der Ziel-Klasse Beispiel Eine Bean-Klasse DataModelBackingBean Eine Managed Bean Instanz unter dem Namen dmbb 1 FacesContext fc = FacesContext.getCurrentInstance(); 2 Application app = fc.getapplication(); 3 ELResolver elr = app.getelresolver(); 4 DataModelBackingBean dmbb; 5 dmbb = (DataModelBackingBean) 6 elr.getvalue(fc.getelcontext(), null, "dmbb"); evaluateexpressionget 1 FacesContext fc = FacesContext.getCurrentInstance(); 2 Application app = fc.getapplication(); 3 DataModelBackingBean dmbb; 4 dmbb = app.evaluateexpressionget(fc, 5 "#{dmbb}", DataModelBackingBean.class); <h:commandbutton> UIComponentBase UIGraphic UICommand UIData UIPanel UIOutput unabhängig von Anzeige Rendertypen HTMLCommandButton HTMLCommandLink UIInput HTMLInputHidden HTMLInputSecret HTMLInputText UISelectOne HTMLSelect OneListBox Image Button Table Grid Hidden ListBox Link Group Secret Menu Text Radio Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 UI-Komponenten UI-Komponenten Styling Texteingabe Default Renderer HTML Standard HTML-Attribute meist erlaubt CSS verwenden stark empfohlen Beispiel mit <h:outputtext>, geht auch mit anderen Tags style-attribut: direkter Einfluss, vermeiden 1 <style type="text/css"> 2.roteklasse { 3 background-color: #FF6666; 4 font-weight: bold; 5 } 6 </style> 1 <h:panelgrid columns="1"> 2 <h:outputtext value="hallo Welt" /> 3 <h:outputtext style="background-color:#ff6666;" 4 value="hallo rote Welt" /> 5 <h:outputtext styleclass="roteklasse" 6 value="hallo rote fette Welt mit class" /> 7 <h:outputtext styleclass="roteklasse" 8 value="#{bb.zeichenkette}" /> 9 </h:panelgrid> Optionen für Texteingabe <h:inputtext>: Eingabe Text <h:inputsecret>: Eingabe Passwort <h:inputtextarea>: Eingabe längerer Text 1 <h:form> 2 <h:panelgrid columns="2"> 3 <h:outputtext value="inputtext"/> 4 <h:inputtext id="i1" value="#{bb.zk1}" /> 5 <h:outputtext value="inputsecret"/> 6 <h:inputsecret id="i2" value="#{bb.zk2}" /> 7 <h:outputtext value="inputtext"/> 8 <h:inputtextarea id="i3" value="#{bb.zk3}" /> 9 <h:commandbutton value="mach"/> 10 </h:panelgrid> 11 </h:form> <h:panelgrid border="1" columns="1"> 14 <h:outputtext value="inputtext: #{bb.zk1}"/> 15 <h:outputtext value="inputsecret: #{bb.zk2}"/> 16 <h:outputtext value="inputtextarea: #{bb.zk3}"/> 17 </h:panelgrid> styleclass-attribut: Angabe der CSS-Klasse fürs Rendern BackingBean.java 1 private String s1, s2, s3; 2 public String getzk1() { return s1; } 3 public void setzk1(string s) { this.s1 = s; } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

60 UI-Komponenten UI-Komponenten Facetten Ja/Nein Auswahl <h:facet> Zusätzliche Informationen in Vater-Element rendern Für Wiederholungen in zum Beispiel Tabellenköpfen oder Gruppierungen wie <h:panelgrid> Beispiel Schönere Ausgabe der Texteingabe Zweispaltig Mehrspaltige Überschrift grau hinterlegt 1 <style type="text/css"> 2.gray { 3 background-color: #AAAAAA; 4 font-weight: bold; 5 } 6 </style> 7 Die Werte sind <br /> 8 <h:panelgrid columns="2"> 9 <f:facet name="header"> 10 <h:outputtext styleclass="gray" 11 value="eine Ausgabebox" /> 12 </f:facet> 13 <h:outputlabel value="inputtext:" /> 14 <h:outputtext value="#{bb.zk1}" /> 15 <h:outputlabel value="inputsecret:" /> 16 <h:outputtext value="#{bb.zk2}" /> 17 <h:outputlabel value="inputtextarea:" /> 18 <h:outputtext value="#{bb.zk3}" /> 19 </h:panelgrid> <h:selectbooleancheckbox> Ja/Nein Auswahl Checkbox Binden an einen Booleschen Wert 1 <h:form> 2 <h:panelgrid columns="2"> 3 <h:outputtext value="ja oder Nein" /> 4 <h:selectbooleancheckbox value="#{bb.janein}"/> 5 <h:outputtext value="wert ist #{bb.janein}" /> 6 <h:commandbutton value="mach"/> 7 </h:panelgrid> 8 </h:form> BackingBean.java 1 private Boolean janein; 2 public Boolean getjanein() { 3 return janein; 4 } 5 public void setjanein(boolean janein) { 6 this.janein = janein; 7 } Bei panelgrid ist Facette Überschrift über alle Spalten. Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 UI-Komponenten UI-Komponenten Einfachauswahl Statisch Einfachauswahl dynamisch <h:selectoneradio> Ergebnis in String-Property Möglichkeiten manuell angeben mit <f:selectitem> innerhalb von Tag <f:selectitem> itemvalue: Wert für Property itemlabel: Ansicht im Browser Alternativen <h:selectonelistbox> <h:selectonemenu> 1 <h:form> 2 <h:panelgrid columns="2"> 3 <h:outputtext value="einfachauswahl" /> 4 <h:selectoneradio value="#{bb.zk1}"> 5 <f:selectitem itemvalue="eins" itemlabel="one" /> 6 <f:selectitem itemvalue="zwei" itemlabel="two" /> 7 <f:selectitem itemvalue="drei" itemlabel="three" /> 8 </h:selectoneradio> 9 <h:outputtext value="wert ist #{bb.zk1}" /> 10 <h:commandbutton value="mach"/> 11 </h:panelgrid> 12 </h:form> <h:select*> Wie statisch <f:selectitems> Property, Value-Bindung Liste mit SelectItem-Instanzen Beispiel Wie statisch Visualisierung Ausrichtung 1 <h:form> 2 <h:panelgrid columns="2"> 3 <h:outputtext 4 value="einfachauswahl mit Listenproperty" /> 5 <h:selectoneradio layout="pagedirection" 6 value="#{bb.zk2}"> 7 <f:selectitems value="#{bb.selectliste}" /> 8 </h:selectoneradio> 9 <h:outputtext value="wert ist #{bb.zk2}" /> 10 <h:commandbutton value="mach"/> 11 </h:panelgrid> 12 </h:form> BackingBean.java 1 public List<SelectItem> getselectliste() { 2 List<SelectItem> ret = new ArrayList<SelectItem>(); 3 ret.add(new SelectItem("Eins", "One")); 4 ret.add(new SelectItem("Zwei", "Two")); 5 ret.add(new SelectItem("Drei", "Three")); 6 return ret; 7 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

61 UI-Komponenten UI-Komponenten Mehrfachauswahl Tabelle aus Daten <h:selectmanylistbox> Wie One aber Ergebnis in Property vom Typ String[] oder List<String> Alternativen <h:selectmanycheckbox> <h:selectmanymenu> 1 <h:form> 2 <h:panelgrid columns="3"> 3 <h:outputtext value="mehrfachauswahl" /> 4 <h:selectmanylistbox value="#{bb.selectlerg}"> 5 <f:selectitems value="#{bb.selectliste}"/> 6 </h:selectmanylistbox> 7 <h:commandbutton value="mach"/> 8 </h:panelgrid> 9 </h:form> BackingBean.java 1 private List<String> selectlerg; 2 public List<String> getselectlerg() { 3 return selectlerg; 4 } 5 public void setselectlerg(list<string> erg) { 6 selectlerg = erg; 7 } <h:datatable> Tabelle aus dynamischen Daten Mehre Items, meist Liste oder Feld über value-attribut binden Laufvariable über var-attribut <c:foreach> nicht verwenden <h:column> Je Spalte ein Tag In Tag Zugriff auf Laufvariable Beispiel Spalten mit Kopf (Facetten) Text und Wert 1 <h:datatable var="wahl" value="#{bb.selectlerg}"> 2 <h:column> 3 <f:facet name="header"> 4 <h:outputtext value="text"/> 5 </f:facet> 6 <h:outputtext value="wahl ist" /> 7 </h:column> 8 <h:column> 9 <f:facet name="header"> 10 <h:outputtext value="wert"/> 11 </f:facet> 12 <h:outputtext value="#{wahl}" /> 13 </h:column> 14 </h:datatable> <h:panelgroup>, um mehrere Komponenten zu verwenden, wo nur eine erwartet wird Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Interaktion mit Kollektionen Interaktion mit Kollektionen Interaktion mit Kollektionen DataModel Beispiel Auswahl, Editieren, Sichern Ziel Interaktion mit mehreren Objekten Beispiel Bearbeiten eines Objekts in einer Sammlung von Objekten Auswahl: Wähle ein Element aus einer Sammlung von Elementen Herausfinden welches Objekt gemeint ist DataModel JSF-Typ für Datenmodell auf Java-Ebene Arbeitet mit <h:datatable> automatisch zusammen Abstrakter Typ, verschiedene Unterklassen, z.b. ListDataModel datamodel wrappeddata rowcount rowindex rowdata n 2 Editieren: Ausgewähltes Element editieren, Kopieren in temporäres zu editierendes Objekt Sichern: Daten aus geändertem Objekt in Original-Objekt zurück speichern, dadurch Abbrechen möglich Umsetzung mit DataModel Generischer Typ, sollte mit Datentyp parametrisiert werden Beinhaltet Objekt-Sammlung item1 item2 item3 itemn... Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

62 Interaktion mit Kollektionen Interaktion mit Kollektionen Backing-Bean für Interaktion DataModelBackingBean Darstellung und Auswahl DataModelBackingBean Liste von NameBean Passendes DataModel Referenz auf ausgewähltes Element Referenz auf Kopie des ausgewählten Elements Initialisierung, Getter Daten besorgen und für Dauer der Interaktion merken 3 public class DataModelBackingBean implements Serializable { 1 private List<NameBean> lnb; 2 // DataModel ist nicht serialisierbar 3 transient private DataModel<NameBean> namesmodel; 4 private NameBean current = null; 5 private NameBean currentcopy = null; 1 public DataModelBackingBean() { 2 lnb = retrievedata(); 3 namesmodel = new ListDataModel<NameBean>(); 4 namesmodel.setwrappeddata(lnb); 5 } Darstellung Mehrspaltige (column) Tabelle Laufvariable name Auswahl Attribut dername aktuelles NameBean-Objekt Attribut der aktuellen UI-Komponente commandlink Auslesen über ActionEvent 1 <h:datatable var="name" value="#{dmbb.namesmodel}"> 2 <h:column> 3 <f:facet name="header"> 4 <h:outputtext value="vorname" /> 5 </f:facet> 6 <h:outputtext value="#{name.vorname}" /> 7 </h:column> 1 <h:column> 2 <h:commandlink actionlistener="#{dmbb.select}" 3 action="edit"> 4 <f:attribute name="dername" value="#{name}" /> 5 <h:outputtext value="edit" /> 6 </h:commandlink> 7 </h:column> 8 </h:datatable> Passende Getter zum Zugriff DataModelBackingBean.java... 1 public List<NameBean> getliste() { 2 return lnb; 3 } 4 public DataModel<NameBean> getnamesmodel() { 5 return namesmodel; 6 } 7 public NameBean getcurrentcopy() { 8 return currentcopy; Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte 9 } Anwendungen 6. Juli / public void select(actionevent ae) { 2 current = (NameBean) 3 ae.getcomponent().getattributes().get("dername"); 4 currentcopy = new NameBean(current); 5 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Interaktion mit Kollektionen Interaktion mit Kollektionen Editieren Kopie einer NameBean Editieren Auf aktueller Kopie currentcopy Abbrechen ohne Aktion Sichern mit Methode save 1 <h:form> 2 <h:panelgrid columns="2"> 3 <h:outputlabel value="vorname" /> 4 <h:inputtext value="#{dmbb.currentcopy.vorname}" /> 5 <h:outputlabel value="mittelame" /> 6 <h:inputtext value="#{dmbb.currentcopy.mittelname}" /> 7 <h:outputlabel value="nachname" /> 8 <h:inputtext value="#{dmbb.currentcopy.nachname}" /> 9 <h:outputlabel value="alter" /> 10 <h:inputtext value="#{dmbb.currentcopy.alter}" /> 11 </h:panelgrid> 12 <h:commandbutton action="cancel" value="abbrechen" /> 13 <h:commandbutton action="#{dmbb.save}" value="sichern" /> 14 </h:form> Editiere Kopie Sichern Sichern Werte der Kopie in aktueller Bean speichern Abbrechen ändert nur Kopie, nicht zurückspeichern DataModelBackingBean.java 1 public String save() { 2 String result = currentcopy.gueltig(); 3 if (result.equals("ok")) { 4 current.setvorname(currentcopy.getvorname()); 5 current.setmittelname(currentcopy.getmittelname()); 6 current.setnachname(currentcopy.getnachname()); 7 current.setalter(currentcopy.getalter()); 8 } else { 9 FacesContext fc = FacesContext.getCurrentInstance(); 10 FacesMessage msg = new FacesMessage("Objekt nicht gültig"); 11 fc.addmessage("edit", msg); 12 } 13 return result; 14 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

63 Interaktion mit Kollektionen Interaktion mit Kollektionen Editieren/Sichern Navigationsregeln Navigationsregeln von selectname selectname edit editname Navigationsregeln von editname editname ok selectname editname cancel selectname editname fehler editname, bleibt faces-config.xml 1 <navigation-rule> 2 <from-view-id>/selectname.xhtml</from-view-id> 3 <navigation-case> 4 <from-outcome>edit</from-outcome> 5 <to-view-id>/editname.xhtml</to-view-id> 6 </navigation-case> 7 </navigation-rule> 8 <navigation-rule> 9 <from-view-id>/editname.xhtml</from-view-id> 10 <navigation-case> 11 <from-outcome>ok</from-outcome> 12 <to-view-id>/selectname.xhtml</to-view-id> 13 </navigation-case> 14 <navigation-case> 15 <from-outcome>cancel</from-outcome> 16 <to-view-id>/selectname.xhtml</to-view-id> 17 </navigation-case> 18 <navigation-case> 19 <from-outcome>fehler</from-outcome> 20 <to-view-id>/editname.xhtml</to-view-id> 21 </navigation-case> 22 </navigation-rule> Blättern Blättern Pager Anzeige von begrenzt vielen Elementen je Seite Vor, Zurück, Start, Ende Beispiel 25 Elemente, 10 zeigen Vor, Vor, Zurück Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Interaktion mit Kollektionen Interaktion mit Kollektionen Blättern Pager Separate Klasse Pager first: Erstes anzuzeigendes Element size: Anzahl der Elemente insgesamt norows: Wieviel Elemente sollen ab first angezeigt werden Methoden zum Navigieren Einbettung DataModelBackingBean.java 1 private Pager pager = new Pager(); 2 public Pager getpager() { return pager; } 1 public class Pager implements Serializable { 2 private int first; 3 private int size; // wie viele 4 private int norows; // davon wie viele zeigen 5 6 public Pager() { 7 first = 0; size = 0; norows = 10; 8 } 9 public int getfirst() { return first; } 10 public int getsize() { return size; } 11 public void setsize(int size) { 12 this.size = size; this.first = 0; 13 } 14 public int getnorows() { return norows; } 15 public void setnorows(int norows) { this.norows = norows; } 16 public String start() { first = 0; return null; } 17 public String zurueck() { first -= norows; 18 if (first < 0) first = 0; return null; 19 } 20 public String vor() {first += norows; 21 if (first > size - norows) first = size - norows; 22 return null; 23 } 24 public String ende() { 25 first = size - norows; return null; 26 } Blättern Mit datatable Umsetzung 1 <h:commandlink action="#{dmbb.pager.start}" value="start" /> 2 <h:commandlink action="#{dmbb.pager.zurueck}" value="zurück" /> 3 <h:commandlink action="#{dmbb.pager.vor}" value="vor" /> 4 <h:commandlink action="#{dmbb.pager.ende}" value="ende" /> <br /> 5 <h:outputtext value="#{dmbb.pager.first} - / #{dmbb.pager.size}"/> 6 <h:datatable var="name" value="#{dmbb.namesmodel}" 7 first="#{dmbb.pager.first}" rows="#{dmbb.pager.norows}"> 8 <h:column> 9 <f:facet name="header"> 10 <h:outputtext value="vorname" /> 11 </f:facet> 12 <h:outputtext value="#{name.vorname}" /> 13 </h:column> Binden der Links an die jeweils passende Methode Nutzen der Attribute first und rows von <h:datatable> Allgemein Keine Logik im Facelet, nur Binden an Methoden (ohne Parameter) Nutzen der Features der UI-Komponenten (nicht Daten ändern) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

64 GET-Unterstützung GET-Unterstützung Bookmarks Problem POST JSF nutzt hauptsächlich POST GET für Bookmarks notwendig Bei GET kein JSF-Lebenstyklus Lösung Expliziter GET-Support Tags <h:link> und <h:button> Funktioniert außerhalb von <h:form> outcome-attribut für Navigationsregel value-attribut für Darstellung <f:param> (statt <f:attribute>) für Parameterübergabe Nur in Ausnahmefällen verwenden JSF ist ein POST-Framework, hoch interaktive Anwendungen (nicht nur surfen) ID für NameBean DataModelBackingBean.java 1 public String getid(namebean nb) { 2 if (nb == null) { return "null"; } 3 String id = nb.vorname+"-"+nb.mittelname+"-"+ 4 nb.nachname+"-"+nb.alter; 5 return id; 6 } 7 public String getidcurrent() { 8 return getid(current); 9 } 10 public void setidcurrent(string id) { Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Bookmarks, GET-Unterstützung Umsetzung selectnameget.xhtml 1 <h:column> 2 <h:link value="details" outcome="detail"> 3 <f:param name="dieid" value="#{dmbb.getid(name)}" /> 4 </h:link> 5 </h:column> 6 </h:datatable> detailname.xhtml 1 <f:metadata> 2 <f:viewparam name="dieid" value="#{dmbb.idcurrent}" /> 3 </f:metadata> 4 <h:panelgrid columns="2"> 5 <h:outputlabel value="vorname: " /> 6 <h:outputtext value="#{dmbb.currentcopy.vorname}" /> Ausgeben der ID, ausnahmsweise durch Funktion mit Argumenten Kopieren des Parameters dieid in die Property currentid mit setcurrentid, geht jetzt nicht nur mit POST, sondern auch mit GET Effekt: Bookmark-bar Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 GET-Unterstützung Konvertierung und Validierung Bookmarks Anmerkungen Konvertierung und Validierung View-Parameter weitergeben Potenziell empfangen Seiten, die GET-Parameter enthalten auch GET-Parameter Einfache Möglichkeit alle GET-Parameter weiterzugeben mit includeviewparams Verwendbar in <h:link> und <h:button> Positionierung von <f:metadata> Darf nicht in einem Template oder einem Seitenfragment (später) sein Kann umgangen werden mit Variablen, vermeiden Verwenden von GET Nur für Bookmarks Nur bei Ansichten, nicht bei Änderungen Vermeiden, selten Web-Auftritt zum surfen mit JSP 1 <h:column> 2 <h:link value="details" 3 includeviewparams="true" 4 outcome="detail" > </h:link> 7 </h:column> Bisher Automatische Aktualisierung der Bean-Properties mit den Werten der Eingabefelder Automatische Konvertierung für Standardtypen (Zahlen), ansonsten String Offen Durch Konvertierung von Zahlen auch Validierung, dass nur Ziffern verwendet werden Direkte Konvertierung in benutzerspezifische Datentypen Statt String-Property in der Backing-Bean direkt Property mit benutzerspezifischem Typ Validierung der Eingabe nach benutzerspezifischen Kriterien Umsetzung mit JSF Standardkonverter (automatisch) und benutzerspezifische Konverter Standardvalidierer (Tags, konfigurierbar) und benutzerspezifische Validierer Benutzerspezifische Konvertier und Validierer durch Klassen, die JSF-Schnittstellen implementieren Konfiguration durch Annotation oder faces-config.xml Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

65 Konvertierung und Validierung Konvertierung und Validierung Konvertierung Beispiel NameBean Konverter Einbettung Problemstellung Einzeiliges Eingabefeld für NameBean Eingabe besteht aus 4 durch Leerzeichen getrennten Strings, die den Komponenten zugeordnet werden Konvertierung von und zu namebean, einer managed bean vom Typ webanw.namebean Konvertierungsfehler anzeigen: Weniger/mehr als vier Elemente, vierter Teil kein int Ansicht Einzeilige Eingabe Einzelteile der konvertierten Bean Alles auf eine Seite, keine Navigation 1 <h:form> 2 <h:panelgrid columns="3"> 3 <h:outputlabel for="nameeinzeilig" value="name Einzeilig"/> 4 <h:inputtext id="nameeinzeilig" value="#{namebean}" 5 converter="nameconverter" /> 6 <h:message for="nameeinzeilig" /> 7 <h:commandbutton value="update" /> 8 </h:panelgrid> 9 <h:panelgrid columns="2"> 10 <h:outputlabel value="vorname:"/> <h:outputtext value="#{namebean.vorname}" /> 11 <h:outputlabel value="mittelname:"/> <h:outputtext value="#{namebean.mittelname}" /> 12 <h:outputlabel value="nachname:"/> <h:outputtext value="#{namebean.nachname}" /> 13 <h:outputlabel value="alter:"/> <h:outputtext value="#{namebean.alter}" /> 14 </h:panelgrid> 15 </h:form> converter-tag für Nutzung benutzerdefinierten Konverter, Zeile 5 <h:message for...> für Konverter-spezifische Fehlermeldungen action nicht notwendig, gleiche Seite Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Konvertierung und Validierung Konvertierung und Validierung Konverter Implementierung NameConverter.java FacesConverter-Tag zur Registrierung unter Namen getasobject: von String nach NameBean getasstring: von NameBean nach String Konvertierungsfehler als 2 public class NameConverter implements Converter { 3 public Object getasobject(facescontext fc, 4 UIComponent uic, String value) { 5 String[] parts = value.split("[\t\n\r ]+"); nameconverter 6 if (parts.length!= 4) { 7 FacesMessage msg = new FacesMessage("keine 4 Teile"); Alternativ in 8 throw new ConverterException(msg); faces-config.xml möglich 9 } 10 NameBean nb = new NameBean(); 11 nb.setvorname(parts[0]); 12 nb.setmittelname(parts[1]); 13 nb.setnachname(parts[2]); 14 try { 15 nb.setalter(integer.parseint(parts[3])); 16 } catch (NumberFormatException e) { 17 FacesMessage msg = new FacesMessage("4. Teil kein int"); 18 throw new ConverterException(msg); 19 ConverterException } 20 return nb; 21 } 22 public String getasstring(facescontext fc, 23 UIComponent uic, Object value) { 24 if (value == null) { return null; } 25 NameBean nb = (NameBean) value; 26 return nb.getname() + " " + nb.getalter(); 27 } 28 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Validierung Manuell Ohne spezifische Unterstützung action-methode, bei Fehlschlag auf gleicher Seite bleiben Alles möglich, keine spezifische Unterstützung Ab und zu notwendig (komplexe, abhängige Validierung) Implizit Grundtypen und spezielle Attribute Properties bei Grundtypen wie Zahlen prüfen, ob passender Wert als String vorliegt wie nur Ziffern Boolean, Byte, Character, Double, Float, Integer, Short, Long Attribute wie required="true" Explizit Ausdrücklich angegebene Validierer Angabe von Validierungsbedingungen in Standardvalidierer zum Beispiel <f:validatelongrange mininum="0"maximum="128"/> Angabe von selbstgeschriebenen Validierer-Klassen oder -Methoden Achtung: Validierer setzt erfolgreich konvertiertes Objekt voraus Validierer arbeitet auf konvertiertem Objekt, nicht auf String Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

66 Konvertierung und Validierung Konvertierung und Validierung Standard-Validatoren Benutzerspezifische Validatoren Beispiel Verwendung <f:validate... /> disabled-attribut Weitere Attribute spezifisch je Tag Mehrere kombiniert erlaubt Standard-Validatoren <f:validatelongrange>, <f:validatedoublerange>, <f:validatelength> (String) 1 <h:panelgrid columns="3"> 2 <h:outputlabel for="zahl" value="zahl" /> 3 <h:inputtext id="zahl" value="#{bb.zahl}"> 4 <f:validatelongrange minimum="17" maximum="42" /> 5 </h:inputtext> 6 <h:message for="zahl" /> 7 <h:outputlabel for="zk1" value="zk1"/> 8 <h:inputtext id="zk1" value="#{bb.zk1}"> 9 <f:validateregex pattern="a[bc]+d"/> 10 </h:inputtext> 11 <h:message for="zk1" /> 12 <h:commandbutton value="update" /> 13 </h:panelgrid> Anforderungen Nur geradzahlige Zahlen Mit 3 Ziffern Oder festlegbarer Anzahl von Ziffern Passende Fehlermeldungen In Ordnung Fehlschlag, bei 3 Ziffern minimum/maximum, Zahl oder Anzahl Zeichen <f:validateregex>, reg. Ausdruck Fehlschlag, bei 2 Ziffern <f:validaterequired>, Muß-Eingabe Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Konvertierung und Validierung Konvertierung und Validierung Validator Default Anzahl Ziffern Klasse EvenDigitsValidator registriert unter angegebene Namen den Validator EvenDigitsValidator.java 2 public class EvenDigitsValidator 3 implements Validator, StateHolder, Serializable { 1 public void validate(facescontext fc, Auch mit <validator> unter 2 UIComponent uic, Object value) faces-config.xml 3 throws ValidatorException { 4 Integer zahl; Validator-Schnittstelle für validate 5 try { 6 zahl = (Integer) value; StateHolder, kommt noch 7 } catch (ClassCastException e) { 8 FacesMessage msg = new FacesMessage("not int"); validate 9 throw new ValidatorException(msg); 10 } Bei Fehlern ValidatorException 11 if (zahl%2!= 0) { 12 FacesMessage msg = new FacesMessage("not even"); Instanzvariable digits, default 3 13 throw new ValidatorException(msg); 1 Integer digits = Integer.valueOf(3); 14 } 2 public void setdigits(integer digits) { 15 zahl = zahl < 0? -zahl : zahl; 3 this.digits = digits; 16 if (zahl.tostring().length()!= digits) { 4 } 17 String s = 18 String.format("not %d digits", digits); 19 FacesMessage msg = new FacesMessage(s); 20 throw new ValidatorException(msg); 21 } 22 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Facelet Default Anzahl Ziffern Facelet <f:validator> erlaubt direkte Nutzung eines registrierten Validators 1 <h:panelgrid columns="3"> 2 <h:outputlabel for="ed" 3 value="gerade Zahl mit 3 Ziffern" /> 4 <h:inputtext id="ed" value="#{bb.zahl}"> 5 <f:validator validatorid="evendigits" /> 6 </h:inputtext> 7 <h:message for="ed" /> 8 <h:commandbutton value="update" /> 9 </h:panelgrid> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

67 Konvertierung und Validierung Konvertierung und Validierung Validator StateHolder StateHolder Wiederverwendung Validatoren Sinnvoll, spart Speicherallokation Durch Angabe Ziffern sind Instanzen von EvenDigitsValidator parametrisiert und damit zustandsbehaftet sind StateHolder Je nach Verwendung anders parametrisiert Zustand austauschbar Entwickler legt fest was und wie mit savestate und restorestate Es muss noch angegeben werden, dass gespeichert werden darf istransient, Setter dann auch Zwang EvenDigitsValidator.java 1 boolean istrans = false; 2 public void restorestate(facescontext fc, 3 Object o) { 4 this.digits = (Integer) o; 5 } 6 public Object savestate(facescontext fc) { 7 return this.digits; 8 } 9 public void settransient(boolean b) { 10 this.istrans = b; 11 } 12 public boolean istransient() { 13 return this.istrans; 14 } Im Beispiel: Zustand in Anzahl der Ziffern Default 3, kann aber gesetzt werden Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Taglibs Flexible Validatoren nur als Taglib Falls Attribute, dann Deklaration der Attribute notwendig Deklaration nur bei eigenem Tag-Namen möglich Deklaration in Taglib notwendig Taglib XML-Datei Sollte Endung.taglib.xml haben Muss in web.xml deklariert werden (oder in JARS unter META-INF) Assoziiert Tag-Name mit Validator-ID Deklariert Attribute web.xml 1 <context-param> 2 <param-name>javax.faces.facelets_libraries</param-name> 3 <param-value>/web-inf/mytags.taglib.xml</param-value> 4 </context-param> mytags.taglib.xml 1 <facelet-taglib 2 xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 4 xsi:schemalocation="http://xmlns.jcp.org/xml/ns/javaee 5 6 version="2.2"> 7 <namespace>myfaceletstags</namespace> 8 <tag> 9 <tag-name>validateeven</tag-name> 10 <validator> 11 <validator-id>evendigits</validator-id> 12 </validator> 13 <attribute> 14 <name>digits</name> 15 <required>true</required> 16 </attribute> 17 </tag> 18 </facelet-taglib> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Konvertierung und Validierung Konvertierung und Validierung Validator Setze Anzahl Ziffern Taglib zur Verfügung stellen Als Namespace, Zeile 5 Neues Tag verwenden Dann intuitiv und einfach, Zeile 15 Fazit: Sehr aufwendig für Programmierer, aber einfach für Verwender! 1 <html xmlns="http://www.w3.org/1999/xhtml" 2 xmlns:f="http://xmlns.jcp.org/jsf/core" 3 xmlns:h="http://xmlns.jcp.org/jsf/html" 4 xmlns:ui="http://xmlns.jcp.org/jsf/facelets" 5 xmlns:my="myfaceletstags" > 6 <h:head> 7 <title>evendigits.xhtml</title> 8 </h:head> 9 <h:body> 10 <h:form> 11 <h:panelgrid columns="3"> 12 <h:outputlabel for="ed" 13 value="gerade Zahl mit 2 Ziffern" /> 14 <h:inputtext id="ed" value="#{bb.zahl}"> 15 <my:validateeven digits="2" /> 16 </h:inputtext> 17 <h:message for="ed" /> 18 <h:commandbutton value="update" /> 19 </h:panelgrid> Bean-Validation Ausblick Problem Validierung über Schichtgrenzen, gleiche Einschränkungen bei UI-, Anwendungs- und Persistenzschicht Mehrfache Implementierung: Mehraufwand, fehleranfällig, Änderungen nicht synchron Lösungsansatz Bean-Validation Bean-Validation, JSR-303 Meta-Datenmodell und Java-API zur Bündelung von Constraints an Daten Validierungsregeln mit Annotationen Benutzerdefinierte Constraints auch möglich Integration automatisch Aber leider noch nicht der volle Funktionsumfang verfügbar Extension Validator schließt Lücken Kleines erzwingt Konfiguration javax.faces.interpret_empty_string_submitted_values_as_null auf true in web.xml Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

68 Komposition und Templating Komposition und Templating Komposition und Templating Ziel Modularer Seitenaufbau Zusammenfassung von Komponenten/Teilseiten zu Modulen Wiederverwendung von Seitenteilen und Komponenten Ohne komplexe Definition von Tag-Libraries Voraussetzung: Facelets, dadurch deklarative Beschreibung des UI, strukturiertes XML (XHTML), Komponentenbaum Lösung Komposition und Templates, Facelets mit <html... xmlns:ui="http://xmlns.jcp.org/jsf/facelets"> Komposition Komponenten mit <ui:composition>, alles außerhalb des Tags ignorieren Zusammenbau mit <ui:include>, Seite aus Komponenten Parameter erlaubt Templating Templates (vollständiges Dokument) mit Platzhaltern <ui:insert> Verwenden mit <ui:composition> und ausfüllen mit <ui:define> Mischen und Verschachteln beliebig möglich Komposition Komponenten/Module Vollständige XHTML-Dokumente Beinhaltet genau ein <ui:compostion> Alles außerhalb dieses <ui:compostion>-tags wird ignoriert Darin alle Tags erlaubt Komposition Vollständiges XHTML-Dokument Mindestens ein <ui:include>-tag Absoluter oder relativer Pfad Meist absolut unter /WEB-INF Inkludiert Komponenten/Module header.xhtml 1 <h:body> 2 <ui:composition> 3 <h3> Immer am Anfang der Seite </h3> 4 </ui:composition> 5 </h:body> copyright.xhtml 1 <h:body> 2 Das wird ignoriert! 3 <ui:composition> 4 <div style="text-align: center"> 5 Copyright </div> 7 </ui:composition> 8 </h:body> page.xhtml 1 <h:body> 2 <ui:include src="header.xhtml" /> 3 <p> Dazwischen. </p> 4 <ui:include src="copyright.xhtml" /> 5 </h:body> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Komposition und Templating Komposition und Templating Komposition Parameter Ziel Seitenteile parametrisieren Parameter verwenden Innerhalb von <ui:composition> Einfach Parameternamen in ExpressionLanguage-Ausdruck verwenden Parameter definieren Innerhalb von <ui:include> <ui:param>-tag mit name- und value-attribut Innerhalb von value kann beliebiger Expression-Language Ausdruck verwendet werden Damit auch Werte von Backing-Beans headerparam.xhtml 1 <h:body> 2 <ui:composition> 3 <h3> Immer am Anfang von #{title} </h3> 4 </ui:composition> 5 </h:body> pageparam.xhtml 1 <h:body> 2 <ui:include src="headerparam.xhtml"> 3 <ui:param name="title" value="super Titel"/> 4 </ui:include> 5 <p> Dazwischen. </p> 6 <ui:include src="copyright.xhtml" /> 7 </h:body> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Templating Template Definition Vollständiges XHTML-Dokument mit Platzhaltern <ui:insert>-tags mit name-attribut Default Inhalt ist Inhalt des Tags Template Verwendung <ui:composition>-tag template-attribut Innerhalb <ui:define>-tags mit name-attribut, ersetzen Platzhalter Mischen (Komposition/Templating) erlaubt template.xhtml 1 <h:head> 2 <title><ui:insert name="title"/></title> 3 </h:head> 4 <h:body> 5 <h3> Immer am Anfang von 6 <ui:insert name="title">titel</ui:insert> 7 </h3> 8 <p> <ui:insert name="content">inhalt</ui:insert> </p> 9 <div style="text-align: center"> 10 Copyright </div> 12 </h:body> tpage.xhtml 1 <h:body> 2 <ui:composition template="template.xhtml"> 3 <ui:define name="title"> 4 Super Titel 5 </ui:define> 6 <ui:define name="content"> 7 Dazwischen. 8 </ui:define> 9 </ui:composition> 10 </h:body> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

69 Komposition und Templating Komposition und Templating Templates in Templates Teilweise ausgefüllte Templates sind wieder Templates und können wieder ausgefüllt werden templateeins.xhtml 1 <h:body> 2 <ui:composition template="template.xhtml"> 3 <ui:define name="title">eins</ui:define> 4 </ui:composition> 5 </h:body> templatezwei.xhtml 1 <h:body> 2 <ui:composition template="template.xhtml"> 3 <ui:define name="title">zwei</ui:define> 4 </ui:composition> 5 </h:body> templateeinsa.xhtml 1 <h:body> 2 <ui:composition template="templateeins.xhtml"> 3 <ui:define name="content">a</ui:define> 4 </ui:composition> 5 </h:body> templateeinsb.xhtml 1 <h:body> 2 <ui:composition template="templateeins.xhtml"> 3 <ui:define name="content">b</ui:define> 4 </ui:composition> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte 5 </h:body> Anwendungen 6. Juli / 295 Mehrere Templates in einer Seite Ziel Mehrere Templates in einer Seite verwenden Problem Alles wegwerfen <ui:composition> klappt nicht, es wird alles außerhalb weggeworfen Lösung Neues Tag <ui:decorate> Verhalten wie <ui:composition> Aber umgebender Inhalt wird nicht entfernt linksrechtstemplate.xhtml 1 <h:body> 2 <ui:composition> 3 <table><tr><td> 4 <ui:insert name="links">links</ui:insert> 5 </td><td> 6 <ui:insert name="rechts">rechts</ui:insert> 7 </td></tr></table> 8 </ui:composition> 9 </h:body> linksrechtspage.xhtml 1 <h:body> 2 <ui:composition template="template.xhtml"> 3 <ui:define name="title">links Rechts Seite 4 </ui:define> 5 <ui:define name="content"> 6 <ui:decorate template="linksrechtstemplate.xhtml"> 7 <ui:define name="links">linke Seite</ui:define> 8 <ui:define name="rechts">rechte Seite</ui:define> 9 </ui:decorate> 10 </ui:define> 11 </ui:composition> 12 </h:body> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Komposition und Templating Ressourcen-Management Wiederholungen Ressourcen-Management <ui:repeat> Nur für die Ausgabe Ersatz für <c:foreach> Funktioniert mit Facelets Verschachtelung erlaubt Attribute value Iterierbare Kollektion var Laufvariable varstatus, offset, step Bedingte Ausgabe Konditionale Ausdrücke oder rendered-attribut Empfehlung: Vermeiden <h:datatable> verwenden 1 <ul> 2 <ui:repeat var="nb" 3 value="#{dmbb.liste}"> 4 <li>#{nb.vorname} #{nb.nachname}</li> 5 </ui:repeat> 6 </ul> Ressourcen Bilder, Skripte (JavaScript), Stylesheets (CSS) Meist direkte Einbindung über absoluten Pfad (innerhalb der Web-Anwendung) Probleme mit Ressourcen Bei Komponentenbibliotheken will man nur ein JAR und nicht noch Verzeichnisse kopieren Ort für die Festlegung muss je Seite in speziellem Bereich (Header) erfolgen Lösung Ressourcen-Management Generierung des HTML-Headers, <h:head> statt <head> Dadurch können Skript und Stylesheets an jeder Stelle verwendet werden, JSF sammelt diese gibt alle notwendigen in <head> aus Neue Tags: <h:graphicimage>, <h:outputscript>, <h:outputstylesheet> Standardisierter Ressourcenzugriff: Integration in Expression Language, Versionierung, Lokalisierung Für Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

70 Ressourcen-Management Ressourcen-Management Rahmen und Namen Bibliotheken, Expression Language Rahmen Statt <head> und <body> immer <h:head> und <h:body> JSF-Implementierung entscheidet was zu <head> und <body> kommt Neue Tags <h:graphicsimage> Attribute name, Namen der Ressource Namensauflösung JSF löst Namen auf, sucht Ressource an mehreren Stellen /resources, in der Web-Anwendung In allen JAR-Dateien (und classpath) unter /META-INF/resources Beispiel: HSRM-Logo 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml" 4 xmlns:f="http://xmlns.jcp.org/jsf/core" 5 xmlns:h="http://xmlns.jcp.org/jsf/html" 6 xmlns:ui="http://xmlns.jcp.org/jsf/facelets"> 7 <h:head> 8 <title>das HSRM-Logo</title> 9 </h:head> 10 <h:body> 11 <h:graphicimage name="hsrmlogo.png"/> 12 </h:body> 13 </html> Pfad: resources/hsrmlogo.png Bibliotheken Attribut library, Unterordner Expression-Language erlaubt Expression Language resource-objekt, existiert immer, Pfadgenerierung value-attribut für Pfadzugriff Geht dann auch im img-tag Beispiel: Sun-Logo Mit <h:graphicimage>, so verwenden Festlegung Bibliothek/Namen mit Expression Language möglich Implizites resource-objekt Direkte Pfadangabe, gib generierten Pfad aus (nicht verwenden) 1 Sun-Logo, Library: 2 <h:graphicimage 3 library="images" 4 name="sunlogo.png"/> 5 <br /> 6 Sun-Logo, Pfad: 7 <h:graphicimage 8 value="#{resource[ images:sunlogo.png ]}" /> 9 <br /> 10 Sun-Logo, img-tag: 11 <img src="#{resource[ images:sunlogo.png ]}" /> 12 <br /> 13 Im Pfad 14 <h:outputtext 15 value="#{resource[ images:sunlogo.png ]}" /> /resources/images/sunlogo.png Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Ressourcen-Management Ressourcen-Management Versionierung Problem Aktualisierung von Ressourcen Teilweise, alte Anwendungsteile und Inkompatibilitäten, noch alte Versionen notwendig Mehrere Versionen müssen koexistieren Lösung Versionierung Mit Unterstrich getrennte Versionsnummer, Teil der Pfadangabe Bei Libraries und bei Ressourcen Bei Ressourcen wird Name zu Ordner Bei Auflösung ohne Versionsnummer wird automatisch die höchste gewählt Explizite Angabe der Versionsnummer erlaubt 1 <h:graphicimage library="images" 2 name="logo.png"/> <br /> 3 <h:graphicimage library="images/2_0" 4 name="logo.png"/> <br /> 5 <h:graphicimage library="images/2_1" 6 name="logo.png"/> <br /> 7 <h:graphicimage library="images" 8 name="logo.png/1_0.png"/> <br /> 9 <h:graphicimage library="images/2_0" 10 name="logo.png/1_0.png"/> <br /> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Internationalisierung und Lokalisierung Ressourcen Bei Ressourcen javax.faces.resources.localeprefix Beim Suchpfad am Anfang mit eingefügt Zusätzlich Versionierung zulässig in Theorie, in Praxis Problem Ressource wird nicht gefunden Fix: Manuell Locale einfügen als library Zugriff mit view.locale Setzen für Seite mit <f:view locale="de">... </f:view> 1 Locale: 2 <h:outputtext value="#{view.locale}" /><br /> 3 Richtig funktioniert nicht, de: 4 <h:graphicimage id="fehler" 5 name="daygreeting.png"/><br /> 6 <h:message for="fehler"/><br /> 7 Manuell geht, de: 8 <h:graphicimage library="#{view.locale.tostring()}" 9 name="daygreeting.png"/><br /> 10 Manuell geht, fr: 11 <h:graphicimage library="fr" 12 name="daygreeting.png"/> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

71 Ressourcen-Management Eigene Komponenten Internationalisierung und Lokalisierung Texte Allgemein, JSF ähnlich zu JSP Basierend auf Locale Verwenden Zugriff über expression language Je Seite: Bundle wählen mit <f:loadbundle> Für ganze Anwendung: <resource-bundle> in faces-config.xml faces-config.xml 1 <application> 2 <locale-config> 3 <default-locale>de</default-locale> 4 <supported-locale>de</supported-locale> 5 <supported-locale>fr</supported-locale> 6 </locale-config> 7 <resource-bundle> 8 <base-name>webanw.texte</base-name> 9 <var>texte</var> 10 </resource-bundle> 11 </application> 1 Locale: <h:outputtext value="#{view.locale}" /> 2 <br /> 3 Global: <h:outputtext value="#{texte.hello}" /> 4 <br /> 5 <f:loadbundle basename="webanw.texte" var="ltexte"/> 6 Lokal: <h:outputtext value="#{ltexte.hello}" /> 1 <f:view locale="fr"> 2 Locale: <h:outputtext value="#{view.locale}" /> 3 <br /> 4 Hello: <h:outputtext value="#{texte.hello}" /> 5 </f:view> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Eigene Komponenten Definieren composite Ziel Einfache Realisierung von Komponenten ohne Java-Code XHTML, keine weitere Konfiguration Lösung Composites Neuer Namensraum, composite Spezieller Ordner resources/components, keine weitere Konfiguration notwendig Interface, Implementation Beispiel Eigenes Tag mylist statt direkt Klassen für Darstellung gerade/ungerade als Attribute resources/components/mylist.xhtml 1 <html xmlns="http://www.w3.org/1999/xhtml" 2 xmlns:f="http://xmlns.jcp.org/jsf/core" 3 xmlns:h="http://xmlns.jcp.org/jsf/html" 4 xmlns:ui="http://xmlns.jcp.org/jsf/facelets" 5 xmlns:composite="http://xmlns.jcp.org/jsf/composite"> 6 <h:head><title>mylist</title></h:head> 7 <h:body> 8 <composite:interface> 9 <composite:attribute name="value" /> 10 <composite:attribute name="oddstyle" /> 11 <composite:attribute name="evenstyle" /> 12 </composite:interface> 13 <composite:implementation> 14 <ul> 15 <ui:repeat var="item" value="#{cc.attrs.value}" 16 varstatus="status"> 17 <ui:fragment rendered="#{status.even}"> 18 <li class="#{cc.attrs.evenstyle}"> #{item} </li> 19 </ui:fragment> 20 <ui:fragment rendered="#{status.odd}"> 21 <li class="#{cc.attrs.oddstyle}"> #{item} </li> 22 </ui:fragment> ui:repeat 23 </ui:repeat> 24 </ul> 25 </composite:implementation> 26 </h:body> 27 </html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Eigene Komponenten Ajax und Single Page Eigene Komponenten Verwenden components Bereitstellen UI-Library und Name des Unterordners nach composite im Beispiel components Konvention ist gleicher Name im Präfix Stylesheet Unabhängige Ressource Einbindung wird automatisch im Header gerendert /resources/css/style.css 1.gerade { 2 background-color: green; 3 } 4.ungerade { 5 background-color: red; 6 } 1 <html xmlns="http://www.w3.org/1999/xhtml" 2 xmlns:f="http://xmlns.jcp.org/jsf/core" 3 xmlns:h="http://xmlns.jcp.org/jsf/html" 4 xmlns:ui="http://xmlns.jcp.org/jsf/facelets" 5 xmlns:components= 6 "http://xmlns.jcp.org/jsf/composite/components"> 7 <h:head> 8 <title>mylist verwenden</title> 9 </h:head> 10 <h:body> 11 <h:outputstylesheet library="css" name="style.css" /> 12 <components:mylist value="#{bb.liste}" 13 oddstyle="ungerade" evenstyle="gerade"> 14 </components:mylist> 15 </h:body> 16 </html> Ajax und Single Page Anwendungen Problem Seite Neu Laden Änderungen einer Web-Seite erfordert komplettes Neugenerieren und Neuladen der Seite vom Server Unterschied bei vielen Seiten minimal Eingabe forciert Änderung in einem Nachbarfeld Ticker ändert einen Wert kontinuierlich Ziel Partieller Update Web-Seite bleibt (Single Page Anwendung), nur Teile/Komponenten der Seite werden aktualisiert Interaktiver, reaktiver, weniger Datenverkehr Umsetzung: Ajax, Asynchronuous JavaScript And XML Technische Grundlage: XMLHttpRequestObject Jesse James Garret prägt Begriff Server Server Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

72 Ajax und Single Page Ajax und Single Page JavaScript Asynchroner Rückkanal XMLHttpRequest Historie Einsatz im Browser 1995, Netscape Navigator, LiveScript/JavaScript Ziel: Interaktivitiät, dynamisch Web-Seiten gestalten 1998, ECMA, Standardisierung 2000, Version 1.5, Basis-Featuresatz, können alle 2010, Version 1.9, ECMA-262, können fast alle Sprachfeatures OO-Skriptsprache Objektorientierte Skriptsprache, dynamische Typen, funktional (innere Funktionen und Closures), Prototypen-basiert, reguläre Ausdrücke, Dictionaries Klammern/Struktur C/Java, hat nichts mit Java zu tun Effiziente Implementierung in modernen Browsern Dynamic HTML, DHTML Begriff Techniken interaktiver/animierter Web-Seiten DOM/CSS-Manipulation mit JavaScript Zu GUI-Apps aufschließen, initial Eye-Candy eins drei zehn Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Historie 1999, IE 5.0, für Outlook Web Access 2000/2002 Mozilla 2005/2006 Standardisiert, Verfügbar (Desktop) Ziel Kanal zwischen Web-Browser und -Server Von Prog.sprache aus (JavaScript), asynchron Transport von Daten (nicht ganze Seite) XML als Datencontainer (heute JSON) Aktualisieren von Daten ohne Seite neu zu laden API open(string method, String url, bool async); method = GET PUT HEAD url = URL für HTTP-Datenanfrage async = true, genau dann wenn asynchron Zustandsbehaftet, Abfrage ob Download fertig Server XMLHttp Request Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Ajax und Single Page Ajax und Single Page Ajax Ergebnis Ajax und JSF Ajax Asynchronuous JavaScript and XML Asynchrones Laden von zu aktualisierenden Daten Benutzeroberfläche bleibt bedienbar Manipulation Anzeige, DHTML Partieller Seiten-Update Ergebnis Interaktive Web-Seite Rich, Look & Feel einer Desktop GUI-App Schnell, reagierend, nicht blockierend Probleme JavaScript JavaScript muss aktiviert sein Potenziell Performance-Fresser auf PC Kompatibilitätsprobleme, jede Client-Engine anders JavaScript Libraries nicht mehr händisch Heutzutage meistens jquery 42 Server XMLHttp Request 42 Einfach, fast perfekt seit JSF 2.0 Ajax-Integration war wichtigstes Ziel bei JSF 2.0 <f:ajax>, Deklaration der sich potenziell ändernden Komponenten bei partiellen Seiten-Update Lebenszyklus angepasst für partielles Rendern, nur potenziell geänderte Komponenten durchlaufen Lebenszyklus Native Unterstützung für partielles Seitenrendern, JavaScript-Library kommt mit Vollständiges Verstecken von JavaScript möglich! Vor JSF 2.0 Durchgriff möglich Riesenproblem mit Lebenszyklus, es musste immer ganze Seite gerendert werden Eigene inkompatible Erweiterungen der verschiedenen Anbieter: MyFaces, IceFaces, PrimeFaces,... Alles sehr böse (aber InHouse-Apps laufen auch schnell und stabil mit kompletten Seitenaufbau) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

73 Ajax und Single Page Ajax und Single Page Beispiel Single Page App mit Ajax Beispiel Ausgangssituation Eingabe-Seite mit Ausgabebereich Ausgabe-Bereich geht von Name bis Alter, aktuelles Datum separat Ok(Ajax): Datum (außerhalb Ausgabe) bleibt, nicht neu gerendert Ok(Seite): Die ganze Seite, und damit das Datum, wird aktualisiert Neuer Mittelname XXX, Ok(Ajax) Neuer Mittelname YYY, Ok(Seite) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Beispiel <f:ajax> Aufbau Aufbau, JSF-Standard Alle Tags wie gewohnt Ein neues zusätzliches Tag <f:ajax> bei erstem Button, axafiziert Eingabe <f:ajax>-tag render: Mit id spezifierte Part (Komponente) wird gerendert execute: Ausführen des mit id spezifierten Parts, schicken umschließende Form, explizite id möglich event: Wenn was passiert? Vorgabe action bei command* oder onchange bei input* Alle on* nur ohne on 1 <h:form> 2 <h:panelgrid columns="2" id="eingabe"> 3 Vorname <h:inputtext value="#{namebean.vorname}"/> 4 Mittelname <h:inputtext value="#{namebean.mittelname}"/> 5 Nachname <h:inputtext value="#{namebean.nachname}"/> 6 Alter <h:inputtext value="#{namebean.alter}"/> 7 </h:panelgrid> 8 <h:commandbutton action="#{namebean.gueltig}" 9 value="ok(ajax)"> 10 <f:ajax render="ausgabe" 11 event="action" /> 12 </h:commandbutton> 13 <h:commandbutton action="#{namebean.gueltig}" 14 value="ok(seite)"/> 15 </h:form> 16 <h:panelgrid columns="2" id="ausgabe"> 17 Hallo <h:outputtext value="#{namebean.name}"/> 18 Vorname <h:outputtext value="#{namebean.vorname}"/> 19 Mittelname <h:outputtext value="#{namebean.mittelname}"/> 20 Nachname <h:outputtext value="#{namebean.nachname}"/> 21 Alter <h:outputtext value="#{namebean.alter}"/> 22 </h:panelgrid> 23 <center> #{bb.jetzt} </center> Mehrere Teile bei render, durch Leerzeichen getrennt Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Ajax und Single Page Ajax und Single Page Beispiel <f:ajax> Ablauf Client, Web-Browser Benutzer klickt Ok(Ajax) Deklaratives Ajax-Tag Klick löst JavaScript aus, kein Neu-Laden der Seite Wege wird alles im ersten panelgrid (Form) zum Server geschickt Server Lebenszyklus läuft für Komponenten der Form Aktualisieren der Beans Nicht rendern, aber Daten für rendering des ausgabe-bereichs extrahieren und zum Client schicken 1 <h:form> 2 <h:panelgrid columns="2" id="eingabe"> 3 Vorname <h:inputtext value="#{namebean.vorname}"/> 4 Mittelname <h:inputtext value="#{namebean.mittelname}"/> 5 Nachname <h:inputtext value="#{namebean.nachname}"/> 6 Alter <h:inputtext value="#{namebean.alter}"/> 7 </h:panelgrid> 8 <h:commandbutton action="#{namebean.gueltig}" 9 value="ok(ajax)"> 10 <f:ajax render="ausgabe" 11 event="action" /> 12 </h:commandbutton> 13 <h:commandbutton action="#{namebean.gueltig}" 14 value="ok(seite)"/> 15 </h:form> 16 <h:panelgrid columns="2" id="ausgabe"> 17 Hallo <h:outputtext value="#{namebean.name}"/> 18 Vorname <h:outputtext value="#{namebean.vorname}"/> 19 Mittelname <h:outputtext value="#{namebean.mittelname}"/> 20 Nachname <h:outputtext value="#{namebean.nachname}"/> 21 Alter <h:outputtext value="#{namebean.alter}"/> 22 </h:panelgrid> 23 <center> #{bb.jetzt} </center> Client: Empfang Daten, Aktualisieren DOM des ausgabe Bereichs Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Beispiel Klappen Rechts: Zk1 Ok(Ajax), Zk1 Update(Ajax), Zk2 Update(Seite) Unten: Nicht Zk2 zeigen Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

2. Interaktive Web Seiten. action in Formularen. Formular. Superglobale Variablen $ POST, $ GET und $ REQUEST. GET und POST

2. Interaktive Web Seiten. action in Formularen. Formular. Superglobale Variablen $ POST, $ GET und $ REQUEST. GET und POST 2. Interaktive Web Seiten GET und POST Die Übertragungsmethoden GET und POST sind im http Protokoll definiert: POST: gibt an, dass sich weitere Daten im Körper der übertragenen Nachricht befinden: z.b.

Mehr

php Hier soll ein Überblick über das Erstellen von php Programmen gegeben werden. Inhaltsverzeichnis 1.Überblick...2 2.Parameterübergabe...

php Hier soll ein Überblick über das Erstellen von php Programmen gegeben werden. Inhaltsverzeichnis 1.Überblick...2 2.Parameterübergabe... php Hier soll ein Überblick über das Erstellen von php Programmen gegeben werden. Inhaltsverzeichnis 1.Überblick...2 2.Parameterübergabe...7 3.Zugriff auf mysql Daten...11 Verteilte Systeme: php.sxw Prof.

Mehr

9 Dynamisches Erzeugen von Webseiten

9 Dynamisches Erzeugen von Webseiten 9 Dynamisches Erzeugen von Webseiten 9.1 CGI CGI (Common Gateway Interface) Skripte erlauben die dynamische Erzeugung von Dokumenten auf dem Webserver. Typische Anwendung: CGI-Skripte verarbeiten Eingaben

Mehr

PHP-Schwachstellen und deren Ausnutzung

PHP-Schwachstellen und deren Ausnutzung PHP-Schwachstellen und deren Ausnutzung 44. DFN Betriebstagung / 7. Februar 2006 DFN-CERT Services GmbH Jan Kohlrausch / CSIRT Gliederung Grundlagen HTTP und PHP Anatomie typischer Schwachstellen in PHP-Skripten

Mehr

Datenbank-basierte Webserver

Datenbank-basierte Webserver Datenbank-basierte Webserver Datenbank-Funktion steht im Vordergrund Web-Schnittstelle für Eingabe, Wartung oder Ausgabe von Daten Datenbank läuft im Hintergrund und liefert Daten für bestimmte Seiten

Mehr

Proseminar: Website-Management-Systeme

Proseminar: Website-Management-Systeme Proseminar: Website-Management-Systeme Thema: Web: Apache/Roxen von Oliver Roeschke email: o_roesch@informatik.uni-kl.de Gliederung: 1.) kurze Einleitung 2.) Begriffsklärung 3.) Was ist ein Web? 4.) das

Mehr

Crashkurs http - CGI/Servlets(JSF) - Viewer

Crashkurs http - CGI/Servlets(JSF) - Viewer jkrueger(at)cebitec.uni-bielefeld.de http TCP Referenzmodell : ApplicationLayer zustandloses Protokoll textbasiert für Hypertext entwickelt ist es nicht darauf beschränkt Nachrichten : Request : Client

Mehr

CGI-Programmierung. Fachhochschule Wiesbaden Fachbereich Design-Informatik-Medien Prof. Dr. Weber 15. Dezember 2008

CGI-Programmierung. Fachhochschule Wiesbaden Fachbereich Design-Informatik-Medien Prof. Dr. Weber 15. Dezember 2008 CGI-Programmierung Fachhochschule Wiesbaden Fachbereich Design-Informatik-Medien Prof. Dr. Weber 15. Dezember 2008 Alexander Petitjean - Alexander.Petitjean@YMail.com Yelena Kolpakova - Yelena.K@gmx.de

Mehr

Apache HTTP-Server Teil 2

Apache HTTP-Server Teil 2 Apache HTTP-Server Teil 2 Zinching Dang 04. Juli 2014 1 Benutzer-Authentifizierung Benutzer-Authentifizierung ermöglicht es, den Zugriff auf die Webseite zu schützen Authentifizierung mit Benutzer und

Mehr

Web 2.0 Software-Architekturen

Web 2.0 Software-Architekturen Web 2.0 Software-Architekturen Servlets als Controller einer MVC Web Architektur Prof. Dr. Nikolaus Wulff HTTP und HTML Das HyperText TransferProtokoll (HTTP) beschreibt eine einfache verbindungslose Kommunikation,

Mehr

Web-Seiten als Programmoberflächen - CGI-Scripte selbst erstellt

Web-Seiten als Programmoberflächen - CGI-Scripte selbst erstellt Seite 18 Ausgabe 20 - Dezember 2000 ZPG-Mitteilungen für gewerbliche Schulen Web-Seiten als Programmoberflächen - CGI-Scripte selbst erstellt Der unter Linux übliche WEB-Server Apache bietet die Möglichkeit

Mehr

Fortgeschrittene Servlet- Techniken. Ralf Gitzel ralf_gitzel@hotmail.de

Fortgeschrittene Servlet- Techniken. Ralf Gitzel ralf_gitzel@hotmail.de Fortgeschrittene Servlet- Techniken Ralf Gitzel ralf_gitzel@hotmail.de 1 Themenübersicht Ralf Gitzel ralf_gitzel@hotmail.de 2 Übersicht Servlet Initialisierung Attribute und Gültigkeitsbereiche Sessions

Mehr

Herzlich willkommen im Modul Web-Engineering

Herzlich willkommen im Modul Web-Engineering Herbst 2014 Herzlich willkommen im Modul Web-Engineering Wirtschaftsinformatik: 5. Semester Dozenten: Rainer Telesko / Martin Hüsler Fachhochschule Nordwestschweiz FHNW / Martin Hüsler und Rainer Telesko

Mehr

Rechnernetze Übung 12

Rechnernetze Übung 12 Rechnernetze Übung 12 Frank Weinhold Professur VSR Fakultät für Informatik TU Chemnitz Juli 2011 Sie kennen sicherlich sogenannte Web-Mailer, also WWW-Oberflächen über die Sie Emails lesen und vielleicht

Mehr

Web-Anwendungsentwicklung mit dem Delivery Server

Web-Anwendungsentwicklung mit dem Delivery Server Web-Anwendungsentwicklung mit dem Delivery Server Java-Framework auf Basis der Open API Bernfried Howe, Webertise Consulting GmbH WEBertise Consulting Dipl. Informatiker (Wirtschaftsinformatik) 2001-2010

Mehr

Session Management und Cookies

Session Management und Cookies LMU - LFE Medieninformatik Blockvorlesung Web-Technologien Wintersemester 2005/2006 Session Management und Cookies Max Tafelmayer 1 Motivation HTTP ist ein zustandsloses Protokoll Je Seitenaufruf muss

Mehr

Dynamische Webseiten

Dynamische Webseiten Dynamische Webseiten Seminar Medientechnik 30.06.2003 Dynamische Webseiten 1 Inhalt Allgemeine Funktionsweise eines Webservers Grundgedanke von dynamischen Webseiten Einschub: Dynamische Seitenerzeugung

Mehr

Hochschule Darmstadt Fachbereich Informatik

Hochschule Darmstadt Fachbereich Informatik Hochschule Darmstadt Fachbereich Informatik 6.3 Systemarchitektur 430 6.3 Systemarchitektur Drei Schichten Architektur Die "Standardtechniken" des Software-Engineering sind auch auf die Architektur einer

Mehr

4. Servlets Ein kleiner Einstieg. Kurze Java Historie. Erinnerung: Internet Anwendungen. Konzept eines Seitenaufrufs

4. Servlets Ein kleiner Einstieg. Kurze Java Historie. Erinnerung: Internet Anwendungen. Konzept eines Seitenaufrufs 4. s Ein kleiner Einstieg Erinnerung: HTTP und HTML Idee von Web n und Containern Erstellung einfacher s (zunächst software technisch übelst unstrukturiert) Literatur: B. Basham, K. Sierra, B. Bates, Head

Mehr

!"# $ % Internet Protokolle: HTTP 1/38

!# $ % Internet Protokolle: HTTP 1/38 !"# $ % Internet Protokolle: HTTP 1/38 1 Themenübersicht Schichtenmodell Gopher /FTP Statistik URL Einleitung Anwendungsablauf Beispiel mit Telnet Request, Response Anfragemethoden header Negotiation Proxyserver

Mehr

Perl-Praxis. CGI-Skripte. Michael Beckstette Martin Mann, Steffen Heyne. {mbeckste,mmann,sheyne}@informatik.uni-freiburg.de

Perl-Praxis. CGI-Skripte. Michael Beckstette Martin Mann, Steffen Heyne. {mbeckste,mmann,sheyne}@informatik.uni-freiburg.de Perl-Praxis CGI-Skripte Michael Beckstette Martin Mann, Steffen Heyne {mbeckste,mmann,sheyne}@informatik.uni-freiburg.de 1 Übersicht WWW, Web-Server CGI-Skripte Parameterübergabe Web-Formulare CGI.pm 2

Mehr

Dynamik bis zur DB-Interaktion. Marc Schanne. CGI Möglichkeiten

Dynamik bis zur DB-Interaktion. Marc Schanne. CGI Möglichkeiten CGI einfach PHP Dynamik bis zur DB-Interaktion 1 CGI Möglichkeiten Das Common Gateway Interface (CGI) ermöglicht den Entwurf von interaktiven, benutzergesteuerten Web-Applikationen. Der WWW-Server ruft

Mehr

Web-Programmierung (WPR)

Web-Programmierung (WPR) Web-Programmierung (WPR) Vorlesung VIII. Common Gateway Interface(CGI) & PHP mailto:wpr@gruner.org 1 12 Common Gateway Interface Von allen Webservern unterstützt Anzubindende Programme => Gateway zu bestehenden

Mehr

PHP Einsteiger Tutorial Kapitel 4: Ein Email Kontaktformular in PHP Version 1.0 letzte Änderung: 2005-02-03

PHP Einsteiger Tutorial Kapitel 4: Ein Email Kontaktformular in PHP Version 1.0 letzte Änderung: 2005-02-03 PHP Einsteiger Tutorial Kapitel 4: Ein Email Kontaktformular in PHP Version 1.0 letzte Änderung: 2005-02-03 Bei dem vierten Teil geht es um etwas praktisches: ein Emailformular, dass man auf der eigenen

Mehr

Active Server Pages. Internetanbindung von Datenbanken. Gliederung. Einführung in ASP. Sessions mit ASP. Datenbankanbindung mit ASP ASP-1

Active Server Pages. Internetanbindung von Datenbanken. Gliederung. Einführung in ASP. Sessions mit ASP. Datenbankanbindung mit ASP ASP-1 Internetanbindung von Datenbanken Active Server Pages ASP-1 Gliederung Einführung in ASP Sessions mit ASP Datenbankanbindung mit ASP Brunner, Fromm, Huppert ASP-2 Einführung in ASP ASP-3 Entwicklung des

Mehr

Informatik und Programmiersprachen

Informatik und Programmiersprachen Informatik und Programmiersprachen Einschub: HTML Wintersemester 2004/2005 Prof. Dr. Thomas Wieland HTML HTML = Hypertext Markup Language HTML beschreibt Inhalt, Struktur und Darstellung eines Dokumentes.

Mehr

REST Grundlagen. Seminar Aktuelle Software-Engineering-Praktiken für das World Wide Web. Olga Liskin

REST Grundlagen. Seminar Aktuelle Software-Engineering-Praktiken für das World Wide Web. Olga Liskin <olga.liskin@gmail.com> REST Grundlagen Seminar Aktuelle Software-Engineering-Praktiken für das World Wide Web Olga Liskin Übersicht Motivation, Einführung Architekturstil REST RESTful Webservices Patterns,

Mehr

Dynamische Webanwendungen

Dynamische Webanwendungen Dynamische Webanwendungen Mohamed Said Seminar Moderne Informatik Universität Dortmund SS 2003 Mohamed Said / 2003-05-30 1 Überblick Einleitung (Konzept) Client-seitiges Skripting mit JavaScript CGI Server-seitiges

Mehr

JSP und Servlet Programmierung

JSP und Servlet Programmierung Seminarunterlage Version: 5.02 Copyright Version 5.02 vom 1. März 2013 Dieses Dokument wird durch die veröffentlicht. Copyright. Alle Rechte vorbehalten. Alle Produkt- und Dienstleistungs-Bezeichnungen

Mehr

Internetanbindung von Datenbanken

Internetanbindung von Datenbanken Internetanbindung von Datenbanken http://galahad.informatik.fh-kl.de/~miesel/index.html PHP -1 Gliederung Einführung PHP3 Datenbankanbindung mit PHP3 Sicherheitsprobleme Realisierung mit PHP3 Probleme

Mehr

Apache Tomcat. Inhalt. Rechner und Netzarchitektur SS 2003. Einleitung. Architektur

Apache Tomcat. Inhalt. Rechner und Netzarchitektur SS 2003. Einleitung. Architektur Apache Tomcat Rechner und Netzarchitektur SS 2003 Johannes Jabornig Daniel Peintner Inhalt Einleitung Was sind Servlets und JSP Vorteile Architektur Catalina Jasper Konnektoren Installation / Konfiguration

Mehr

Apache. O'REILLY Beijing Cambridge Farnham Köln Paris Sebastopol Taipei Tokyo. Das umfassende Handbuch. Ben Laurie und Peter Laurie 2.

Apache. O'REILLY Beijing Cambridge Farnham Köln Paris Sebastopol Taipei Tokyo. Das umfassende Handbuch. Ben Laurie und Peter Laurie 2. 2.AUFLAGE Apache Das umfassende Handbuch Ben Laurie und Peter Laurie Deutsche Übersetzung von Peter Klicman, Jochen Wiedmann & Jörgen W. Lang O'REILLY Beijing Cambridge Farnham Köln Paris Sebastopol Taipei

Mehr

Aktuelle Sicherheitsprobleme im Internet: Angriffe auf Web-Applikationen

Aktuelle Sicherheitsprobleme im Internet: Angriffe auf Web-Applikationen FAEL-Seminar Aktuelle Sicherheitsprobleme im Internet: Angriffe auf Web-Applikationen Prof. Dr. Marc Rennhard Institut für angewandte Informationstechnologie InIT ZHAW Zürcher Hochschule für Angewandte

Mehr

Anwendungsprotokolle: HTTP, POP, SMTP

Anwendungsprotokolle: HTTP, POP, SMTP Anwendungsprotokolle: HTTP, POP, SMTP TCP? UDP? Socket? eingesetzt, um Webseiten zu übertragen Zustandslos Nutzt TCP Client schickt Anfrage ( HTTP-Request ) an Server, Server schickt daraufhin Antwort

Mehr

Internetanbindung von Datenbanken

Internetanbindung von Datenbanken Internetanbindung von Datenbanken Python und CGI CGI und Perl-1 Gliederung Die Programmiersprache Python CGI in Python Datenbankanbindung Umsetzungskonzepte Zusammenfassung Realisierung Python und CGI-2

Mehr

Merkblatt: HSM. Version 1.01. Systemvoraussetzungen, Setup und Trouble Shooting. pdfsupport@pdf-tools.com

Merkblatt: HSM. Version 1.01. Systemvoraussetzungen, Setup und Trouble Shooting. pdfsupport@pdf-tools.com Merkblatt: HSM Version 1.01 Systemvoraussetzungen, Setup und Trouble Shooting Kontakt: pdfsupport@pdf-tools.com Besitzer: PDF Tools AG Kasernenstrasse 1 8184 Bachenbülach Schweiz www.pdf-tools.com Copyright

Mehr

Multimedia im Netz Wintersemester 2011/12

Multimedia im Netz Wintersemester 2011/12 Multimedia im Netz Wintersemester 2011/12 Übung 01 Betreuer: Verantwortlicher Professor: Sebastian Löhmann Prof. Dr. Heinrich Hussmann Organisatorisches 26.10.2011 MMN Übung 01 2 Inhalte der Übungen Vertiefung

Mehr

Web-Programmierung (WPR)

Web-Programmierung (WPR) Web-Programmierung (WPR) TFH-Berlin Sommer Semester 2008 Manfred Gruner mailto:wpr@gruner.org Web-Programmierung (WPR) Literatur: Web-Technologien (Heiko Wöhr) Konzepte Programmiermodelle - Architekturen

Mehr

Praktikum: Dynamische Webseiten

Praktikum: Dynamische Webseiten Zürcher Hochschule Winterthur Departement Technik, Informatik und Naturwissenschaften Informationssysteme für die Studiengänge ET, MB, MI, MT Januar 2006 Praktikum: Dynamische Webseiten Einführung Inhalt

Mehr

Aktuelle Sicherheitsprobleme im Internet

Aktuelle Sicherheitsprobleme im Internet Herbst 2014 Aktuelle Sicherheitsprobleme im Internet Wirtschaftsinformatik: 5. Semester Dozenten: Rainer Telesko / Martin Hüsler Fachhochschule Nordwestschweiz FHNW / Rainer Telesko - Martin Hüsler 1 Inhalt

Mehr

DOKUMENTATION. CaptchaAd mit Java. Die Schritte zur Integration des CaptchaAd-Modul im Einzelnen

DOKUMENTATION. CaptchaAd mit Java. Die Schritte zur Integration des CaptchaAd-Modul im Einzelnen CaptchaAd mit Java Stand: 26. Juli 2011 Sehr geehrter Nutzer von CaptchaAd! Damit die Integration von CaptchaAd Ihnen noch leichter fällt, haben wir die notwendigen Schritte in diesem Leitfaden zusammen

Mehr

Sicherheit von Webapplikationen Sichere Web-Anwendungen

Sicherheit von Webapplikationen Sichere Web-Anwendungen Sicherheit von Webapplikationen Sichere Web-Anwendungen Daniel Szameitat Agenda 2 Web Technologien l HTTP(Hypertext Transfer Protocol): zustandsloses Protokoll über TCP auf Port 80 HTTPS Verschlüsselt

Mehr

Programmieren 2 (Prof. Hasbargen) Klausur

Programmieren 2 (Prof. Hasbargen) Klausur Programmieren 2 (Prof. Hasbargen) 1 Klausur Aufgabe 1 (10 Punkte) Dynamisierung von HTML-Seiten HTML-Seiten sind eine gängige Art und Weise, Informationen darzustellen. Nennen Sie die Gründe, welche Vorteile

Mehr

Apache Module Funktion, Konfiguration und Programmierung. Abruf einer Webseite, Request/ Response Cyle

Apache Module Funktion, Konfiguration und Programmierung. Abruf einer Webseite, Request/ Response Cyle Apache Module Funktion, Konfiguration und Programmierung Abruf einer Webseite, Request/ Response Cyle Einbindung von Modulen in Apache Einsatz von Standardmodulen Programmierung von Modulen Request/ Response

Mehr

Ablauf Unit2. Walkthrough

Ablauf Unit2. Walkthrough Ablauf Unit2 Vertiefendes Uebungsprojekt - SQL II Gerhard Wohlgenannt Test Vorstellung der Arbeitsumgebung (Software, Locations) Walkthrough Gruppeneinteilung + Themenvergabe Vorstellung der Arbeitsumgebung

Mehr

Steht in der ersten Zeile #!/usr/bin/python und hat man die Ausführungsrechte gesetzt kann man es direkt ausführen.

Steht in der ersten Zeile #!/usr/bin/python und hat man die Ausführungsrechte gesetzt kann man es direkt ausführen. Python Unter Windows empfiehlt sich der Download von Python unter folgender URL, http:// www.python.org/download/. Linux Distributionen wie z.b. Ubuntu liefern Python direkt in Ihrer Paketverwaltung mit:

Mehr

TimeMachine. Time CGI. Version 1.5. Stand 04.12.2013. Dokument: time.odt. Berger EDV Service Tulbeckstr. 33 80339 München

TimeMachine. Time CGI. Version 1.5. Stand 04.12.2013. Dokument: time.odt. Berger EDV Service Tulbeckstr. 33 80339 München Time CGI Version 1.5 Stand 04.12.2013 TimeMachine Dokument: time.odt Berger EDV Service Tulbeckstr. 33 80339 München Fon +49 89 13945642 Mail rb@bergertime.de Versionsangaben Autor Version Datum Kommentar

Mehr

Internetanbindung von Datenbanken

Internetanbindung von Datenbanken Internetanbindung von Datenbanken Perl und CGI http://galahad.informatik.fh-kl.de/boetcher CGI und Perl-1 Gliederung Einführung CGI Datenbankanbindung mit Perl Realisierung von Sessions Sicherheitsprobleme

Mehr

Installation Anleitung für JTheseus und MS SQL Server 2000

Installation Anleitung für JTheseus und MS SQL Server 2000 Installation Anleitung für JTheseus und MS SQL Server 2000 Inhaltsverzeichnis 1 Installation der Datenbank 3 1.1 Erstellen der Datenbank 3 1.2 Tabellen und Minimal Daten einlesen 4 1.3 Benutzer JTheseus

Mehr

Peter Sobe Internettechnologien. HTTP Protokoll (1) Hypertext Transport Protocol, größtenteils zum Austausch von Hypertext (HTML, xhtml) benutzt

Peter Sobe Internettechnologien. HTTP Protokoll (1) Hypertext Transport Protocol, größtenteils zum Austausch von Hypertext (HTML, xhtml) benutzt WWW Web basierend auf dem Internet Das Internet war bereits eher als das Web vorhanden, mit verteilten Anwendungen, Dateitransfer, Netzwerk- Dateisystemen (NFS) Web: entstanden durch Vorhandensein des

Mehr

Projektvortrag von Andrzej Aftyka, Abdi Leili, Elsa Mahari

Projektvortrag von Andrzej Aftyka, Abdi Leili, Elsa Mahari Projektvortrag von Andrzej Aftyka, Abdi Leili, Elsa Mahari Herzlich Willkommen [Lehrveranstaltung Systemprogrammierung SS008 bei Herr Prof. Weber] Projektthema: Programmiersprachen-Server mit CGI Inhaltsverzeichnis

Mehr

VWA Rhein-Neckar Dipl.-Ing. Thomas Kloepfer. Kommunikation I (Internet) Übung 4 PHP

VWA Rhein-Neckar Dipl.-Ing. Thomas Kloepfer. Kommunikation I (Internet) Übung 4 PHP VWA Rhein-Neckar Dipl.-Ing. Thomas Kloepfer Kommunikation I (Internet) Übung 4 PHP SS 2004 Inhaltsverzeichnis 1. PHP die serverseitige Programmiersprache...1 1.1. PHP - Bereiche in HTML definieren...1

Mehr

Klausur Kommunikation I. Sommersemester 2003. Dipl.-Ing. T. Kloepfer

Klausur Kommunikation I. Sommersemester 2003. Dipl.-Ing. T. Kloepfer Kommunikation I 1 Klausur Kommunikation I Sommersemester 2003 Dipl.-Ing. T. Kloepfer Bearbeitungsinformationen Aufbau der Klausur Die Klausur ist wie folgt aufgebaut: Die Klausur ist in 18 Aufgaben unterteilt.

Mehr

09.06.2003 André Maurer andre@maurer.name www.andre.maurer.name Wirtschaftsinformatik FH 3.5 Fachhochschule Solothurn, Olten

09.06.2003 André Maurer andre@maurer.name www.andre.maurer.name Wirtschaftsinformatik FH 3.5 Fachhochschule Solothurn, Olten Aktuelle Themen der Wirtschaftsinformatik Zusammenfassung 09.06.2003 André Maurer andre@maurer.name www.andre.maurer.name Wirtschaftsinformatik FH 3.5 Fachhochschule Solothurn, Olten 1 Serverseitige Webprogrammierung

Mehr

Inhaltsverzeichnis. Hinweise zum Gebrauch des Buches... XIII. Teil I Grundlagen der Web-Programmierung

Inhaltsverzeichnis. Hinweise zum Gebrauch des Buches... XIII. Teil I Grundlagen der Web-Programmierung Hinweise zum Gebrauch des Buches... XIII Teil I Grundlagen der Web-Programmierung 1 Entwicklung der Web-Programmierung... 3 1.1 DerWegzumWorldWideWeb... 3 1.2 Komponenten der frühen Technik..... 5 1.3

Mehr

Angreifbarkeit von Webapplikationen

Angreifbarkeit von Webapplikationen Vortrag über die Risiken und möglichen Sicherheitslücken bei der Entwicklung datenbankgestützter, dynamischer Webseiten Gliederung: Einführung technische Grundlagen Strafbarkeit im Sinne des StGB populäre

Mehr

Ablauf. Wichtige Termine. Vertiefendes Übungsprojekt - SQL II

Ablauf. Wichtige Termine. Vertiefendes Übungsprojekt - SQL II Ablauf Wichtige Termine Ablauf der Lehrveranstaltung Vorstellung des Projektthemas Projektgruppen Vorstellung der Arbeitsumgebung (Software, Locations) Walkthrough Datenbankentwurf Formulare PHP Security

Mehr

Sicherheit in Webanwendungen CrossSite, Session und SQL

Sicherheit in Webanwendungen CrossSite, Session und SQL Sicherheit in Webanwendungen CrossSite, Session und SQL Angriffstechniken und Abwehrmaßnahmen Mario Klump Die Cross-Site -Familie Die Cross-Site-Arten Cross-Site-Scripting (CSS/XSS) Cross-Site-Request-Forgery

Mehr

web(in)securities CISCO Academy Day 11/12.05.2012 Mark Hloch Montag, 14. Mai 12

web(in)securities CISCO Academy Day 11/12.05.2012 Mark Hloch Montag, 14. Mai 12 Hochschule Niederrhein University of Applied Sciences Elektrotechnik und Informatik Faculty of Electrical Engineering and Computer Science web(in)securities CISCO Academy Day 11/12.05.2012 Mark Hloch Inhalt

Mehr

Benutzerhandbuch. Gästebuch Software - YellaBook v1.0 http://www.yellabook.de. Stand: 01.08.2012. by YellaBook.de - Alle Rechte vorbehalten.

Benutzerhandbuch. Gästebuch Software - YellaBook v1.0 http://www.yellabook.de. Stand: 01.08.2012. by YellaBook.de - Alle Rechte vorbehalten. Benutzerhandbuch Gästebuch Software - YellaBook v1.0 http://www.yellabook.de Stand: 01.08.2012 Inhalt 1 Funktionen... 3 2 Systemanforderungen... 4 3 Installation... 4 4 Einbinden des Gästebuchs... 5 5

Mehr

Einführung in Web-Security

Einführung in Web-Security Einführung in Web-Security Alexander»alech«Klink Gulaschprogrammiernacht 2013 Agenda Cross-Site-Scripting (XSS) Authentifizierung und Sessions Cross-Site-Request-Forgery ([XC]SRF) SQL-Injections Autorisierungsprobleme

Mehr

eytron VMS Webanwendung Fehlersuche und -Behebung

eytron VMS Webanwendung Fehlersuche und -Behebung eytron VMS Webanwendung Fehlersuche und -Behebung 2009 ABUS Security-Center GmbH & Co. KG, Alle Rechte vorbehalten Diese Anleitung soll Ihnen Unterstützung für den Fall geben, dass die Webanwendung nach

Mehr

Praktikum Internetprotokolle - POP3

Praktikum Internetprotokolle - POP3 Technische Universität Ilmenau Fakultät für Informatik und Automatisierung Institut für Praktische Informatik und Medieninformatik Fachgebiet Telematik/Rechnernetze 19. Mai 2008 1 Aufgabenstellung Praktikum

Mehr

Aktuelle Sicherheitsprobleme im Internet: Angriffe auf Web-Applikationen

Aktuelle Sicherheitsprobleme im Internet: Angriffe auf Web-Applikationen Aktuelle Sicherheitsprobleme im Internet: Angriffe auf Web-Applikationen Dr. Marc Rennhard Institut für angewandte Informationstechnologie Zürcher Hochschule Winterthur marc.rennhard@zhwin.ch Angriffspunkt

Mehr

Grundlagen zum Internet. Standarddienste der Bürowelt

Grundlagen zum Internet. Standarddienste der Bürowelt Grundlagen zum Internet Grundlagen zum Internet Standarddienste der Bürowelt Lehrstuhl für Automatisierungstechnik Dr.-Ing. A. Braune SS05 - Bra Übersicht Dienste Offene Standards der Bürowelt (z.b. Web,

Mehr

SINT Rest App Documentation

SINT Rest App Documentation SINT Rest App Documentation Release 1.0 Florian Sachs September 04, 2015 Contents 1 Applikation 3 2 Rest Service 5 3 SOAP Service 7 4 Technologiestack 9 5 Deployment 11 6 Aufgabe 1: Google Webservice

Mehr

FileMaker und PHP Workshop

FileMaker und PHP Workshop FileMaker und PHP Workshop 2-stündiger Ausschnitt aus einem 3-tägigen Schulungsprogramm Bernhard Schulz FileMaker Konferenz 2010 / Zürich Ziel des Workshops Kennenlernen von PHP Möglichkeiten von FileMaker

Mehr

Groovy und CouchDB. Ein traumhaftes Paar. Thomas Westphal

Groovy und CouchDB. Ein traumhaftes Paar. Thomas Westphal Groovy und CouchDB Ein traumhaftes Paar Thomas Westphal 18.04.2011 Herzlich Willkommen Thomas Westphal Software Engineer @ adesso AG Projekte, Beratung, Schulung www.adesso.de thomas.westphal@adesso.de

Mehr

z.b. 192.168.0.180 Ihr Datensammelpunkt bekommt dann die Serveradresse http://192.168.0.180 / grafstat/..

z.b. 192.168.0.180 Ihr Datensammelpunkt bekommt dann die Serveradresse http://192.168.0.180 / grafstat/.. Grafstat Datensammelpunkt on Stick Voraussetzungen Ein Datensammelpunkt besteht aus eine Reihe von PHP-Scripten ( oder Perl/CGI). Damit diese Scripte funktionieren, braucht man einen Webserver ( z.b. Apache

Mehr

SMS-Gateway HTTP(S) Schnittstellenbeschreibung

SMS-Gateway HTTP(S) Schnittstellenbeschreibung SMS-Gateway HTTP(S) Schnittstellenbeschreibung Version 1.01 02.05.2013 Web: http://www.sms-expert.de Allgemeine Beschreibung der HTTP(S)- Schnittstelle des SMS-Gateways Inhaltsverzeichnis 1. Einleitung...

Mehr

Theorie und Praxis einer JSON-RPC-basierten Web-API

Theorie und Praxis einer JSON-RPC-basierten Web-API Theorie und Praxis einer JSON-RPC-basierten Web-API Christian Krause Christian.Krause@raritan.com Raritan Deutschland GmbH Chemnitzer LinuxTage 2015 Gliederung 1 2 Remote Procedure Call Interface Definition

Mehr

Inhalt: Konfiguration: web.xml ; server.xml Workflow: Weiterleitung von Requests Lektion II-IV Lektion V-VI

Inhalt: Konfiguration: web.xml ; server.xml Workflow: Weiterleitung von Requests Lektion II-IV Lektion V-VI Servlet II Inhalt: Konfiguration: web.xml ; server.xml Workflow: Weiterleitung von Requests Lektion II-IV Lektion V-VI 3-1 1. Grundlagen 2. Servlets 3. JSP 4 1.1. JAR Files 4 1.2. TCP/IP, Sockels 4 1.3.

Mehr

Verteidigung gegen SQL Injection Attacks

Verteidigung gegen SQL Injection Attacks Verteidigung gegen SQL Injection Attacks Semesterarbeit SS 2003 Daniel Lutz danlutz@watz.ch 1 Inhalt Motivation Demo-Applikation Beispiele von Attacken Massnahmen zur Verteidigung Schlussfolgerungen 2

Mehr

ZenQuery - Enterprise Backend as a Service Single Page Applications mit AngularJS und Spring MVC. - Björn Wilmsmann -

ZenQuery - Enterprise Backend as a Service Single Page Applications mit AngularJS und Spring MVC. - Björn Wilmsmann - ZenQuery - Enterprise Backend as a Service Single Page Applications mit AngularJS und Spring MVC - Björn Wilmsmann - ZenQuery Enterprise Backend as a Service Unternehmen horten Daten in Silos ZenQuery

Mehr

Erstellung eines Frameworks für Shop Systeme im Internet auf Basis von Java

Erstellung eines Frameworks für Shop Systeme im Internet auf Basis von Java Erstellung eines Frameworks für Shop Systeme im Internet auf Basis von Java Präsentation zur Diplomarbeit von Übersicht Java 2 Enterprise Edition Java Servlets JavaServer Pages Enterprise JavaBeans Framework

Mehr

Wolfgang Dehnhardt: JavaScript, VBScript, ASP, Perl, PHP, XML: Scriptsprachen für dynamische Webauftritte, Carl Hanser 2001

Wolfgang Dehnhardt: JavaScript, VBScript, ASP, Perl, PHP, XML: Scriptsprachen für dynamische Webauftritte, Carl Hanser 2001 8. Skriptsprachen 8.1 Clientseitige Web-Skripte: JavaScript 8.2 Document Object Model (DOM) 8.3 Serverseitige Web-Skripte: PHP Weiterführende Literatur: Wolfgang Dehnhardt: JavaScript, VBScript, ASP, Perl,

Mehr

FuE-Bereich IuK-Systeme im Gesundheitswesen

FuE-Bereich IuK-Systeme im Gesundheitswesen FuE-Bereich IuK-Systeme im Gesundheitswesen IG XML und Web Services Dipl.-Inform. Axel Schwolow IG Kommunikation im Web Entwicklung früher ausschließlich Kommunikation über Browser heute zunehmend direkt

Mehr

Hochschule Darmstadt Fachbereich Informatik

Hochschule Darmstadt Fachbereich Informatik Hochschule Darmstadt Fachbereich Informatik Entwicklung webbasierter Anwendungen Tipps und Tricks zur Software Installation 1 Vorbemerkung Auf den Laborrechnern ist natürlich alles installiert! Die Installation

Mehr

Motivation. Inhalt. URI-Schemata (1) URI-Schemata (2)

Motivation. Inhalt. URI-Schemata (1) URI-Schemata (2) 14. URIs Uniform Resource Identifier 14-1 14. URIs Uniform Resource Identifier 14-2 Motivation Das WWW ist ein Hypermedia System. Es enthält: Resourcen (Multimedia Dokumente) Verweise (Links) zwischen

Mehr

IT Engineering Continuous Delivery. Development Tool Chain Virtualisierung, Packer, Vagrant und Puppet. Alexander Pacnik Karlsruhe, 20.05.

IT Engineering Continuous Delivery. Development Tool Chain Virtualisierung, Packer, Vagrant und Puppet. Alexander Pacnik Karlsruhe, 20.05. IT Engineering Continuous Delivery Development Tool Chain Virtualisierung, Packer, Vagrant und Puppet Alexander Pacnik Karlsruhe, 20.05.2014 Einleitung... worum es in diesem Vortrag geht Ziele Continuous

Mehr

Java zur Realisierung von Internetanwendungen

Java zur Realisierung von Internetanwendungen Java zur Realisierung von Internetanwendungen Elementare Web-Programmierung HTTP Web-Browser Web-Browser GET http://www.zw.fh-kl.de/beispiel.htm Beispiel Ein

Mehr

Ruby on Rails. Florian Ferrano Ralf Heller Markus Nagel

Ruby on Rails. Florian Ferrano Ralf Heller Markus Nagel Ruby on Rails Florian Ferrano Ralf Heller Markus Nagel Überblick Ruby on Rails Ruby Rails Geschichte MVC allgemein MVC in Rails Scaffolding Webserver Installation Beispiele Wo wird Rails verwendet? Ausblick

Mehr

Schwachstellen in Web- Applikationen: Was steckt dahinter und wie nutzt man sie aus?

Schwachstellen in Web- Applikationen: Was steckt dahinter und wie nutzt man sie aus? Schwachstellen in Web- Applikationen: Was steckt dahinter und wie nutzt man sie aus? Prof. Dr. Marc Rennhard Institut für angewandte Informationstechnologie InIT ZHAW Zürcher Hochschule für Angewandte

Mehr

Performance Tuning mit @enterprise

Performance Tuning mit @enterprise @enterprise Kunden-Forum 2005 Performance Tuning mit @enterprise Herbert Groiss Groiss Informatics GmbH, 2005 Inhalt Datenbank RMI JAVA API HTTP Konfiguration Analyse Groiss Informatics GmbH, 2005 2 Datenbank

Mehr

HTML Formulare / CGI / JavaScript / Perl

HTML Formulare / CGI / JavaScript / Perl Übungen Informatik I HTML Formulare / CGI / JavaScript / Perl http://www.fbi-lkt.fh-karlsruhe.de/lab/info01/tutorial http://de.selfhtml.org 1 HTML Inhalt HTML Formulare JavaScript CGI / Perl 2 HTML Formulare

Mehr

Herzlich Willkommen! eine praxisnahe Übersicht. Mit Java ins Web - mb@bebox.franken.de. 26.11.2000 (c) Michael Behrendt -

Herzlich Willkommen! eine praxisnahe Übersicht. Mit Java ins Web - mb@bebox.franken.de. 26.11.2000 (c) Michael Behrendt - Herzlich Willkommen! Mit Java ins Web - eine praxisnahe Übersicht 1 Wer bin ich? Michael Behrendt, 21, Nürnberg kurzer Lebenslauf: 1991 Erster Rechner: Commodore C128 1995 Ausbildung zum Datenverarbeitungskaufmann

Mehr

Um asynchrone Aufrufe zwischen Browser und Web Anwendung zu ermöglichen, die Ajax Hilfsmittel DWR ist gebraucht.

Um asynchrone Aufrufe zwischen Browser und Web Anwendung zu ermöglichen, die Ajax Hilfsmittel DWR ist gebraucht. Technisches Design Inhalt Design Übersicht Menü und DispatcherServlet DWR Servlet Viewer Servlets Controllers Managers Sicherheit Anwendung Architektur Component Diagram Deployment Diagram Komponente Sequence

Mehr

Sitzungszustand. Vorläufige Version 309 c 2005 Peter Thiemann

Sitzungszustand. Vorläufige Version 309 c 2005 Peter Thiemann Sitzungszustand Gruppierung von Anfragen zu Sitzungen (Sessions) Klasse HttpServletRequest Methode HttpSession getsession (bool create) liefert aktuelle Sitzungsobjekt Zustand lokal zur Anwendung (ServletContext)

Mehr

Konzept eines Datenbankprototypen. 30.06.2003 Folie 1 Daniel Gander / Gerhard Schrotter

Konzept eines Datenbankprototypen. 30.06.2003 Folie 1 Daniel Gander / Gerhard Schrotter Konzept eines Datenbankprototypen 30.06.2003 Folie 1 Daniel Gander / Gerhard Schrotter Inhalt (1) Projektvorstellung & Projektzeitplan Softwarekomponenten Detailierte Beschreibung der System Bausteine

Mehr

Einstieg Projektziel Proxy Grundlagen Demonstration Ausblick. Reverse Proxys. Robert Hilbrich. Fakultät für Informatik Humboldt Universität Berlin

Einstieg Projektziel Proxy Grundlagen Demonstration Ausblick. Reverse Proxys. Robert Hilbrich. Fakultät für Informatik Humboldt Universität Berlin Reverse Proxys Robert Hilbrich Fakultät für Informatik Humboldt Universität Berlin 28. September 2006 John von Neumann, 1949 It would appear that we have reached the limits of what it is possible to achieve

Mehr

Ein kleines Tutorial zu 1 st News, dem New sletter- Skript von Stephan Altmann

Ein kleines Tutorial zu 1 st News, dem New sletter- Skript von Stephan Altmann Ein kleines Tutorial zu 1 st News, dem New sletter- Skript von Stephan Altmann 1 Einführung 2 Voraussetzungen 3 I nstallation allgemein 4 I nstallation als Plugin für AT Contenator 5 Funktionalitäten 6

Mehr

XPages Good to know. Benjamin Stein & Pierre Hein Stuttgart 7. Mai 2015

XPages Good to know. Benjamin Stein & Pierre Hein Stuttgart 7. Mai 2015 XPages Good to know Benjamin Stein & Pierre Hein Stuttgart 7. Mai 2015 Agenda 1. Einführung Was sind XPages? 2. Allgemeine Tipps Allgemeine Tipps für die Verwendung von XPages 3. Designer Tipps Tipps für

Mehr

Dynamische Webseiten mit PHP 1

Dynamische Webseiten mit PHP 1 Dynamische Webseiten mit PHP 1 Webserver, PHP und MYSQL Ein Webserver dient dazu, Internetseiten an PCs zu senden, von denen sie aufgerufen werden. Beispiel: Sie tippen im Browser www.fosbosweiden.de ein.

Mehr

FAQ - Script gaesteform

FAQ - Script gaesteform FAQ - Script gaesteform www.kundencenter.ws 9. April 2009 Salvatore Spadaro 1 2 Inhaltsverzeichnis 1 Script - gaesteform 3 1.1 Welchen Funktionumfang bietet das Script gaesteform und welche Technik steckt

Mehr

4. Verwendete Methoden und Werkzeuge

4. Verwendete Methoden und Werkzeuge 4. Verwendete Methoden und Werkzeuge In diesem Kapitel werden die verschiedenen Methoden und Werkzeuge vorgestellt, die bei der Realisierung der Mediathek eingesetzt wurden. Zuerst werden die Grundlagen

Mehr

Websockets: Leichtgewichtige Verbindungen für Web-Applikationen

Websockets: Leichtgewichtige Verbindungen für Web-Applikationen Websockets: Leichtgewichtige Verbindungen für Web-Applikationen Seite: 1 / 16 Über mich Stefan Neufeind Mit-Geschäftsführer der SpeedPartner GmbH aus Neuss ein Internet-Service-Provider (ISP) Individuelle

Mehr

Soziale Funktionen zu verträglichen Kosten

Soziale Funktionen zu verträglichen Kosten Soziale Funktionen zu verträglichen Kosten Marc Achtelig, Dipl.-Ing.(FH), Dipl.-Wirtschaftsing.(FH) Handbücher Online-Hilfen Screencasts www.indoition.com Agenda Integrationsstufen Organisatorische Voraussetzungen

Mehr

Auszug aus Axis2 Schulung

Auszug aus Axis2 Schulung Auszug aus Axis2 Schulung Dieses Dokument ist ein Auszug aus unserem Skript zur Axis2- Schulung. Es dient lediglich als Beispiel für unsere Kursunterlagen. Thomas Bayer Hauptstraße 33 75050 Gemmingen Mehr

Mehr

Aufgabenstellung und Zielsetzung

Aufgabenstellung und Zielsetzung Aufgabenstellung und Zielsetzung In diesem Szenario werden Sie eine Bestellung, vorliegend im XML-Format, über einen Web-Client per HTTP zum XI- System senden. Dort wird die XML-Datei mittels eines HTTP-Interfaces

Mehr