Web-basierte Anwendungen

Größe: px
Ab Seite anzeigen:

Download "Web-basierte Anwendungen"

Transkript

1 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

2 Organisatorisches Organisatorisches 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 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

3 Ziele der Veranstaltung 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 Java Server Faces 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

4 Organisatorisches Voraussetzungen 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

5 Organisatorisches Literatur CGI, Grundlagen Programming Python, O Reilly, Lutz, Kapitel 16 Servlets Core Servlets and JavaServer Pages, Hall & Brown, JAVAEE/servlet, JavaEE/jsp Java Server Faces Java Server Faces 2.2, dpunkt, Marinscheck et. al JAVAEE/javaserverfaces html, Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

6 Grundlagen Web Einführung Einführung Web-basierte Anwendung Dokumentenbasiert, Client-Server Client Präsentation, Dokumentendarstellung Web-Browser Desktop, mobiles Device Server Anwendungsfunktionalität, Dokumentenerzeugung Web-Server Meist Server Anfrage Antwort Klassifikation Inhalte, Layout, Interaktion Server Anzahl Nutzer, Zugriffe Sicherheit, Verfügbarkeit Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

7 Grundlagen Web 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/ de.selfhtml.org Http-Server (Web Server) Konfiguration Antwort Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

8 Grundlagen Web Einführung 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 Http-Server (Web Server) Konfiguration Antwort Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

9 Grundlagen Web Einführung Dynamische Inhalte Server 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 HTTP-Server Prozess HTTP-Server Prozess HTTP-Server HTTP-Server Container Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 Host Host Host

10 Grundlagen Web Einführung Infrastruktur an der Hochschule 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

11 Grundlagen Web Einführung Dynamische Inhalte Client Roundtrips Visualisierung 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

12 Grundlagen Web Common Gateway Interface Erzeugen dynamischer Web-Seiten auf dem Server CGI Common Gateway Interface (CGI) 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

13 Grundlagen Web 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>") Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

14 Grundlagen Web Common Gateway Interface 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/ 0 HTTP_HOST=www 1 GATEWAY_INTERFACE=CGI/1.1 2 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

15 Grundlagen Web Common Gateway Interface Komfortable CGI-Programmierung Python-Bibliothek cgi Hilfsroutinen cgitb (TraceBack), Ansicht Fehlermeldungen, sehr sinnvoll hallokomf.cgi 1 #!/usr/bin/python 2 # immer gleich am Anfang 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>") 0 print("<head><title>hallo</title></head>") 1 print("<body>") 2 print("hallo CGI Python") 3 print("</body></html>") Fehler in Zeile 8 wird erkannt und entsprechend im Browser ausgegeben. Sehr hilfreich beim Entwickeln. Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

16 Grundlagen Web Common Gateway Interface Umgebungsvariablen Informationen in Umgebungsvariablen Vom Web-Server, aus Anfrage Vom Skript verwertbar Informationen Anfrage Anfragemethode, Query-String,... Informationen Infrastruktur 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

17 Grundlagen Web Common Gateway Interface Anfragemethode GET 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

18 Grundlagen Web Common Gateway Interface Anfragemethode GET Query-String 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

19 Grundlagen Web Common Gateway Interface Query-String verwenden CGI-Bibliothek Ohne Query-String 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 0 if "ende" in form: 1 ende = form["ende"].value 2 print("hallo %s,<br />%s" % (name, ende)) 3 print("<br />%s" % os.environ["query_string"]) Query-String?name=Tim&ende=ciao Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

20 Grundlagen Web Common Gateway Interface Formulare erzeugen Query-String Erzeugen Query-String mit <form>-tag action-attribut: (relative) Ziel-URL method-attribut: Anfrage-Methode, get (oder post) 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> 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

21 Grundlagen Web Common Gateway Interface Parameter mit POST statt GET POST statt GET Philosophie: Daten schicken statt holen Server-Zustand darf sich ändern Wiederholte Anfragen können unterschiedliche Ergebnisse haben, Ergebnisse nicht cachen Ä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"> 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 postparam.cgi 1 #!/usr/bin/python 2 print("content-type: text/html\n") 3 import sys 4 print sys.stdin.read() Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

22 Grundlagen Web Formularelemente Formularelemente Hausaufgabe 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

23 Grundlagen Web Formularelemente Formulare und Mehrfachauswahl Mehrfachauswahl Derselbe Schlüssel mehrfach in Formular verwendet Bei Radiobuttons natürlicherweise Mehrere Ergebnisse in Parameter je Schlüssel möglich mehrfach.cgi 1 #!/usr/bin/python 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()) Muss in Anwendungsprogramm berücksichtigt werden 1 <html><body> 2 <form action="mehrfach.cgi" method="post"> 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

24 Grundlagen Web Templating 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 Template-Engines Achtung: Art der Dokumentenerstellung unabhängig von technischer Integration (egal ob CGI oder proprietär) 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>") Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

25 Grundlagen Web Templating Server Pages Konzept 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 hello.sp 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>") Führe entstehendes Skript aus Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

26 Grundlagen Web Templating Server Pages Anwendungsgebiet 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

27 Grundlagen Web Templating Dokumentenerzeugung mit Templates Trennen Markup und Code Markup als separate Teile, z.b. Zeichenketten oder Dateien Markup mit speziellen Platzhaltern Code generiert Inhalte Templates Skript Eingaben Am Ende Templates mit Inhalten füllen und ausgeben Seite Beispiel Tabelle erzeugen mit Klein-/Großbuchstaben Nächste Seite Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

28 Grundlagen Web Templating Dokumentenerzeugung mit Templates Beispiel Spaghetti-Code 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) 0 print("</title></head>") 1 print("<body><table>") 2 3 for c in string.lowercase: 4 print("<tr><td>") 5 print(c) 6 print("</td>") 7 print("<td>") 8 print(c.upper()) 9 print("</td></tr>") 0 1 print "</table></body></html>" Template-Code 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))) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

29 Grundlagen Web 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 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> Template-Engines Reichlich vorhanden, ein paar Dutzende in Mehr Features, zum Beispiel Iterieren Uns reicht Einfachst-Templating Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

30 Grundlagen Web Templating 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

31 Grundlagen Web 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 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)) 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,... 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

32 Grundlagen Web Templating 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 )] 0 data = [{V: Susi, N: Sinnlos, M: }, 1 {V: Rudi, N: Ratlos, M: }, 2 {V: WWW, N: WickedWestWitch, M: }] 3 ctable = table(keys, data) 4 c = "<html><body><h3>tabelle</h3>%s</body></html>" % ctable 5 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

33 Grundlagen Web 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

34 Grundlagen Web Proprietäre Integration 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 HTTP-Server WSGI Python-Prozess Python-Prozess Apache-HTTP-Server mod_wsgi (WSGI-Gateway) WSGI-Protokoll Python-Prozess code.google.com/p/modwsgi/ Proprietäre effiziente Integration Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

35 Grundlagen Web Proprietäre Integration Ablauf WSGI im Web-Server Anfrage von Client im Web-Server 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

36 Grundlagen Web Proprietäre Integration WSGI HTTP-Server mit WSGI liefert 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 jetzt.wsgi 1 import datetime 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

37 Grundlagen Web 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

38 Grundlagen Web Proprietäre Integration 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

39 GET Anfragen mit WSGI Grundlagen Web Proprietäre Integration get.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

40 Grundlagen Web Proprietäre Integration POST-Anfragen mit WSGI postparam.wsgi 1 from urlparse import parse_qs 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 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 Verarbeiten wie bei GET mit parse_qs Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

41 Grundlagen Web 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

42 Grundlagen Web Proprietäre Integration 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

43 Grundlagen Web Proprietäre Integration pydev Python mit Eclipse PyDev 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

44 Grundlagen Web werkzeug Abstraktion von der dokumentenbasierten Web-Schnittstelle Web-Anwendung 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 Abstraktion bei Web-Frameworks 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

45 Grundlagen Web werkzeug Abstraktion mit werkzeug werkzeug werkzeug.pocoo.org 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) 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() Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

46 Grundlagen Web werkzeug 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

47 Grundlagen Web 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) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

48 Grundlagen Web werkzeug 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

49 Grundlagen Web werkzeug Response-Objekt 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

50 Grundlagen Web Routing Routing Welche Seite soll angezeigt werden? 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

51 Grundlagen Web Routing Routing Beispiel Statische Inhalte mit WSGI 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 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) Wenn URL mit /statisch/ beginnt, dann einfach nur Inhalt wiedergeben Ansonsten mit application weitermachen Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

52 Grundlagen Web Routing Optionen Code-Organisation 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

53 Grundlagen Web 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

54 Grundlagen Web Routing 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

55 Grundlagen Web 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

56 Grundlagen Web Zustandsverwaltung über Anfrage hinaus 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

57 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Anwendungskontext im Client 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

58 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Kontext im Client Formulare 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

59 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Kontext im Client Generiertes Formular Generiertes Formular Verstecke Eingabefelder für Schlüssel/Wert-Paare name als Schlüssel value als Wert 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 /> Werden automatisch durch Formular submit übertragen Formular selbst hat keine sichtbaren Elemente außer dem Knopf Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

60 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Cookies 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

61 Grundlagen Web 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

62 Grundlagen Web Zustandsverwaltung über Anfrage hinaus 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 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()) Set-Cookie: jetzt=" :52: "; Path=/ 6 7 cookie["jetzt"]["path"] = "/" 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

63 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Kontext im Client 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

64 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Kontext im Client Sichere Cookies 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

65 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Kontext im Client Sichere Cookies, Beispiel 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) 0 1 def restore_context(request): 2 if CONTEXT not in request.cookies: 3 return {} 4 if FP not in request.cookies: 5 raise Exception("Security Error") 6 ctx = request.cookies[context] 7 fp = hashlib.sha1(ctx+salt).hexdigest() 8 if fp!= request.cookies[fp]: 9 raise Exception("Security Error") 0 ret = urlparse.parse_qs(ctx) 1 for k in ret: # nur ein Wert 2 ret[k] = "".join(ret[k]) 3 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

66 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Kontext im Client Sichere Cookies, werkzeug 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): 0 if CONTEXT not in request.cookies: 1 return {} 2 scs = request.cookies[context] 3 ctx = sc.securecookie.unserialize(scs, SALT) 4 if not ctx: 5 raise Exception("Security Error") 6 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

67 Grundlagen Web 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

68 Grundlagen Web Zustandsverwaltung über Anfrage hinaus 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

69 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Session-Verwaltung auf Server Zusammenspiel Session-ID und Kontext Inhalte des Anwendungskontextes werden auf Server gehalten Assoziation von Session-ID mit Anwendungskontext 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 Hauptspeicher/ Prozesskontext Dateisystem Datenbank Web-Server/Skriptumgebung Server/Host Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

70 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Session-Verwaltung auf Server mit Python Anwendungskontext Verwendung Session-Objekte, Middleware Middleware entscheidet über Ort und Art der Speicherung Session-ID 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 Dateisystem Datenbank Web-Server/Skriptumgebung Server/Host Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

71 Grundlagen Web 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

72 Grundlagen Web Zustandsverwaltung über Anfrage hinaus 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

73 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Session-Verwaltung auf Server Beispiel 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

74 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Achtung beim Schreiben Nebenläufigkeit! 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

75 Grundlagen Web 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

76 Grundlagen Web Zustandsverwaltung über Anfrage hinaus 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

77 Grundlagen Web Zustandsverwaltung über Anfrage hinaus Sessions Sessions Umsetzung Serialisieren häufig notwendig Versuchen wenig Daten in der Session zu halten Keine Frames, kein <iframe>, konkurrierende Zugriffe Dateien als Ablage und sperren häufig nicht beste Wahl 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) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

78 Grundlagen Web Bibliotheken Integration von Datenbanken Datenbanken für Web-Anwendungen Mehrbenutzeranw., immer mit dabei Alle Anwendungsdaten, auch Session-Daten möglich Datenbanken und Python 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

79 Grundlagen Web 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") Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

80 Grundlagen Web Bibliotheken 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

81 Grundlagen Web Bibliotheken Sicheres Parameterisieren von Anfragen Ernst gemeint 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

82 Grundlagen Web Bibliotheken Postgresql und Python Hinweise/1 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

83 Grundlagen Web Bibliotheken Postgresql und Python Hinweise/2 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,)] Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

84 Grundlagen Web Bibliotheken Web-Anwendungen und Transaktionen 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

85 Grundlagen Web 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

86 Grundlagen Web Bibliotheken 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="medi 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

87 Grundlagen Web Bibliotheken Laden Binärdatei von Datenbank 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) 0 else: # Rahmen fuer ein Beispielbild 1 c = img % { id : 31693} 2 dic={ title : Image Show, content :c} 3 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="medi 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] Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

88 Grundlagen Web Bibliotheken Bilder erzeugen mit Image 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 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

89 Grundlagen Web 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) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

90 Grundlagen Web Bibliotheken 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: 0 anrede = addr.find("anrede").get("bez") 1 name = addr.find("name").text 2 l.append("%s %s" % (anrede, name)) 3 c = "<br />\n".join(l) 4 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

91 Grundlagen Web Bibliotheken Frameworks Beispiel django 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. Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

92 Grundlagen Web Bibliotheken Fazit Grundlagen Web 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

93 JavaEE Web Tier Servlet Container Web-Anwendungen im Container 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

94 JavaEE Web Tier Servlet Container JavaEE Übersicht 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 Java Server Faces (JSF) Framework, Programmiermodell, Präsentation Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

95 JavaEE Web Tier Servlet Container JavaEE, Web Tier Servlet Container Servlet Java-Klasse, die Servlet-Schnittstelle implementiert Für Verarbeitung von (HTTP-)Anfragen Servlet-Umgebung Laufzeitumgebung des Web Tier, Container Ausführen von Servlets, Übersetzen von JSP in Servlets Weiterleiten einer Anfrage an passendes Servlet 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

96 JavaEE Web Tier Servlet Container Tomcat Installieren und Verwenden Archiv extrahieren In beliebigem Verzeichnis auspacken tar zxvf apache-tomcat tar.gz Konfiguration (conf) nicht notwendig Starten und Stoppen (bin) Starten: bin/startup.sh Stoppen: bin/shutdown.sh HTTP-Server, Port 8080, Servlet-Container, lokal Logging (logs) 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

97 JavaEE Web Tier Servlet Container Web-Anwendungen im Container 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

98 JavaEE Web Tier Servlet Container Servlet Lebenszyklus 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

99 JavaEE Web Tier Servlet Container 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

100 JavaEE Web Tier Servlet Container 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

101 JavaEE Web Tier Servlet Container 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

102 JavaEE Web Tier Servlet Container 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

103 JavaEE Web Tier Servlet Container 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 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

104 JavaEE Web Tier Servlet Container 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

105 JavaEE Web Tier Servlet Container Generieren Binärdaten 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 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

106 JavaEE Web Tier Servlet Container Weiterleitung Server Ziel: Ein Quellcode für GET und POST Weiterleitung der Anfrage im Servlet Container 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

107 JavaEE Web Tier Servlet Container 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

108 JavaEE Web Tier Servlet Container 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

109 JavaEE Web Tier Servlet Container Struktur Web-Anwendung Mapping? Woher weiß Tomcat was bei einem Request (URL) passieren soll? Beispiel: /jee/helloservlet Struktur Webanwendung In eigenem Verzeichnis, beliebiger Name, meist erster Teil der URL 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

110 JavaEE Web Tier Servlet Container Deployment Web-Anwendung Web-Anwendung deployen Web-Anwendung auf dem Container bereit stellen Spezifisch je nach Container Deployment mit tomcat Verzeichnisbaum der Web-Anwendung unter webapps kopieren 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

111 JavaEE Web Tier Servlet Container Konfiguration mit 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=" 3 xmlns:xsi=" 4 xsi:schemalocation=" 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

112 JavaEE Web Tier Servlet Container Wichtigste Tags web.xml 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

113 JavaEE Web Tier Servlet Container Weitere Tags web.xml 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

114 JavaEE Web Tier Servlet Container Annotationen ab Servlet 3.0 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

115 JavaEE Web Tier Servlet Container Weitere Annotationen ab Servlet 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... Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

116 JavaEE Web Tier Servlet Container Beispiel Konfiguration eines Servlets mit web.xml Ziel Deployment Parameter Servlet konfigurierbar Parameter ändern ohne Quellcode-Anpassung oder neu übersetzen Ändern der web.xml ServletConfig 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 } Zugriff auf Konfiguration Spezifisch für Servlet getinitparameter zum Zugriff auf Parameter init-param Innerhalb Servlet-Tag Name/Wert Paare Mehrere möglich 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

117 JavaEE Web Tier Servlet Container 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

118 JavaEE Web Tier Servlet Container 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, dbpasswor 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

119 JavaEE Web Tier Servlet Container 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

120 JavaEE Web Tier Servlet Container 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

121 JavaEE Web Tier Servlet Container Datenbankzugriff Verbindung je Thread Idee 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:postgres 26 DriverManager.deregisterDriver(driver); 27 } catch (SQLException ignore) { } 28 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295 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

122 JavaEE Web Tier Servlet Container Datenbankzugriff Übersicht 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

123 JavaEE Web Tier Servlet Container Scopes Übersicht Achtung: Anfragen potenziell parallel Synchronisation, wenn notwendig, Aufgabe des Entwicklers Attr. Anfrage Sessionattribut Session forward Instanzvariable* Servlet Servlet Servlet * zum Beispiel für Caching, Datenverbindung, Attribut Lebensdauer Anwendung ServletContext Anwendung Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

124 JavaEE Web Tier Servlet Container Anfrage-Scope 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 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

125 JavaEE Web Tier Servlet Container Session-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

126 JavaEE Web Tier Servlet Container Anwendungs-Scope 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

127 JavaEE Web Tier Servlet Container 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

128 JavaEE Web Tier Servlet Container ServletContext getinitparameter Zugriff auf Parameter definiert in web.xml Definition auf web-app Ebene, unabhängig von Servlets 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"); getresourceasstream Zugriff auf zum Beispiel statische Inhalte wie Bilder oder ähnliches 1 ServletContext app = getservletcontext(); 2 String admin = app.getinitparameter("admin"); 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 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

129 JavaEE Web Tier Servlet Container 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 Filter Filter Filter Servlet Response Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

130 JavaEE Web Tier Servlet Container 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

131 JavaEE Web Tier Servlet Container Antwort Aufsammeln zur Manipulation 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 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

132 JavaEE Web Tier Servlet Container Beispielmanipulation Fette Medieninformatik 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

133 JavaEE Web Tier Servlet Container Filterketten Konfigurieren 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 /* *.bla /p1/* Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

134 JavaEE Web Tier Servlet Container Hinweis für Entwicklung Vermeiden von Caching 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); Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

135 JavaEE Web Tier Servlet Container Eclipse-Unterstützung Web Tools Platform (WTP) 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

136 JavaEE Web Tier Java Server Pages Templating mit Java Server Pages (JSP) 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

137 JavaEE Web Tier Java Server Pages Hello JSP World Struktur hello_jsp.java public final class hello_jsp extends org.apache.jaspe Markup/HTML 3 implements org.apache.jasper.runtime.jspsourcedepe 4... Tags in <%... %> für Java-Code, in 5 public void _jspservice(final javax.servlet.http.htt <%=... %> für Wertausgabe 6 throws java.io.ioexception, javax.servlet.servl 7 final javax.servlet.jsp.pagecontext pagecontext; Integration in Container 8 javax.servlet.http.httpsession session = null; 9 final javax.servlet.servletcontext application; Ablage innerhalb Web-App auf 10 final javax.servlet.servletconfig config; 11 oberster Ebene, wie statischer Inhalt javax.servlet.jsp.jspwriter out = null; (nicht unterhalb WEB-INF) 14 javax.servlet.jsp.pagecontext _jspx_page_context = Wird automatisch bei Änderung von 15 try { Container in Servlet übersetzt und 16 response.setcontenttype("text/html"); 17 pagecontext = _jspxfactory.getpagecontext(this, r automatisch deployed 18 null, true, 8192, true); hello.jsp 19 _jspx_page_context = pagecontext; 20 application = pagecontext.getservletcontext(); 1 <html> 21 config = pagecontext.getservletconfig(); 2 <head><title>hello World</title></head> 22 session = pagecontext.getsession(); 3 <body> 23 out = pagecontext.getout(); 4 Hallo Welt <br /> 24 _jspx_out = out; 5 <%= new java.util.date() %> 25 out.write("<html>\n"); 6 </body> 26 out.write("<head><title>hello World</title></head 7 </html> 27 out.write("<body>\n"); Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / final java.lang.object page = this; 13 javax.servlet.jsp.jspwriter _jspx_out = null;

138 JavaEE Web Tier Java Server Pages JSP Scripting Tags Scriptlets <%... %> Beliebiger Java Code, mehrere Anweisungen Mit Semikolon jede Anweisung abschließen Wird direkt in die Servlet-Methode _jspservice übernommen Ausdrücke <%=... %> Nur ein Java Ausdruck, keine Anweisungen, kein Semikolon am Ende Wert des Ausdrucks wird im Markup ausgegeben Wird in _jspservive in out.print Methodenaufruf übernommen Deklarationen <%!... %> Beliebiger Java Code, Methoden und Variablen Deklarationen Wird in die Servlet-Klasse übernommen Direktiven %> Nachrichten an den Servlet-Container Definition von Seiten-Attributen, inkludieren von Seiten,... Wird in die Datei der Servlet-Klasse außerhalb des Servlets übernommen Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

139 JavaEE Web Tier Java Server Pages Scriptlet, Beispiel Java Code innerhalb von <%... %> Beliebiger Code, der innerhalb einer Methode erlaubt ist Vordefinierte Variablen, viele, von Servlet bekannt, spart Code PrintWriter out HttpServletRequest request HttpServletResponse response ServletConfig config ServletContext application HttpSession session Achtung: Verleitet zu bösem Spaghetti-Code quadratzahlen.jsp 1 <html><body> 2 <h3> Quadratzahlen </h3> 3 <table> 4 <tr><th>zahl</th><th>quadratzahl</th></tr> 5 <% 6 int wieviel = 9; 7 String p = request.getparameter("wieviel"); 8 if (p!= null) { 9 wieviel = Integer.parseInt(p); 10 } 11 for (int i=1; i <= wieviel; i+=1) { 12 out.print("<tr><td>"+i+"</td>"); 13 out.print("<td>"+(i*i)+"</td></tr>"); 14 } 15 %> 16 </table> 17 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

140 JavaEE Web Tier Java Server Pages Ausdrücke, Beispiel Java Ausdruck innerhalb von <%=... %> Ein Java-Ausdruck der zu einem Wert evaluiert Wird mit tostring() zu String konvertiert, wenn notwendig Korrekte Konvertierung von Grundtypen Ausgabe mit out.print Nutzen vordefinierter Variablen möglich Verwendung Markup kann im Editor erstellt und überprüft werden Wird meist zusammen mit Scriptlets verwendet 1 <html><body> 2 <h3> Quadratzahlen </h3> 3 <table> 4 <tr><th>zahl</th><th>quadratzahl</th></tr> 5 <% 6 int wieviel = 9; 7 String p = request.getparameter("wieviel"); 8 if (p!= null) { 9 wieviel = Integer.parseInt(p); 10 } 11 for (int i=1; i <= wieviel; i+=1) { 12 %> 13 <tr><td><%= i %></td> 14 <td><%= i*i %></td></tr> 15 <% } %> 16 </table> 17 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

141 JavaEE Web Tier Java Server Pages Deklaration, Beispiel 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

142 JavaEE Web Tier Java Server Pages Quadratzahlen Pager mit Session 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

143 JavaEE Web Tier 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

144 JavaEE Web Tier Java Server Pages 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

145 JavaEE Web Tier 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 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> Neue vordefinierte Variable exception noch mehr Attribute session, default true buffer, default 8k autoflush, default true... fehler.jsp 1 <%@ page iserrorpage="true" 2 %><html> 3 <body> 4 Uuuuups: <%= exception.getmessage() %> 5 <br /><%= request.getquerystring() %> 6 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

146 JavaEE Web Tier Java Server Pages 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

147 JavaEE Web Tier 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

148 JavaEE Web Tier Java Server Pages 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

149 JavaEE Web Tier Java Server Pages Vordefinierte Variablen für Scopes ServletContext application request response HttpSession session ServletConfig config Attr. Anfrage Sessionattribut Session forward Instanzvariable* Servlet (aus JSP) Servlet (JSP) Attribut Lebensdauer Anwendung ServletContext Anwendung Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

150 JavaEE Web Tier Java Server Pages 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> Alle Attribute </h3> 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> 1 <html><body> 2 <h3> PageContext </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 /> 0 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

151 JavaEE Web Tier 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

152 JavaEE Web Tier Java Server Pages Controller Servlet 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

153 JavaEE Web Tier Java Server Pages JSP Seiten Anfragen auf Servlet leiten Alle Verweise auf Servlet Konfiguration von ctrl auf Servlet Controller notwendig 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> 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 rauf.jsp 1 <html><body> 2 Hallo <%= session.getattribute("login") %> <br /> 3 Der Wert ist <%= session.getattribute("zaehler") %> < 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") %> < 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

154 JavaEE Web Tier JavaBeans 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

155 JavaEE Web Tier JavaBeans Beispiel-Anwendung mit Bean 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

156 JavaEE Web Tier JavaBeans Beispiel Bean NameBean 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

157 JavaEE Web Tier JavaBeans JavaBeans und JSP <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 %> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

158 JavaEE Web Tier JavaBeans Beispiel Formular, Header, Fehler 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

159 JavaEE Web Tier 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"> 0 <table><tr><td>vorname</td><td> 1 <input type="text" name="vorname" value="<jsp:getproperty name="nb" property="vorname"/>"> 2 </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="*"/> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

160 JavaEE Web Tier JavaBeans 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

161 JavaEE Web Tier Expression Language Expression Language Motivation Problem mit Scriptlets Selbst einfache Ausdrücke nur mit Scriptlets möglich, zum Beispiel Addition 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" /> 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> Mit Expression Language </h3> 2 ${ }<br /> 3 ${cookie.jsessionid.value}<br /> 4 ${nb.vorname} ${nb.nachname} Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

162 JavaEE Web Tier Expression Language 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

163 JavaEE Web Tier 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

164 JavaEE Web Tier Expression Language 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

165 JavaEE Web Tier Standard Tag Library (JSTL) Standard Tag Library (JSTL) Standard JSP Tags Vordefinierte Tags, spezielle Bedeutung Fester Namensraum (jsp) mit Tags (usebean) Custom Tags, Custom Tag Library <jsp:usebean id="nb" class= "webanw.namebean" /> 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,... <c:foreach var="v" items="${header}" > <c:out value= "${v.key}=${v.value}" /> </c:foreach> Implementierung nicht Teil des Servlet-Containers Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

166 JavaEE Web Tier Standard Tag Library (JSTL) JSTL Einbinden 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=" prefix="c" %> <c:out value="hallo"/> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

167 JavaEE Web Tier 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=" 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

168 JavaEE Web Tier Standard Tag Library (JSTL) 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) 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"/> target: Zielobjekt, Map oder Bean property: Schlüssel oder Eigenschaft Tag <c:remove> möglich Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

169 JavaEE Web Tier Standard Tag Library (JSTL) JSTL Core, <c:foreach> 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

170 JavaEE Web Tier Standard Tag Library (JSTL) JSTL Core, <c:foreach>, Statusvariable 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

171 JavaEE Web Tier 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 /> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

172 JavaEE Web Tier Standard Tag Library (JSTL) 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=" />: Inkludieren von Inhalten, wie <jsp:include />, aber auch externe Ressourcen möglich <c:redirect url=" />: Redirect über Browser <c:url value=" />: 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

173 JavaEE Web Tier Standard Tag Library (JSTL) JSTL Funktionen für Expression Language 1 <%@ taglib prefix = "c" 2 uri=" %> 3 <%@ taglib prefix = "fn" 4 uri=" %> 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. 0 </c:if><br /> 1 <c:if test="${fn:endswith(header.referer, jstl/ )}"> 2 jstl/ am Ende beim referer 3 <c:out value="${header.referer}" /> 4 </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

174 JavaEE Web Tier i18n, l10n Internationalisierung, Lokalisierung 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

175 JavaEE Web Tier i18n, l10n JavaEE Web Tier und i18n/l10n Auswahl der Sprache und Formatierung 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 Dokumentation lesen, große Teile schon in JavaSE Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

176 JavaEE Web Tier i18n, l10n Auswahl Lokalisierung mit Locale Web-Browser, Accept-Language 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 ; Locale: Java-Klasse für Sprache/Länder 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 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

177 JavaEE Web Tier i18n, l10n Ressourcedateien 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

178 JavaEE Web Tier i18n, l10n Verwendung von Ressourcedateien mit <fmt:...> 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=" %> 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

179 JavaEE Web Tier i18n, l10n Ressourcen und Formatierungsparameter 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> 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> <fmt:param value="<wert>"/> Reihenfolge bestimmt Verwendung als 0tes, 1tes, 2tes,... Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

180 JavaEE Web Tier i18n, l10n Formatierung für Länder, Regionen und Zeitzonen Formatierungen spezifisch für eine Region Zeit- und Datumsangaben, Aussehen und Werte Zahldarstellung Währungsdarstellung und Geldbeträge Beispiel 2, $, 4/1/2014 versus 1.435,00 e, Greenwich Mean Time (GMT) versus Universal Time Coordinated (UTC) Wiesbaden: GMT+1 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

181 JavaEE Web Tier 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" /> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

182 JavaEE Web Tier i18n, l10n 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

183 JavaEE Web Tier i18n, l10n 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

184 JavaEE Web Tier Custom Tags 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 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> Makro -Feature notwendig Lösungsansatz Custom Tags JSP-Fragmente wiederverwenden Benutzen als eigene (custom) Tags <center> Copyleft 2015 </center> 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

185 JavaEE Web Tier 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=" %> 6 <%@ taglib prefix="fmt" 7 uri=" %> 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

186 JavaEE Web Tier Custom Tags 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

187 JavaEE Web Tier 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=" 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}" /> 0 </body></html> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

188 JavaEE Web Tier Custom Tags 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 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=" %> 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> Lebenszeit der Attribute Wird der Variablen von name zugewiesen PageScope, aber nur innerhalb der Tag-Datei, eigentlich TagScope Kann in Expression Language verwendet werden Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

189 JavaEE Web Tier 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=" %> 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

190 JavaEE Web Tier Custom Tags 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=" %> 4 <%@ taglib prefix="fn" 5 uri=" %> 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

191 JavaEE Web Tier 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

192 JavaEE Web Tier Custom Tags 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

193 JavaEE Web Tier 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=" %> 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

194 JavaEE Web Tier Custom Tags 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=" 3 xmlns:xsi=" 4 xsi:schemalocation=" version="2.1"> 7 <tlib-version>1.2</tlib-version> 8 <short-name>c</short-name> 9 <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

195 JavaEE Web Tier Custom Tags Tag Library Descriptor Tag-File Elemente Tag-Files in Tag Library Descriptor Tag tag-file Kind name: Name des Tags, meist Dateiname Tag-File Element in TLD-Datei 1 <tag-file> 2 <name>copyleft</name> 3 <path>/web-inf/tags/copyleft.tag</path> 4 </tag-file> 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/ Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

196 JavaEE Web Tier Custom Tags Tag-Klassen 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

197 Java Server Faces Model 1 / Model 2 Architektur Review Model 1 Architektur Nur JSPs und Beans 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 Hart realisierte Links... JSP JSP JSP JSP Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

198 Java Server Faces Model 1 / Model 2 Architektur Review Model 2 Architektur Model 1 plus Controller 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 Keine vordefinierten UI-Komponenten, händisches HTML, kein Tooling Keine Events und kein Event-Handling, request Controller Servlet update forward response händische Anfrageauswertung JSP JSP retrieve Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

199 Java Server Faces Java Server Faces Übersicht Java Server Faces Ziele UI-Framework für interaktive Web-Anwendungen Wiederverwendbare UI-Komponenten nutzen und erstellen Datenbindung zwischen Logik (Beans) und UI-Komponenten Event-Modell um Browser-Events auf Server-Methoden abzubilden Konfigurierbare Ablaufsteuerung 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,... Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

200 Java Server Faces Java Server Faces Übersicht Java Server Faces Features, Architektur Konfiguration und Folgeseitensteuerung Deklarative Konfiguration Kein Java-Code Komponentenbaum Abstraktion der Ansicht Wie klassische UI-Komponente Datenbindung UI-Daten und Bean-Properties Deklarative Assoziation Hilfsmittel Konvertierung, Validierung Fehlermeldungen Lokalisierung Expression Language,... facesconfig. xml request update Faces Servlet response retrieve facelet JSP JSP render faces Komponentenbaum Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

201 Java Server Faces Java Server Faces Übersicht Java Server Faces FacesServlet Fest vorgegebenes Controller Servlet FacesServlet 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 Event-Listener facesconfig. xml request update Faces Servlet response retrieve facelet JSP JSP render faces Komponentenbaum Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

202 Java Server Faces Java Server Faces Übersicht Java Server Faces Komponentenbaum Abstraktion der Präsentation / View 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 Zusammenbau von Seiten aus Teilkomponenten Wiederverwendbare UI-Bausteine facesconfig. xml request update Faces Servlet response retrieve facelet JSP JSP render faces Komponentenbaum Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

203 Java Server Faces Java Server Faces Übersicht Java Server Faces Datenbindung Datenbindung 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 Deklaration Scope, dann Initialisierung, halten und entfernen automatisch facesconfig. xml request update Faces Servlet response retrieve facelet JSP JSP render faces Komponentenbaum Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

204 Java Server Faces JSF einrichten JSF Bibliotheken JSF Implementierung 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) Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

205 Java Server Faces 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

206 Java Server Faces JSF einrichten JSF-Konfiguration in faces-config.xml faces-config.xml Konfigurationsdatei für Java Server Faces Unter WEB-INF, neben web.xml Initial leer außer faces-config Tag faces-config.xml 1 <faces-config 2 xmlns=" 3 xmlns:xsi=" 4 xsi:schemalocation=" version="2.2">... 1 </faces-config> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

207 Java Server Faces JSF einrichten Eclipse JSF Tooling / Ermöglichen 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

208 Java Server Faces JSF einrichten Eclipse JSF Klicki Bunti 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

209 Java Server Faces JSF Erstes Beispiel Java Server Faces 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

210 Java Server Faces JSF Erstes Beispiel NameBean Wiederholung 1 public class NameBean implements Serializable { webanw.namebean 2 String vorname; String nachname; 3 String mittelname; int alter; Normale Bean, 4 public NameBean() { // parameterloser Konstruktor nichts JSF 5 vorname = "Max"; mittelname="m."; 6 nachname = "Mustermann"; alter = 0; spezifisches 7 } 8 public String getvorname() { return vorname; } Fast wie bei 9 public void setvorname(string vorname) { this.vorname = vorname; } JSP-Beispiel 10 public String getmittelname() { return mittelname; } Unterschiede 13 public void setnachname(string nachname) { this.nachname = nachname; } Rückgabewert 14 public int getalter() { return alter; } String bei 15 public void setalter(int alter) { this.alter = alter<0? 0 : alter; } gueltig 18 } Nur Lesen 19 public String gueltig() { // Logik Property 20 if (alter > 0 && status 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 / public void setmittelname(string mittelname) { this.mittelname = mittelname; } public String getname() { // Convenience, lesend (vorname+mittelname+nachname).length() >= 4) { public String getnachname() { return nachname; } return vorname+" "+mittelname+" "+nachname; return "ok";

211 Java Server Faces 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

212 Java Server Faces JSF Erstes Beispiel 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 NameBean.java 1 package webanw; 2 import javax.faces.bean.*; 3 6 public class NameBean 7 implements Serializable { } Vorteile Alles an einem Ort, einfacher Annotation und faces-config.xml Bei zusätzlicher Konfiguration in faces-config.xml überschreibt diese die Annotationen Verwendung der Annotationen als Default Werte 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

213 Java Server Faces 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

214 Java Server Faces JSF Erstes Beispiel 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

215 Java Server Faces JSF Erstes Beispiel Facelets Rahmen XHTML-Seite 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 2 " 3 <html xmlns=" 4 xmlns:f=" 5 xmlns:h=" 6 xmlns:ui=" 7 <h:head> 8 <title>der Titel</title> 9 0 </h:head> 1 <h:body> </h:body> 5 </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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

216 Java Server Faces JSF Erstes Beispiel 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}" /> 0 </h:panelgrid> 1 </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

217 Java Server Faces 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> 0 <h:commandbutton action="#{namebean.gueltig}" value="abschicken" /> 1 </h:form> 2 </h:body> <h:form>, notwendig bei Eingaben, wird gerne vergessen <h:inputtext> für Text-Eingabezeile <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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

218 Java Server Faces JSF Erstes Beispiel 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 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> 0 <tr><td><label for="j_idt6:age">alter</label></td> 1 <td><input id="j_idt6:age" type="text" name="j_idt6:age" value="17"></td></tr> 2 </tbody></table> 3 <input type="submit" name="j_idt6:j_idt15" value="abschicken"> 4 <input type="hidden" name="javax.faces.viewstate" id="j_id1:javax.faces.viewstate:0" 5 value=" : " autocomplete="off"> 6 </form></body> Komponentenbaum, auf Server Automatische Vergabe IDs Ausgabeelemente werden ignoriert Anspringen zentrales Servlet Flacher Pfad für HTML-Ausgabe input:9 form:6 input:11 input:13 input:17 submit:15 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

219 Java Server Faces 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! Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

220 Java Server Faces JSF Erstes Beispiel Navigationsregeln <navigation-rule> Haupt Tag <from-view-id> Ausgangsseite Absoluter Pfad in Web-Anwendung Pattern (/*) erlaubt 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 <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 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

221 Java Server Faces JSF Erstes Beispiel Navigation Festlegung der Folgeseite Abhängig von Outcome, action-attribut 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 Rückgabewert der Methode Beispiel: Ergebnis von namebean.gueltig() Statisch 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> Method-Binding ohne Klammern/Parameter Method-Expression mit... vermeiden Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

222 Java Server Faces JSF Erstes Beispiel Fehlermeldungen Anforderungen 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 Alternative während Entwicklung, PROJECT_STAGE auf Development in web.xml 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

223 Java Server Faces JSF Erstes Beispiel Fehlermeldungen an Passender Stelle 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

224 Java Server Faces Ablauf einer JSF-Anfrage Ablauf einer JSF-Anfrage Komponentenbaum (wieder-) herstellen Werte UI-Komp. mit Anfrageparam. aktualisieren Anfragebehandlung stoppen* Konvertierung und Validierung Antwort generieren, rendern direkt rendern Anwendung ausführen (action) Anfragebehandlung stoppen* Fehler direkt rendern Werte in Beans aktualisieren (setproperty) Ereignisbehandlung * wurde anderweitig behandelt, z.b. forward Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

225 Java Server Faces Ablauf einer JSF-Anfrage JSF-Ablauf Komponentenbaum 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

226 Java Server Faces Ablauf einer JSF-Anfrage JSF-Ablauf Werte Konvertieren und Validieren 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

227 Java Server Faces Ablauf einer JSF-Anfrage JSF-Ablauf Werte in den Beans aktualisieren, Aktion 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 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

228 Java Server Faces Ablauf einer JSF-Anfrage JSF-Ablauf Antwort Generieren 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

229 Java Server Faces Ablauf einer JSF-Anfrage 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

230 Java Server Faces Aktionen und Kommandos 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 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> Darstellung Kommandos statt Submit <h:commandbutton> <h:commandlink> Darstellung mit Bild möglich Beispiel 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 } Schaltknopf, Textlink, Imagelink An Methode kommando von bb gebunden Aufruf bb.kommando(), Rückgabe String Instanz einer passenden Bean unter dem Namen bb vorausgesetzt Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

231 Java Server Faces 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 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 } Parameter vom Framework gesetzt Über Parameter rufendes Widget Beispiel: Nachricht mit ID bei Klick auf linken Button Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

232 Java Server Faces Aktionen und Kommandos 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

233 Java Server Faces Aktionen und Kommandos Ausdrücke in Java Auflösen Problem 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 Expression Language Resolver 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); Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

234 Java Server Faces UI-Komponenten UI-Komponentenhierarchie, Auszug UIComponent UIComponentBase UIGraphic UICommand UIData UIPanel UIOutput UIInput <h:commandbutton> unabhängig von Anzeige Rendertypen HTMLCommandButton HTMLCommandLink HTMLInputHidden HTMLInputSecret HTMLInputText UISelectOne HTMLSelect OneListBox Image Button Table Grid Hidden ListBox Link Group Secret Text Menu Radio Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

235 Java Server Faces UI-Komponenten Styling 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> styleclass-attribut: Angabe der CSS-Klasse fürs Rendern Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

236 Java Server Faces UI-Komponenten Texteingabe 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> 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

237 Java Server Faces UI-Komponenten Facetten <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> Bei panelgrid ist Facette Überschrift über alle Spalten. Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

238 Java Server Faces UI-Komponenten Ja/Nein Auswahl <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 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

239 Java Server Faces UI-Komponenten Einfachauswahl Statisch <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 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> Alternativen <h:selectonelistbox> <h:selectonemenu> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

240 Java Server Faces UI-Komponenten Einfachauswahl dynamisch <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

241 Java Server Faces UI-Komponenten Mehrfachauswahl <h:selectmanylistbox> Wie One aber Ergebnis in Property vom Typ String[] oder List<String> 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 } Alternativen <h:selectmanycheckbox> <h:selectmanymenu> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

242 Java Server Faces UI-Komponenten Tabelle aus Daten <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

243 Java Server Faces Interaktion mit Kollektionen Interaktion mit Kollektionen DataModel Ziel Interaktion mit mehreren Objekten Bearbeiten eines Objekts in einer Sammlung von Objekten 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 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

244 Java Server Faces Interaktion mit Kollektionen Beispiel Auswahl, Editieren, Sichern Beispiel Auswahl: Wähle ein Element aus einer Sammlung von Elementen 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

245 Java Server Faces Interaktion mit Kollektionen Backing-Bean für Interaktion DataModelBackingBean 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 Passende Getter zum Zugriff 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 }... 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 / 295

246 Java Server Faces Interaktion mit Kollektionen Darstellung und Auswahl 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> DataModelBackingBean.java 1 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

247 Java Server Faces 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

248 Java Server Faces Interaktion mit Kollektionen 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

249 Java Server Faces 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

250 Java Server Faces Interaktion mit Kollektionen 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

251 Java Server Faces 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 } Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

252 Java Server Faces Interaktion mit Kollektionen 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

253 Java Server Faces 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

254 Java Server Faces GET-Unterstützung Bookmarks, GET-Unterstützung 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}" /> Umsetzung 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

255 Java Server Faces GET-Unterstützung Bookmarks Anmerkungen View-Parameter weitergeben Potenziell empfangen Seiten, die GET-Parameter enthalten auch GET-Parameter Einfache Möglichkeit alle GET-Parameter weiterzugeben mit includeviewparams 1 <h:column> 2 <h:link value="details" 3 includeviewparams="true" 4 outcome="detail" > </h:link> 7 </h:column> 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

256 Java Server Faces Konvertierung und Validierung Konvertierung und Validierung 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

257 Java Server Faces Konvertierung und Validierung Konvertierung Beispiel NameBean 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

258 Java Server Faces Konvertierung und Validierung Konverter Einbettung 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"> 0 <h:outputlabel value="vorname:"/> <h:outputtext value="#{namebean.vorname}" /> 1 <h:outputlabel value="mittelname:"/> <h:outputtext value="#{namebean.mittelname}" /> 2 <h:outputlabel value="nachname:"/> <h:outputtext value="#{namebean.nachname}" /> 3 <h:outputlabel value="alter:"/> <h:outputtext value="#{namebean.alter}" /> 4 </h:panelgrid> 5 </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

259 Java Server Faces 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

260 Java Server Faces Konvertierung und Validierung 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

261 Java Server Faces Konvertierung und Validierung Standard-Validatoren Verwendung <f:validate... /> disabled-attribut Weitere Attribute spezifisch je Tag Mehrere kombiniert erlaubt Standard-Validatoren <f:validatelongrange>, <f:validatedoublerange>, <f:validatelength> (String) minimum/maximum, Zahl oder Anzahl Zeichen 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> <f:validateregex>, reg. Ausdruck <f:validaterequired>, Muß-Eingabe Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

262 Java Server Faces Konvertierung und Validierung Benutzerspezifische Validatoren Beispiel Anforderungen Nur geradzahlige Zahlen Mit 3 Ziffern Oder festlegbarer Anzahl von Ziffern Passende Fehlermeldungen Fehlschlag, bei 3 Ziffern In Ordnung Fehlschlag, bei 2 Ziffern Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

263 Java Server Faces 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

264 Java Server Faces Konvertierung und Validierung 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

265 Java Server Faces 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 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 Es muss noch angegeben werden, dass gespeichert werden darf istransient, Setter dann auch Zwang Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

266 Java Server Faces Konvertierung und Validierung 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=" 3 xmlns:xsi=" 4 xsi:schemalocation=" 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

267 Java Server Faces 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=" 2 xmlns:f=" 3 xmlns:h=" 4 xmlns:ui=" 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

268 Java Server Faces Konvertierung und Validierung 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

269 Java Server Faces 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=" 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

270 Java Server Faces Komposition und Templating 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

271 Java Server Faces 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

272 Java Server Faces Komposition und Templating 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

273 Java Server Faces Komposition und Templating Templates in Templates Teilweise ausgefüllte Templates sind wieder Templates 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 und können wieder ausgefüllt werden 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

274 Java Server Faces Komposition und Templating 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

275 Java Server Faces Komposition und Templating Wiederholungen <ui:repeat> Nur für die Ausgabe Ersatz für <c:foreach> Funktioniert mit Facelets 1 <ul> 2 <ui:repeat var="nb" 3 value="#{dmbb.liste}"> 4 <li>#{nb.vorname} #{nb.nachname}</li> 5 </ui:repeat> 6 </ul> Verschachtelung erlaubt Attribute value Iterierbare Kollektion var Laufvariable varstatus, offset, step Bedingte Ausgabe Konditionale Ausdrücke oder rendered-attribut Empfehlung: Vermeiden <h:datatable> verwenden Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

276 Java Server Faces Ressourcen-Management Ressourcen-Management 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

277 Java Server Faces Ressourcen-Management Rahmen und Namen 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 Transiti 2 " 3 <html xmlns=" 4 xmlns:f=" 5 xmlns:h=" 6 xmlns:ui=" 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

278 Java Server Faces Ressourcen-Management Bibliotheken, Expression Language 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 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 ]}" /> Implizites resource-objekt Direkte Pfadangabe, gib generierten Pfad aus (nicht verwenden) /resources/images/sunlogo.png Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

279 Java Server Faces 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

280 Java Server Faces Ressourcen-Management 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

281 Java Server Faces Ressourcen-Management 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

282 Java Server Faces Eigene Komponenten 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=" 2 xmlns:f=" 3 xmlns:h=" 4 xmlns:ui=" 5 xmlns: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

283 Java Server Faces Eigene Komponenten 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=" 2 xmlns:f=" 3 xmlns:h=" 4 xmlns:ui=" 5 xmlns:components= 6 " 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> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

284 Java Server Faces Ajax und Single Page 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

285 Java Server Faces Ajax und Single Page JavaScript 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

286 Java Server Faces Ajax und Single Page Asynchroner Rückkanal XMLHttpRequest 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

287 Java Server Faces Ajax und Single Page Ajax Ergebnis 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 Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

288 Java Server Faces Ajax und Single Page Ajax und JSF 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

289 Java Server Faces Ajax und Single Page Beispiel Single Page App mit Ajax Beispiel Ausgangssituation Neuer Mittelname XXX, Ok(Ajax) Eingabe-Seite mit Ausgabebereich Ausgabe-Bereich geht von Name bis Alter, aktuelles Datum separat Neuer Mittelname YYY, Ok(Seite) Ok(Ajax): Datum (außerhalb Ausgabe) bleibt, nicht neu gerendert Ok(Seite): Die ganze Seite, und damit das Datum, wird aktualisiert Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

290 Java Server Faces Ajax und Single Page 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? 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 execute="@form" 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> Vorgabe action bei command* oder onchange bei input* Alle on* nur ohne on Mehrere Teile bei render, durch Leerzeichen getrennt Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

291 Java Server Faces 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 execute="@form" 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

292 Java Server Faces Ajax und Single Page 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

293 Java Server Faces Ajax und Single Page Beispiel Klappen, Detail boxes Welche Zeilen angezeigen? Boolesche Property je String-Property panels Label, Eingabefeld, anzeigen? Je Zeichenkette eine Zeile Zeilen können ausgeblendet werden zeit: Aktuelle Uhrzeit aus Backing-Bean Sonst Ok(Ajax), aktualisieren ohne Eingabewerte zu lesen Update(Ajax), aktualisieren mit Eingabewerte lesen Update(Seite), ganzer Request Nochmal aktuelle Uhrzeit, ohne Ajax boxes Eingabefelder Blendet Zeilen in panels ein und aus panels zeit Aktuelle Zeit Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

294 Java Server Faces Ajax und Single Page Beispiel Klappen, Umsetzung Umschließendes <f:ajax> Default-Verhalten für alle umschlossenen Elemente Checkbox mit onchange sonst nichts Bei Änderung neu rendern Effekt: Klick klappt Zeile ein oder12 rendered="#{bb.showzk1}"> aus Zk1 <h:inputtext value="#{bb.zk1}"/> #{bb.showzk1} </h:panelgrid> Unteres <f:ajax>... Wie vorher Explizit eine der zwei Zeitangaben neu rendern Anmerkungen: rendered und id nicht mischbar 1 <h:form> 2 <f:ajax render="panels"> 3 <h:panelgrid columns="3" id="boxes"> 4 Zk1 <h:outputtext value="zk2"/> Zk3 5 <h:selectbooleancheckbox value="#{bb.showzk1}" /> 6 <h:selectbooleancheckbox value="#{bb.showzk2}" /> 7 <h:selectbooleancheckbox value="#{bb.showzk3}" /> 8 </h:panelgrid> 9 </f:ajax> 10 <h:panelgrid columns="1" id="panels"> 11 <h:panelgrid columns="3" border="1" 1 <h:commandbutton value="ok(ajax)"> 2 <f:ajax render="panels zeit" execute="boxes"/> 3 </h:commandbutton> 4 <h:commandbutton value="update(ajax)"> 5 <f:ajax render="panels zeit" execute="boxes panels"/> 6 </h:commandbutton> 7 <h:commandbutton value="update(seite)" /> 8 <h:outputtext value="#{bb.jetzt}" id="zeit" /> 9 </h:form> 10 <center>#{bb.jetzt}</center> Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

295 Java Server Faces Wie Weiter Wie Weiter... JavaEE mehr als nur Web-UI Anwendungs- und Datenschicht, im Master oder in Vertiefungen Persistenzlayer (JPA), im Projekt gegeben Enterprise Java Beans, Application Server Alternative Web-Frameworks Java: Struts, Vaadin,... JavaVM: Grails (Groovy),... Andere Sprachen/Umgebungen Ruby on Rails Django (Python), Sommerschool bei Interesse! Zend (PHP) Andere UI-Ansätze: GWT, JQuery/ExtJS,... Prof. Dr. Peter Barth (HS-RheinMain) Web-basierte Anwendungen 6. Juli / 295

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

Organisatorisches. Web-basierte Anwendungen. Ziele der Veranstaltung. Voraussetzungen Organisatorisches Organisatorisches Web-basierte Anwendungen Grundlagen und Frameworks Prof. Dr. Peter Barth Hochschule RheinMain Fachbereich Design Informatik Medien Medieninformatik 6. Juli 2015 Prof.

Mehr

Python CGI-Skripte erstellen

Python CGI-Skripte erstellen Python CGI-Skripte erstellen CGI (Common Gateway Interface)... ist eine Schnittstelle, um Scripte im Web bereitzustellen. ist eine Schnittstelle zwischen einem HTTP-Server und ausführbaren Programmen.

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

OP-LOG www.op-log.de

OP-LOG www.op-log.de Verwendung von Microsoft SQL Server, Seite 1/18 OP-LOG www.op-log.de Anleitung: Verwendung von Microsoft SQL Server 2005 Stand Mai 2010 1 Ich-lese-keine-Anleitungen 'Verwendung von Microsoft SQL Server

Mehr

WEBAPPLIKATIONEN MIT PHP. Wo gibt es Hilfe? Wie fang ich an?

WEBAPPLIKATIONEN MIT PHP. Wo gibt es Hilfe? Wie fang ich an? WEBAPPLIKATIONEN MIT PHP Wo gibt es Hilfe? Wie fang ich an? Tools Webapplikationen bestehen aus Textdateien Lassen sich in Texteditoren schreiben Alternativen: Eclipse (PDT) Netbeans (Dynamic Languages)

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

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

Aufgaben HTML Formulare. Prof. Dr. rer. nat. Claus Brell, http://claus-brell.de, claus.brell@hs-niederrhein.de, Wirtschaftsinformatik, Statistik

Aufgaben HTML Formulare. Prof. Dr. rer. nat. Claus Brell, http://claus-brell.de, claus.brell@hs-niederrhein.de, Wirtschaftsinformatik, Statistik 1 Aufgaben HTML Formulare Aufgabe 1 (Vorbereitung) Google Suche 2 Probieren vor Studieren.. Arbeitsauftrag: 1.) Fügen Sie mit Notepad++ in Ihrer Datei index.html den unten gezeigten Quelltextschnipsel

Mehr

Einführung in die Scriptsprache PHP

Einführung in die Scriptsprache PHP Herbst 2014 Einführung in die Scriptsprache PHP Wirtschaftsinformatik: 5. Semester Dozenten: Rainer Telesko / Martin Hüsler Fachhochschule Nordwestschweiz FHNW - Rainer Telesko / Martin Hüsler 1 Inhalt:

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

HTML5. Wie funktioniert HTML5? Tags: Attribute:

HTML5. Wie funktioniert HTML5? Tags: Attribute: HTML5 HTML bedeutet Hypertext Markup Language und liegt aktuell in der fünften Fassung, also HTML5 vor. HTML5 ist eine Auszeichnungssprache mit der Webseiten geschrieben werden. In HTML5 wird festgelegt,

Mehr

Novell Client. Anleitung. zur Verfügung gestellt durch: ZID Dezentrale Systeme. Februar 2015. ZID Dezentrale Systeme

Novell Client. Anleitung. zur Verfügung gestellt durch: ZID Dezentrale Systeme. Februar 2015. ZID Dezentrale Systeme Novell Client Anleitung zur Verfügung gestellt durch: ZID Dezentrale Systeme Februar 2015 Seite 2 von 8 Mit der Einführung von Windows 7 hat sich die Novell-Anmeldung sehr stark verändert. Der Novell Client

Mehr

Adminer: Installationsanleitung

Adminer: Installationsanleitung Adminer: Installationsanleitung phpmyadmin ist bei uns mit dem Kundenmenüpasswort geschützt. Wer einer dritten Person Zugriff auf die Datenbankverwaltung, aber nicht auf das Kundenmenü geben möchte, kann

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

Eine Anwendung mit InstantRails 1.7

Eine Anwendung mit InstantRails 1.7 Eine Anwung mit InstantRails 1.7 Beschrieben wird das Anlegen einer einfachen Rails-Anwung, die ohne Datenbank auskommt. Schwerpunktmäßig wird auf den Zusammenhang von Controllern, Views und der zugehörigen

Mehr

Schiller-Gymnasium Hof 20.12.2004

Schiller-Gymnasium Hof 20.12.2004 Erstellen eines HTML-Dokumentes Zum Erstellen einer Homepage benötigen wir lediglich einen Editor. Zum Ansehen der fertigen Site benötigen wir wir natürlich auch einen Browser, z.b. Firefox oder Netscape

Mehr

Einrichten des IIS für VDF WebApp. Einrichten des IIS (Internet Information Server) zur Verwendung von Visual DataFlex Web Applications

Einrichten des IIS für VDF WebApp. Einrichten des IIS (Internet Information Server) zur Verwendung von Visual DataFlex Web Applications Einrichten des IIS (Internet Information Server) zur Verwendung von Visual DataFlex Web Applications Windows 8 Systemsteuerung > Programme > Windows Features aktivieren / deaktivieren > Im Verzeichnisbaum

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

ecaros2 - Accountmanager

ecaros2 - Accountmanager ecaros2 - Accountmanager procar informatik AG 1 Stand: FS 09/2012 Inhaltsverzeichnis 1 Aufruf des ecaros2-accountmanager...3 2 Bedienung Accountmanager...4 procar informatik AG 2 Stand: FS 09/2012 1 Aufruf

Mehr

Python SVN-Revision 12

Python SVN-Revision 12 Python SVN-Revision 12 Uwe Ziegenhagen 7. Januar 2012 Vorwort Dieses Skript erhebt keinen Anspruch auf Vollständigkeit oder Richtigkeit. Es wird geschrieben, um mir als Gedächtnisstütze für den Umgang

Mehr

Seminar DWMX 2004. DW Session 015

Seminar DWMX 2004. DW Session 015 Seminar DWMX 2004 DW Session 015 Veröffentlichen der lokalen Website Bis jetzt sind die Daten immer lokal in Dreamweaver bearbeitet und über die interne Vorschau mit F12/Strg.+F12 im Browser betrachtet

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

Datenbank-Verschlüsselung mit DbDefence und Webanwendungen.

Datenbank-Verschlüsselung mit DbDefence und Webanwendungen. Datenbank-Verschlüsselung mit DbDefence und Webanwendungen. In diesem Artikel werden wir Ihnen zeigen, wie Sie eine Datenbank verschlüsseln können, um den Zugriff einzuschränken, aber trotzdem noch eine

Mehr

PHP - Projekt Personalverwaltung. Erstellt von James Schüpbach

PHP - Projekt Personalverwaltung. Erstellt von James Schüpbach - Projekt Personalverwaltung Erstellt von Inhaltsverzeichnis 1Planung...3 1.1Datenbankstruktur...3 1.2Klassenkonzept...4 2Realisierung...5 2.1Verwendete Techniken...5 2.2Vorgehensweise...5 2.3Probleme...6

Mehr

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter 2 Inhaltsverzeichnis 1 Web-Kürzel 4 1.1 Einführung.......................................... 4 1.2 Web-Kürzel.........................................

Mehr

Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite.

Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite. ewon - Technical Note Nr. 003 Version 1.2 Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite. Übersicht 1. Thema 2. Benötigte Komponenten 3. Downloaden der Seiten und aufspielen auf

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

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

Man liest sich: POP3/IMAP

Man liest sich: POP3/IMAP Man liest sich: POP3/IMAP Gliederung 1. Einführung 1.1 Allgemeiner Nachrichtenfluss beim Versenden von E-Mails 1.2 Client und Server 1.2.1 Client 1.2.2 Server 2. POP3 2.1 Definition 2.2 Geschichte und

Mehr

Informatik I: Einführung in die Programmierung

Informatik I: Einführung in die Programmierung Informatik I: Einführung in die Programmierung 21. Das WWW befragen Albert-Ludwigs-Universität Freiburg Bernhard Nebel 13.01.2015 13.01.2015 B. Nebel Info I 2 / 17 Oft braucht ein Programm Informationen,

Mehr

Thomas Wagner 2009 (im Rahmen der TA) Installation von MySQL 5.0 und Tomcat 5.5

Thomas Wagner 2009 (im Rahmen der TA) Installation von MySQL 5.0 und Tomcat 5.5 Thomas Wagner 2009 (im Rahmen der TA) Installation von MySQL 5.0 und Tomcat 5.5 Im Folgenden wird die Installation von MySQL 5.0 und Tomcat 5.0 beschrieben. Bei MySQL Server 5.0 handelt es sich um ein

Mehr

OUTLOOK-DATEN SICHERN

OUTLOOK-DATEN SICHERN OUTLOOK-DATEN SICHERN Wie wichtig es ist, seine Outlook-Daten zu sichern, weiß Jeder, der schon einmal sein Outlook neu installieren und konfigurieren musste. Alle Outlook-Versionen speichern die Daten

Mehr

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge Ab der Version forma 5.5 handelt es sich bei den Orientierungshilfen der Architekten-/Objektplanerverträge nicht

Mehr

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken. Seite erstellen Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken. Es öffnet sich die Eingabe Seite um eine neue Seite zu erstellen. Seiten Titel festlegen Den neuen

Mehr

Agentur für Werbung & Internet. Schritt für Schritt: Newsletter mit WebEdition versenden

Agentur für Werbung & Internet. Schritt für Schritt: Newsletter mit WebEdition versenden Agentur für Werbung & Internet Schritt für Schritt: Newsletter mit WebEdition versenden E-Mail-Adresse im Control Panel einrichten Inhalt Vorwort 3 Einstellungen im Reiter «Eigenschaften» 4 Einstellungen

Mehr

Möglichkeiten des Parallelbetriebs der VR-NetWorld Software Parallelbetrieb VR-NetWorld Software 4.4x und Version 5.0 ab der 2. Beta!

Möglichkeiten des Parallelbetriebs der VR-NetWorld Software Parallelbetrieb VR-NetWorld Software 4.4x und Version 5.0 ab der 2. Beta! Möglichkeiten des Parallelbetriebs der VR-NetWorld Software Um mehrere Versionsstände parallel betreiben zu können, sollte man die folgenden Hintergründe kennen, um zu verstehen wo ggf. die Hürden liegen.

Mehr

Vorbereitungen zum SIMOTION Webserver Tutorial Anwenderdefinierte Webseiten

Vorbereitungen zum SIMOTION Webserver Tutorial Anwenderdefinierte Webseiten SIMOTION Tutorials Vorbereitungen zum SIMOTION Webserver Tutorial Anwenderdefinierte Webseiten siemens.com/answers SIMOTION- 2 Webserver aktivieren 3 Demo-Variablen hinzufügen 4 Web-Editor 6 Web- 10 SIMOTION

Mehr

Überblick. Netzprogrammierung 7b. Zustand in Web Anwendungen. Zustand in HTTP HTTP ist zustandslos Zwei Interaktionen sind unabhängig voneinander

Überblick. Netzprogrammierung 7b. Zustand in Web Anwendungen. Zustand in HTTP HTTP ist zustandslos Zwei Interaktionen sind unabhängig voneinander Überblick 1. Zustand in Web Anwendungen Netzprogrammierung 7b. Zustand in Web Anwendungen Prof. Dr.-Ing. Robert Tolksdorf Freie Universität Berlin Institut für Informatik Netzbasierte Informationssysteme

Mehr

HTML Formulare. Benutzerschnittstelle für interaktive Webseiten

HTML Formulare. Benutzerschnittstelle für interaktive Webseiten 1 HTML Formulare Benutzerschnittstelle für interaktive Webseiten Literatur und Links 2 Literatur: Coar, Ken; Bowen, Rich: Apache-Kochbuch. 2004 HTML: kein Buch oder irgend eins für Einsteiger, z. B. Münz,

Mehr

Planung für Organisation und Technik

Planung für Organisation und Technik Salztorgasse 6, A - 1010 Wien, Austria q Planung für Organisation und Technik MOA-VV Installation Bearbeiter: Version: Dokument: Scheuchl Andreas 19.11.10 MOA-VV Installation.doc MOA-VV Inhaltsverzeichnis

Mehr

EJB Beispiel. JEE Vorlesung 10. Ralf Gitzel ralf_gitzel@hotmail.de

EJB Beispiel. JEE Vorlesung 10. Ralf Gitzel ralf_gitzel@hotmail.de EJB Beispiel JEE Vorlesung 10 Ralf Gitzel ralf_gitzel@hotmail.de 1 Stundenkonzept Gemeinsame Übung Stoff der letzten Stunde wird gemeinsam in einem Beispiel umgesetzt Details werden nochmals erklärt bzw.

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

Online-Publishing mit HTML und CSS für Einsteigerinnen

Online-Publishing mit HTML und CSS für Einsteigerinnen mit HTML und CSS für Einsteigerinnen Dipl.-Math. Eva Dyllong Universität Duisburg Dipl.-Math. Maria Oelinger spirito GmbH IF MYT 07-2002 Web-Technologien Überblick HTML und CSS, XML und DTD, JavaScript

Mehr

www.flatbooster.com FILEZILLA HANDBUCH

www.flatbooster.com FILEZILLA HANDBUCH www.flatbooster.com FILEZILLA HANDBUCH deutsche Auflage Datum: 12.03.2011 Version: 1.0.2 Download: http://flatbooster.com/support Inhaltsverzeichnis 1 Filezilla FTP Programm 1 1.1 Filezilla installieren.................................

Mehr

Klausurteilnehmer. Wichtige Hinweise. Note: Klausur Informatik Programmierung, 17.09.2012 Seite 1 von 8 HS OWL, FB 7, Malte Wattenberg.

Klausurteilnehmer. Wichtige Hinweise. Note: Klausur Informatik Programmierung, 17.09.2012 Seite 1 von 8 HS OWL, FB 7, Malte Wattenberg. Klausur Informatik Programmierung, 17.09.2012 Seite 1 von 8 Klausurteilnehmer Name: Matrikelnummer: Wichtige Hinweise Es sind keinerlei Hilfsmittel zugelassen auch keine Taschenrechner! Die Klausur dauert

Mehr

SSO-Schnittstelle. Inhalt: Beschreibung der Single Sign-On (SSO) Schnittstelle. NetSlave GmbH Simon-Dach-Straße 12 D-10245 Berlin

SSO-Schnittstelle. Inhalt: Beschreibung der Single Sign-On (SSO) Schnittstelle. NetSlave GmbH Simon-Dach-Straße 12 D-10245 Berlin SSO-Schnittstelle Inhalt: Beschreibung der Single Sign-On (SSO) Schnittstelle NetSlave GmbH Simon-Dach-Straße 12 D-10245 Berlin Telefon +49 (0)30-94408-730 Telefax +49 (0)30-96083-706 E-Mail mail@netslave.de

Mehr

RESTful Web. Representational State Transfer

RESTful Web. Representational State Transfer RESTful Web Representational State Transfer 1 Warum REST? REST ist die Lingua Franca des Webs Heterogene (verschiedenartige) Systeme können mit REST kommunizieren, unabhängig von Technologie der beteiligten

Mehr

Workshop Java Webentwicklung Tapestry. Ulrich Stärk

Workshop Java Webentwicklung Tapestry. Ulrich Stärk Workshop Java Webentwicklung Tapestry Ulrich Stärk Webanwendungen Antwort im Browser des Benutzers sichtbar Anfrage geht ein Antwort rendern Anfrage an passenden Code weiterleiten 2 Servlets Servlet wird

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

Installation des GeoShop Redirector für Apache (Stand 14.8.2007) ================================================================

Installation des GeoShop Redirector für Apache (Stand 14.8.2007) ================================================================ Installation des GeoShop Redirector für Apache (Stand 14.8.2007) ================================================================ 0 Überblick ----------- Die Installation des GeoShop Redirector im Apache

Mehr

Session Beans & Servlet Integration. Ralf Gitzel ralf_gitzel@hotmail.de

Session Beans & Servlet Integration. Ralf Gitzel ralf_gitzel@hotmail.de s & Servlet Integration Ralf Gitzel ralf_gitzel@hotmail.de 1 Themenübersicht Ralf Gitzel ralf_gitzel@hotmail.de 2 Übersicht Motivation Das Interface Stateful und Stateless s Programmierung einer Stateful

Mehr

Plugins. Stefan Salich (sallo@gmx.de) Stand 2008-11-21

Plugins. Stefan Salich (sallo@gmx.de) Stand 2008-11-21 Plugins Stefan Salich (sallo@gmx.de) Stand 2008-11-21 Inhaltsverzeichnis 0 Einleitung...3 0.1 Sinn und Zweck...3 0.2 Änderungsübersicht...3 0.3 Abkürzungsverzeichnis...3 1 Einfügen eines Plugins...4 1.1

Mehr

INSTALLATION. Voraussetzungen

INSTALLATION. Voraussetzungen INSTALLATION Voraussetzungen Um Papoo zu installieren brauchen Sie natürlich eine aktuelle Papoo Version die Sie sich auf der Seite http://www.papoo.de herunterladen können. Papoo ist ein webbasiertes

Mehr

Erstellen von Mailboxen

Erstellen von Mailboxen Seite 1 von 5 Erstellen von Mailboxen Wenn Sie eine E-Mail-Adresse anlegen möchten, mit Ihrem Domain-Namen, z. B. IhrName@Domain.com, müssen Sie eine Mailbox erstellen. Gehen Sie hierzu wie folgt vor:

Mehr

Die Beschreibung bezieht sich auf die Version Dreamweaver 4.0. In der Version MX ist die Sitedefinition leicht geändert worden.

Die Beschreibung bezieht sich auf die Version Dreamweaver 4.0. In der Version MX ist die Sitedefinition leicht geändert worden. In einer Website haben Seiten oft das gleiche Layout. Speziell beim Einsatz von Tabellen, in denen die Navigation auf der linken oder rechten Seite, oben oder unten eingesetzt wird. Diese Anteile der Website

Mehr

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage .htaccess HOWTO zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage Stand: 21.06.2015 Inhaltsverzeichnis 1. Vorwort...3 2. Verwendung...4 2.1 Allgemeines...4 2.1 Das Aussehen der.htaccess

Mehr

Standard-Kontaktformular

Standard-Kontaktformular Online-Tutorials Referat VI.5 Internetdienste Standard-Kontaktformular Legen Sie ein neues Dokument an Klicken Sie die Datei an, unter der Sie das Kontaktformular anlegen möchten Legen Sie über Datei >

Mehr

Artikel Schnittstelle über CSV

Artikel Schnittstelle über CSV Artikel Schnittstelle über CSV Sie können Artikeldaten aus Ihrem EDV System in das NCFOX importieren, dies geschieht durch eine CSV Schnittstelle. Dies hat mehrere Vorteile: Zeitersparnis, die Karteikarte

Mehr

Fachbericht zum Thema: Anforderungen an ein Datenbanksystem

Fachbericht zum Thema: Anforderungen an ein Datenbanksystem Fachbericht zum Thema: Anforderungen an ein Datenbanksystem von André Franken 1 Inhaltsverzeichnis 1 Inhaltsverzeichnis 1 2 Einführung 2 2.1 Gründe für den Einsatz von DB-Systemen 2 2.2 Definition: Datenbank

Mehr

Task: Nmap Skripte ausführen

Task: Nmap Skripte ausführen Task: Nmap Skripte ausführen Inhalt Einfache Netzwerkscans mit NSE Ausführen des Scans Anpassung der Parameter Einleitung Copyright 2009-2015 Greenbone Networks GmbH Herkunft und aktuellste Version dieses

Mehr

Success! Bestellausgabe

Success! Bestellausgabe Success! Bestellausgabe 2 Bestellausgabe in SUCCESS! Für die Anbindung an die Bestellsysteme ihrer Lieferanten ist es möglich, die in Success! erzeugten Bestellungen, in eine Datei auszugeben und optional

Mehr

XQueue Product Sheet - Seiten Editor

XQueue Product Sheet - Seiten Editor XQueue Product Sheet - Seiten Editor 2011 XQueue GmbH. Alle Rechte vorbehalten. Dokumentation für das E-Mail Campaign System Diese Dokumentation darf ohne vorherige schriftliche Genehmigung durch die XQueue

Mehr

Medea3 Print-Client (m3_print)

Medea3 Print-Client (m3_print) Medea3 Print-Client (m3_print) Installationsanleitung Installationsanleitung m3_print.exe...2 1. Installieren von Ghostskript und Ghostview...2 1. Ghostskript...2 2. Ghostview...3 2. Kopieren des Print-Client-Programms...6

Mehr

Senden von strukturierten Berichten über das SFTP Häufig gestellte Fragen

Senden von strukturierten Berichten über das SFTP Häufig gestellte Fragen Senden von strukturierten Berichten über das SFTP Häufig gestellte Fragen 1 Allgemeines Was versteht man unter SFTP? Die Abkürzung SFTP steht für SSH File Transfer Protocol oder Secure File Transfer Protocol.

Mehr

ESB - Elektronischer Service Bericht

ESB - Elektronischer Service Bericht Desk Software & Consulting GmbH ESB - Elektronischer Service Bericht Dokumentation des elektronischen Serviceberichts Matthias Hoffmann 25.04.2012 DESK Software und Consulting GmbH Im Heerfeld 2-4 35713

Mehr

Kurzanleitung zu. von Daniel Jettka 18.11.2008

Kurzanleitung zu. von Daniel Jettka 18.11.2008 Kurzanleitung zu Tigris.org Open Source Software Engineering Tools von Daniel Jettka 18.11.2008 Inhaltsverzeichnis 1.Einführung...1 2.Das Projektarchivs...3 2.1.Anlegen des Projektarchivs...3 2.2.Organisation

Mehr

Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER

Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER Abamsoft Finos in Verbindung mit der Webshopanbindung wurde speziell auf die Shop-Software shop to date von DATA BECKER abgestimmt. Mit

Mehr

Einführung in PHP. (mit Aufgaben)

Einführung in PHP. (mit Aufgaben) Einführung in PHP (mit Aufgaben) Dynamische Inhalte mit PHP? 2 Aus der Wikipedia (verkürzt): PHP wird auf etwa 244 Millionen Websites eingesetzt (Stand: Januar 2013) und wird auf etwa 80 % aller Websites

Mehr

Kurzeinführung Excel2App. Version 1.0.0

Kurzeinführung Excel2App. Version 1.0.0 Kurzeinführung Excel2App Version 1.0.0 Inhalt Einleitung Das Ausgangs-Excel Excel-Datei hochladen Excel-Datei konvertieren und importieren Ergebnis des Imports Spalten einfügen Fehleranalyse Import rückgängig

Mehr

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein.

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein. Schritt 1: Installation des Javacompilers JDK. Der erste Start mit Eclipse Bevor Sie den Java-Compiler installieren sollten Sie sich vergewissern, ob er eventuell schon installiert ist. Gehen sie wie folgt

Mehr

IT-Zertifikat: Allgemeine Informationstechnologien II PHP

IT-Zertifikat: Allgemeine Informationstechnologien II PHP IT-Zertifikat: Allgemeine Informationstechnologien II PHP PHP ( PHP: Hypertext Preprocessor ) ist eine serverseitige Skriptsprache: Der PHP-Code wird nicht wie bei JavaScript auf dem Clientrechner ausgeführt,

Mehr

Themen. Apache Webserver Konfiguration. Verzeichnisse für Web-Applikationen. Server Side Includes

Themen. Apache Webserver Konfiguration. Verzeichnisse für Web-Applikationen. Server Side Includes Themen Apache Webserver Konfiguration Verzeichnisse für Web-Applikationen Server Side Includes Apache Webserver Konfiguration des Apache Webservers Server-Einstellungen in der httpd.conf-datei Einteilung

Mehr

Guide DynDNS und Portforwarding

Guide DynDNS und Portforwarding Guide DynDNS und Portforwarding Allgemein Um Geräte im lokalen Netzwerk von überall aus über das Internet erreichen zu können, kommt man um die Themen Dynamik DNS (kurz DynDNS) und Portweiterleitung(auch

Mehr

Java - Webapplikationen

Java - Webapplikationen Java - Webapplikationen Bestandteile (HTTP,, JSP) Aufbau (Model View Controller) Datenverwaltung (Java Beans, Sessions) Entwicklung (Projektstruktur, Sysdeoplugin für Eclipse) 17. Januar 2006 Jan Hatje

Mehr

Musterlösung für Schulen in Baden-Württemberg. Windows 2003. Basiskurs Windows-Musterlösung. Version 3. Stand: 19.12.06

Musterlösung für Schulen in Baden-Württemberg. Windows 2003. Basiskurs Windows-Musterlösung. Version 3. Stand: 19.12.06 Musterlösung für Schulen in Baden-Württemberg Windows 2003 Basiskurs Windows-Musterlösung Version 3 Stand: 19.12.06 Impressum Herausgeber Zentrale Planungsgruppe Netze (ZPN) am Kultusministerium Baden-Württemberg

Mehr

OSx / MAC. MegaZine3 MZ3-Tool3. Server Upload. Video 2-4

OSx / MAC. MegaZine3 MZ3-Tool3. Server Upload. Video 2-4 OSx / MAC MegaZine3 MZ3-Tool3 Server Upload Video 2-4 Grundlagen Eine MegaZine3 Online Version unterscheidet sich in ein paar Dingen von einer lokalen Version: Online / Server / Browser Version Offline

Mehr

KURZANLEITUNG CLOUD OBJECT STORAGE

KURZANLEITUNG CLOUD OBJECT STORAGE KURZANLEITUNG CLOUD OBJECT STORAGE Version 1.12 01.07.2014 SEITE _ 2 INHALTSVERZEICHNIS 1. Einleitung... Seite 03 2. Anmelden am Cloud&Heat Dashboard... Seite 04 3. Anlegen eines Containers... Seite 05

Mehr

Aufklappelemente anlegen

Aufklappelemente anlegen Aufklappelemente anlegen Dieses Dokument beschreibt die grundsätzliche Erstellung der Aufklappelemente in der mittleren und rechten Spalte. Login Melden Sie sich an der jeweiligen Website an, in dem Sie

Mehr

Ihre Interessentendatensätze bei inobroker. 1. Interessentendatensätze

Ihre Interessentendatensätze bei inobroker. 1. Interessentendatensätze Ihre Interessentendatensätze bei inobroker Wenn Sie oder Ihre Kunden die Prozesse von inobroker nutzen, werden Interessentendatensätze erzeugt. Diese können Sie direkt über inobroker bearbeiten oder mit

Mehr

MSDE 2000 mit Service Pack 3a

MSDE 2000 mit Service Pack 3a MSDE 2000 mit Service Pack 3a Neues MSDE im WINLine-Setup: Seit der WINLine 8.2 Build 972 wird auf der WINLine-CD ein neues Setup der Microsoft MSDE mit ausgeliefert. Mit dieser neuen Version MSDE 2000

Mehr

Tevalo Handbuch v 1.1 vom 10.11.2011

Tevalo Handbuch v 1.1 vom 10.11.2011 Tevalo Handbuch v 1.1 vom 10.11.2011 Inhalt Registrierung... 3 Kennwort vergessen... 3 Startseite nach dem Login... 4 Umfrage erstellen... 4 Fragebogen Vorschau... 7 Umfrage fertigstellen... 7 Öffentliche

Mehr

Übung: Verwendung von Java-Threads

Übung: Verwendung von Java-Threads Übung: Verwendung von Java-Threads Ziel der Übung: Diese Übung dient dazu, den Umgang mit Threads in der Programmiersprache Java kennenzulernen. Ein einfaches Java-Programm, das Threads nutzt, soll zum

Mehr

Die Installation des GeoShop Redirector für IIS (Internet Information Server, Version 4.0, 5.0 und 6.0) umfasst folgende Teilschritte:

Die Installation des GeoShop Redirector für IIS (Internet Information Server, Version 4.0, 5.0 und 6.0) umfasst folgende Teilschritte: Installation des GeoShop Redirector für IIS (Stand 24.8.2007) ============================================================= 0 Überblick ----------- Die Installation des GeoShop Redirector für IIS (Internet

Mehr

Tutorial - www.root13.de

Tutorial - www.root13.de Tutorial - www.root13.de Netzwerk unter Linux einrichten (SuSE 7.0 oder höher) Inhaltsverzeichnis: - Netzwerk einrichten - Apache einrichten - einfaches FTP einrichten - GRUB einrichten Seite 1 Netzwerk

Mehr

JooLIMS. Manueller Import

JooLIMS. Manueller Import JooLIMS Manueller Import XAMPP 1.7.3 (nicht 1.7.4!, da Joomla 1.5 nicht unter 1.7.4 läuft) Joomla 1.5 installieren (nicht 1.6!) Download der Komponente Fabrik 2.1 (http://fabrikar.com/downloads/details/36/89)

Mehr

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER Inhalt 1 Einleitung... 1 2 Einrichtung der Aufgabe für die automatische Sicherung... 2 2.1 Die Aufgabenplanung... 2 2.2 Der erste Testlauf... 9 3 Problembehebung...

Mehr

Tutorial. In diesem Tutorial möchte ich die Möglichkeiten einer mehrspracheigen Web-Site erläutern.

Tutorial. In diesem Tutorial möchte ich die Möglichkeiten einer mehrspracheigen Web-Site erläutern. Tutorial In diesem Tutorial möchte ich die Möglichkeiten einer mehrspracheigen Web-Site erläutern. Zu Beginn müssen wir uns über die gewünschten Sprachen Gedanken machen. Zum einem, da eine professionelle

Mehr

Sun Convergence. Um sich anzumelden gehen Sie auf http://www.uni-erfurt.de/ und dann rechts oben auf IMAP Der Anmeldebildschirm sieht wie folgt aus:

Sun Convergence. Um sich anzumelden gehen Sie auf http://www.uni-erfurt.de/ und dann rechts oben auf IMAP Der Anmeldebildschirm sieht wie folgt aus: Sun Convergence 1. Was ist Sun Convergence? Es ist ein neuer Web Client, mit dem Sie E-Mails empfangen, lesen und schreiben können. Noch dazu haben Sie einen Kalender in dem Sie Ihre Termine/Aufgaben verwalten

Mehr

Adami CRM - Outlook Replikation User Dokumentation

Adami CRM - Outlook Replikation User Dokumentation Adami CRM - Outlook Replikation User Dokumentation Die neue Eigenschaft der Adami CRM Applikation macht den Information Austausch mit Microsoft Outlook auf vier Ebenen möglich: Kontakte, Aufgaben, Termine

Mehr

1. Zuerst muss der Artikel angelegt werden, damit später die Produktvarianten hinzugefügt werden können.

1. Zuerst muss der Artikel angelegt werden, damit später die Produktvarianten hinzugefügt werden können. Produktvarianten und Downloads erstellen Produktvarianten eignen sich um Artikel mit verschiedenen Optionen wie bspw. ein Herrenhemd in den Farben blau, grün und rot sowie in den Größen S, M und L zu verkaufen.

Mehr

Suche schlecht beschriftete Bilder mit Eigenen Abfragen

Suche schlecht beschriftete Bilder mit Eigenen Abfragen Suche schlecht beschriftete Bilder mit Eigenen Abfragen Ist die Bilderdatenbank über einen längeren Zeitraum in Benutzung, so steigt die Wahrscheinlichkeit für schlecht beschriftete Bilder 1. Insbesondere

Mehr

Virtuemart-Template installieren? So geht es! (Virtuemart 2.0.x)

Virtuemart-Template installieren? So geht es! (Virtuemart 2.0.x) Virtuemart-Template installieren? So geht es! (Virtuemart 2.0.x) Navigation Systemvoraussetzungen! 1 1. Vorbereitung der Installation! 2 2. Installation des Templates! 2 3. Konfiguration des Yagendoo VirtueMart-Templates!

Mehr

Konfiguration VLAN's. Konfiguration VLAN's IACBOX.COM. Version 2.0.1 Deutsch 01.07.2014

Konfiguration VLAN's. Konfiguration VLAN's IACBOX.COM. Version 2.0.1 Deutsch 01.07.2014 Konfiguration VLAN's Version 2.0.1 Deutsch 01.07.2014 In diesem HOWTO wird die Konfiguration der VLAN's für das Surf-LAN der IAC-BOX beschrieben. Konfiguration VLAN's TITEL Inhaltsverzeichnis Inhaltsverzeichnis...

Mehr

PC-Kaufmann Supportinformation - Proxy Konfiguration für Elster

PC-Kaufmann Supportinformation - Proxy Konfiguration für Elster Seite 1 von 12 Dieses Dokument dient für Sie als Hilfe für die Konfiguration verschiedener Proxy-Server, wenn Sie Ihre Daten per Elster an das Finanzamt über einen Proxy-Server senden möchten. 1. Was ist

Mehr

CGI Programmierung mit Ha. Markus Schwarz

CGI Programmierung mit Ha. Markus Schwarz CGI Programmierung mit Ha Markus Schwarz Überblick Was ist funktionale Programmierung Einführung in Haskell CGI-Programmierung mit Haskell Ein etwas größeres Beispiel Was ist funktionale Programm Ein Programm

Mehr

BusinessMail X.400 Webinterface Gruppenadministrator V2.6

BusinessMail X.400 Webinterface Gruppenadministrator V2.6 V2.6 Benutzerinformation (1) In der Vergangenheit konnten Sie X.400 Mailboxen, die Ihnen als Gruppenadministrator zugeordnet sind, nur mittels strukturierten Mitteilungen verwalten. Diese Mitteilungen

Mehr

How to do? Projekte - Zeiterfassung

How to do? Projekte - Zeiterfassung How to do? Projekte - Zeiterfassung Stand: Version 4.0.1, 18.03.2009 1. EINLEITUNG...3 2. PROJEKTE UND STAMMDATEN...4 2.1 Projekte... 4 2.2 Projektmitarbeiter... 5 2.3 Tätigkeiten... 6 2.4 Unterprojekte...

Mehr

Publizieren von Webs mit SmartFTP

Publizieren von Webs mit SmartFTP Publizieren von Webs mit SmartFTP Informationen FTP steht für File Transfer Protocol. Ein Protokoll ist eine Sprache, die es Computern ermöglicht, miteinander zu kommunizieren. FTP ist das Standardprotokoll

Mehr

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten In dem Virtuellen Seminarordner werden für die Teilnehmerinnen und Teilnehmer des Seminars alle für das Seminar wichtigen Informationen,

Mehr