MySQL, Java und einiges mehr
Client Der Browser Firefox Chrome Safari Internet Explorer URL http://localhost:8080/html/index.html Internet Die darzustellende Webseite HTML Server Apache Tomcat Jetty Microsoft IIS
URL http://localhost:8080 /html/index.html angefragte Datei Ressource Jetty-Server addcontext ("/html", "html/"); Dateipfad index.html angefragte Datei Ressource Resource Liest angefragte Datei index.html in Verzeichnis html/ Der Resourceist eine Klasse von Jetty. Er liefert einfach Dateien zurück.
Klasse ImdbServer, Hauptprogramm main: Context html = handlers.addcontext("/html", "html/"); html.set(new Resource()); Context css = handlers.addcontext("/css", "css/"); css.set(new Resource()); Context img = handlers.addcontext("/images", "images/"); img.set(new Resource());
URL http://localhost:8080/ query/actors/?name =watson%2c+emma Jetty-Server Parameter name=watson%2c +emma ActorsQuery Fixfertiges HTML Ressource addcontext ("/query/ actors", ""); Fixfertiges HTML Ressource Macht Datenbank- Abfrage und Darstellung der Webseite Der ActorsQueryist eine unserer eigenen Klassen. Er sucht in der Datenbank nach Schauspieler/innen und stellt die Treffer in einer Webseite dar.
Parameter name=watson%2c +emma ActorsQuery SQL Abfrage SELECT * FROM actors WHERE name like? ORDER BY name Abfrage-Parameter: "%watson, emma%" MySQL Datenbank Server 1. Datenbank- Abfrage Gefundene Datensätze Enthält die Tabellen mit den IMDB- Daten Der ActorsQuerysucht als erstes in unserer MySQL-Datenbank nach Schauspieler/innen, deren Namen ähnlich ist wie der URL-Parameter name.
1. Die Datenbankabfrage aufbereiten in ActorsQuery: 1.1. Prüfen, ob ein Parameter name vorhanden ist if (request.getparameter("name")!= null) { PreparedStatement statement = connection.preparestatement( "SELECT * FROM actors "+ "WHERE name like? ORDER BY name" ); statement.setstring(1, "%"+request.getparameter("name")+"%«); return statement; }
1. Die Datenbankabfrage aufbereiten in ActorsQuery: 1.2. SQL-Abfrage vorbereiten, ohne Input-Daten if (request.getparameter("name")!= null) { PreparedStatement statement = connection.preparestatement( "SELECT * FROM actors "+ "WHERE name like? ORDER BY name" ); statement.setstring(1, "%"+request.getparameter("name")+"%«); return statement; }
1. Die Datenbankabfrage aufbereiten in ActorsQuery: 1.3. Input-Daten auf vorbereiteter Abfrage setzen if (request.getparameter("name")!= null) { PreparedStatement statement = connection.preparestatement( "SELECT * FROM actors "+ "WHERE name like? ORDER BY name" ); statement.setstring(1, "%"+request.getparameter("name")+"%«); return statement; }
Der naïve Ansatz einer SQL-Abfrage: Die Benutzereingabe (in rot dargestellt) direkt in der SQL-Abfrage verwenden: executequery("select * FROM actors WHERE name like '%watson, emma%' ORDER BY name"); Aber was passiert, wenn der Benutzer böswillige Eingaben macht? executequery("select * FROM actors WHERE name like '%';DROP TABLE actors;%' ORDER BY name"); Nach SELECT wird DROP TABLE ausgeführt. Uups. de.wikipedia.org/wiki/sql-injection
ActorsQuery Daten result_list={ { name=watson, Emma (I), id=1935796 }, Velocity Fixfertiges HTML Ressource 2. Erstellung von HTML mit Treffern der DB- Abfrage { name=watson, Emma (II), id=1935797 } } Fixfertiges HTML Ressource HTML- Template plus Daten ergibt HTML für Browser Der ActorsQueryerstellt anschliessend das HTML. Dazu verwendet er das Framework Velocity. So können wir unsere Daten in HTML «mischen».
2. Die Daten der Abfrage für Velocityaufbereitenin ActorsQuery: Map<String, Object> hm = new HashMap<String, Object>(); hm.put("name", resultset.getstring("name")); hm.put("id", resultset.getint("actorid")); return hm; Mapssind Paare von (Name, Wert). Auf die Werte kann zugegriffen werden, indem ein Name abgefragt wird. Die obige Mapwird mit zwei Paaren befüllt, die zum Beispiel die Werte haben könnten («name», «Streep, Meryl») und («id», «1235454»).
Daten result_list={ { name=watson, Emma (I), id=1935796 }, { name=watson, Emma (II), id=1935797 } } Fixfertiges HTML Ressource Auszug aus unserem Velocity-Template <h1>gefundene Schauspieler</h1> <ul> #foreach($actor in $result_list) <li><a href="/query/movies?actor_id=$actor.id"> $actor.name</a></li> #end </ul> Ein Velocity-Template erhält vom Java-Programm Daten. Diese können mit einfach Befehlen ausgelesen und in das HTML eingebaut werden.
War das alles? Es braucht noch mehr Code, um Jettymit MySQL via JDBC und mit Velocity zu integrieren. Wenn eine einzelne SQL-Abfrage ausreicht, können wir die Klasse AbstractSingleQueryerweitern (ca. 200 Zeilen). Diese Klasse stellt die ganze Infrastruktur zur Verfügung. So können sich unsere eigenen die wenigen Teile ergänzen, die spezifisch für unsere SQL-Abfrage sind.
Die Klasse AbstractSingleQuery- und ihre Unterklassen sind ein Beispiel des Design Patterns «Schablonenmethode». Die Methode handle verwendet Methoden wie preparequery. Diese Methoden sind nicht in der abstrakten Klasse, sondern erst in den Unterklassen definiert. Siehe auch de.wikipedia.org/ wiki/template_method
Client Internet Jetty-Server ActorsQuery Velocity MySQL
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form>
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> ImdbServer: für /html konfigurieren Contexthtml= handlers.addcontext("/html", "html/"); html.set(new Resource());
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> localhost:8080/query/ actors/?name=watson query/ actors
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> localhost:8080/query/ actors/?name=watson query/ actors index.html: Das Formular definiert Input Parameter <form action="/query/actors" method="get"> <input name="name" type="text" size="30" /> <input type="submit" value=" Absenden" /> </form> ImdbServer: für/query/actors konfigurieren ContextactorsQuery= handlers.addcontext("/query/actors", ""); actorsquery.set(new ActorsQuery());
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> localhost:8080/query/ actors/?name=watson query/ actors preparequery() SELECT * FROM actors where
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> localhost:8080/query/ actors/?name=watson query/ actors preparequery() SELECT * FROM actors where ActorsQuery: Abfrage vorbereiten public PreparedStatement preparequery(httpservletrequest request, Connection connection) /**/ { if (request.getparameter("name")!= null) { PreparedStatementstatement = connection.preparestatement("select * FROM actors WHERE name like? ORDER BY name"); statement.setstring(1, "%" + request.getparameter("name") + "%"); return statement; } /**/ }
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> localhost:8080/query/ actors/?name=watson query/ actors preparequery() SELECT * FROM actors where mapresult()
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> localhost:8080/query/ actors/?name=watson query/ actors preparequery() SELECT * FROM actors where ActorsQuery: Resultate aufbereiten public Map<String, Object> mapresult(resultset resultset) { Map<String, Object> hm = new HashMap<String, Object>(); hm.put("name", resultset.getstring("name")); hm.put("id", resultset.getint("actorid")); return hm; } mapresult() actorid name 123456789 Watson, Emma (II)
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> localhost:8080/query/ actors/?name=watson query/ actors preparequery() SELECT * FROM actors where mapresult() <h1>gefundene Schauspieler</h1> <ul><li><a href="/query/ movies?actor_id=007"> Bond, James</li></ul> getvelocity Template() actors.vm
Client Imdb- Server Resource- ActorsQuery - Velocity MySQL localhost:8080/ html/index.html /html/ index.html html\index.html <form action="/query/actors"> <input name="name" /> </form> localhost:8080/query/ actors/?name=watson query/ actors preparequery() SELECT * FROM actors where ActorsQuery: Resultate aufbereiten public Map<String, Object> mapresult(resultset resultset) { Map<String, Object> hm = new HashMap<String, Object>(); <h1>gefundene hm.put("name", resultset.getstring("name")); Schauspieler</h1> hm.put("id", resultset.getint("actorid")); <ul><li><a return hm; href="/query/ movies?actor_id=007"> } Bond, James</li></ul> actors.vm: mapresult() HTML erstellen <ul> #foreach($actor in $result_list) <li><a getvelocity href="/query/movies?actor_id=$actor.id"> actors.vm $actor.name</a></li> Template() #end </ul>
Imdb- Server AbstractQuery- ActorsQuery - Velocity MySQL query/ actors handle() preparequery() answerquery() SELECT * FROM actors where mapresultset() mapresult()