MySQL, Java und einiges mehr
Client
Der Browser
Firefox
Chrome
Safari
Internet
Explorer…
Server
Apache
Tomcat
Jetty
Microsoft IIS
…
Internet
URL
http://localhost:8080/html/index.html
Die darzustellende Webseite
HTML
Jetty-Server
addContext
("/html",
"html/");
Resource
Handler
Liest
angefragte
Datei
index.html in
Verzeichnis
html/
URL
http://localhost:8080
/html/index.html
angefragte Datei
Ressource
Dateipfad
index.html
angefragte Datei
Ressource
Der ResourceHandler ist eine Klasse von
Jetty. Er liefert einfach Dateien zurück.
Klasse ImdbServer, Hauptprogramm main:
ContextHandler htmlHandler = handlers.addContext("/html", "html/");htmlHandler.setHandler(new ResourceHandler());
ContextHandler cssHandler = handlers.addContext("/css", "css/");cssHandler.setHandler(new ResourceHandler());
ContextHandler imgHandler = handlers.addContext("/images", "images/");imgHandler.setHandler(new ResourceHandler());
Jetty-Server
addContext
("/query/
actors", "");
ActorsQuery
Handler
Macht
Datenbank-
Abfrage und
Darstellung
der Webseite
URL
http://localhost:8080/
query/actors/?name
=watson%2C+emma
Fixfertiges HTML
Ressource
Parameter
name=watson%2C
+emma
Fixfertiges HTML
Ressource
Der ActorsQueryHandler ist eine unserer eigenen Klassen. Er sucht in der
Datenbank nach Schauspieler/innen und stellt die Treffer in einer Webseite dar.
ActorsQuery
Handler
1.
Datenbank-
Abfrage
Parameter
name=watson%2C
+emma
Gefundene
Datensätze
SQL AbfrageSELECT * FROM
actors WHERE name
like ? ORDER BY name
Abfrage-Parameter:
"%watson, emma%"
Der ActorsQueryHandler sucht als erstes in unserer MySQL-Datenbank nach
Schauspieler/innen, deren Namen ähnlich ist wie der URL-Parameter name.
MySQLMySQL
Datenbank
Server
Enthält die
Tabellen mit
den IMDB-
Daten
1. Die Datenbankabfrage aufbereiten in ActorsQueryHandler: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 ActorsQueryHandler: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 ActorsQueryHandler: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öswilligeEingaben 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
Handler
2.
Erstellung
von HTML
mit Treffern
der DB-
Abfrage
Datenresult_list={
{ name=Watson, Emma (I),
id=1935796 },
{ name=Watson, Emma (II),
id=1935797 }
}
Der ActorsQueryHandler erstellt anschliessend das HTML. Dazu verwendet er
das Framework Velocity. So können wir unsere Daten in HTML «mischen».
Velocity
HTML-
Template
plus Daten
ergibt HTML
für BrowserFixfertiges HTML
Ressource
Fixfertiges HTML
Ressource
2. Die Daten der Abfrage für Velocity aufbereiten in
ActorsQueryHandler:
Map<String, Object> hm =
new HashMap<String, Object>();
hm.put("name", resultSet.getString("name"));
hm.put("id", resultSet.getInt("actorid"));
return hm;
Maps sind Paare von (Name, Wert). Auf die Werte kann zugegriffen werden,
indem ein Name abgefragt wird. Die obige Map wird mit zwei Paaren befüllt,
die zum Beispiel die Werte haben könnten («name», «Streep, Meryl») und («id», «1235454»).
Datenresult_list={
{ name=Watson, Emma (I),
id=1935796 },
{ name=Watson, Emma (II),
id=1935797 }
}
Ein Velocity-Template erhält vom Java-Programm Daten. Diese können mit
einfach Befehlen ausgelesen und in das HTML eingebaut werden.
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>Fixfertiges HTML
Ressource
War das alles?
Es braucht noch mehr Code, um Jetty mit MySQL via JDBC und
mit Velocity zu integrieren.
Wenn eine einzelne SQL-Abfrage ausreicht, können wir die Klasse
AbstractSingleQueryHandler erweitern (ca. 200 Zeilen).
Diese Klasse stellt die ganze Infrastruktur zur Verfügung. So
können sich unsere eigenen Handler die wenigen Teile ergänzen,
die spezifisch für unsere SQL-Abfrage sind.
Die Klasse AbstractSingleQuery-
Handler 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
Cli
en
t
Jett
y-S
erv
er
Inte
rne
t
Act
ors
Qu
ery
Ha
nd
ler
My
SQ
LV
elo
city
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.html
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
ImdbServer: Handler für /html konfigurieren
ContextHandler htmlHandler =
handlers.addContext("/html", "html/");
htmlHandler.setHandler(new ResourceHandler());
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
localhost:8080/query/
actors/?name=watson
query/
actors
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\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: Handler für /query/actors konfigurieren
ContextHandler actorsQueryHandler =
handlers.addContext("/query/actors", "");
actorsQueryHandler.setHandler(new ActorsQueryHandler());
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
localhost:8080/query/
actors/?name=watson
query/
actorsprepareQuery(…)
SELECT * FROM
actors where …
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
localhost:8080/query/
actors/?name=watson
query/
actorsprepareQuery(…)
SELECT * FROM
actors where …
ActorsQueryHandler: Abfrage vorbereiten
public PreparedStatement prepareQuery(HttpServletRequest request, Connection connection) /*…*/ {
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;
} /*…*/
}
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
localhost:8080/query/
actors/?name=watson
query/
actorsprepareQuery(…)
SELECT * FROM
actors where …
mapResult(…)
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
localhost:8080/query/
actors/?name=watson
query/
actorsprepareQuery(…)
SELECT * FROM
actors where …
mapResult(…)ActorsQueryHandler: 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;
}
actorid name
123456789 Watson, Emma (II)
… …
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
localhost:8080/query/
actors/?name=watson
query/
actorsprepareQuery(…)
SELECT * FROM
actors where …
mapResult(…)
actors.vmgetVelocity
Template()
…
<h1>Gefundene
Schauspieler</h1>
<ul><li><a href="/query/
movies?actor_id=007">
Bond, James</li></ul>
…
ClientImdb-
Server
Resource-
Handler
ActorsQuery
-HandlerVelocity MySQL
localhost:8080/
html/index.html
/html/
index.htmlhtml\index.html
…
<form
action="/query/actors">
<input name="name" …/>
</form>
…
localhost:8080/query/
actors/?name=watson
query/
actorsprepareQuery(…)
SELECT * FROM
actors where …
mapResult(…)
actors.vmgetVelocity
Template()
…
<h1>Gefundene
Schauspieler</h1>
<ul><li><a href="/query/
movies?actor_id=007">
Bond, James</li></ul>
…
ActorsQueryHandler: 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;
}
actors.vm: HTML erstellen
<ul>
#foreach ($actor in $result_list)
<li><a href="/query/movies?actor_id=$actor.id">
$actor.name</a></li>
#end
</ul>
ActorsQuery
-HandlerVelocity MySQL
SELECT * FROM
actors where …
AbstractQuery-
Handler
Imdb-
Server
query/
actorshandle(…)
answerQuery(…)
prepareQuery(…)
mapResult(…)mapResultSet(…)
…