Filterprogrammierung: Beispiel

Werbung
Filterprogrammierung: Beispiel
package de.rainer_klute.servlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
* <p>This demo filter replaces a configurable hostname in a
* {@link ServletRequest} by a replacement string.</p>
*/
public class HostChangeFilter implements Filter
{
FilterConfig config;
String hostname;
String replacement;
public void init(FilterConfig config)
{
/* Could be used to fetch the ServletContext. */
this.config = config;
hostname = config.getInitParameter("Hostname");
replacement = config.getInitParameter("Replacement");
}
Web−Anwendungen mit Java
351
Filterprogrammierung: Beispiel
public void doFilter(ServletRequest req,
ServletResponse res,
FilterChain chain)
throws IOException, ServletException
{
ServletRequest wrapper =
new HttpServletRequestWrapper((HttpServletRequest) req)
{
public String getRemoteHost()
{
final String s =
getRequest().getRemoteHost();
if (s.equals(hostname))
return replacement;
else
return s;
}
};
chain.doFilter(wrapper, res);
}
public void destroy()
{}
Web−Anwendungen mit Java
}
352
Filterprogrammierung
•
Zentrale Methode:
FilterChain.doFilter(ServletRequest
request, ServletResponse response)
•
Ruft nächsten Filter in der Filterkette oder Ressource
•
Parameter: Wrapper oder Original−Request/Response
– ServletRequestWrapper, ServletResponseWrapper
– HttpServletRequestWrapper, HttpServletResponseWrapper
–
Implementieren ServletRequest, ServletResponse,
HttpServletRequest, HttpServletResponse
•
Tomcat 4.0.3 erwartet HttpServletRequest und
HttpServletResponse.
•
Methoden überschreiben, neue definieren
Web−Anwendungen mit Java
353
Filterkonfiguration
•
Konfiguration im Deployment descriptor
•
Definition:
<filter>
<filter−name>Filter 1</filter−name>
<filter−class>
de.rainer_klute.servlet.HostChangeFilter
</filter−class>
<init−param>
<param−name>Hostname</param−name>
<param−value>mark.rainer−klute.de</param−value>
</init−param>
<init−param>
<param−name>Replacement</param−name>
<param−value>foo.bar.de</param−value>
</init−param>
</filter>
Web−Anwendungen mit Java
354
Filterkonfiguration
•
Mapping:
<filter−mapping>
<filter−name>Filter 1</filter−name>
<servlet−name>Snoop</servlet−name>
</filter−mapping>
<filter−mapping>
<filter−name>Filter 2</filter−name>
<servlet−name>Snoop</servlet−name>
</filter−mapping>
•
Aufrufreihenfolge entspricht der Reihenfolge im
Deployment descriptor
–
Im Beispiel: Filter 1 → Filter 2 → Snoop
Web−Anwendungen mit Java
355
Anwendungsereignisse
•
Ereignisse, die eine Web−Anwendung als ganzes
betreffen
–
Servlet−Kontext
–
Sessions
–
potentiell alle Servlets der Anwendung
Web−Anwendungen mit Java
356
Anwendungsereignisse: Interfaces
•
Listener−Interfaces
– javax.servlet.ServletContextListener
Erzeugen und Beenden des Servlet−Kontexts
– javax.servlet.ServletContextAttributeListener
–
Änderungen an ServletContext−Attributen
– javax.servlet.http.HttpSessionActivationListener
–
Aktivieren und Deaktivieren von Sessions
– javax.servlet.http.HttpSessionListener
–
Erzeugen und Beenden von Sessions
– javax.servlet.http.HttpSessionAttributeListener
–
–
•
Änderungen an Session−Attributen
Servlet−Container stellt den Implementierungen
Event−Objekte zu.
Web−Anwendungen mit Java
357
Anwendungsereignisse: Beispiel
package de.rainer_klute.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
public class SessionListener implements HttpSessionListener
{
public void sessionCreated(HttpSessionEvent e)
{
// ...
}
public void sessionDestroyed(HttpSessionEvent e)
{
// ...
}
}
Web−Anwendungen mit Java
358
Listener−Klassen registrieren
•
Registrierung im Deployment Descriptor nötig
•
Beispiel:
<listener>
<listener−class>
de.rainer_klute.servlet.SessionListener
</listener−class>
</listener>
<listener>
<listener−class>
de.rainer_klute.servlet.FooListener
</listener−class>
</listener>
Web−Anwendungen mit Java
359
JDBC
JDBC
Web−Anwendungen mit Java
360
JDBC
•
Standard−API für den Java−Zugriff auf relationale
Datenbanksysteme
–
Oracle, DB2, Informix, Adabas D
–
PostgreSQL, MySQL
–
usw.
Web−Anwendungen mit Java
361
Erwartungen
•
•
Was Sie nicht erwarten können
–
Einführung in relationale Datenbanksysteme
(Relationenalgebra, Relationenkalkül)
–
Anfragesprache SQL
Was Sie erwarten können
–
Einführung in JDBC
–
Beispiele mit Datenbanksystem PostgreSQL
Web−Anwendungen mit Java
362
Vertiefung
•
Dokumentation zu PostgreSQL lesen
–
Beschreibt nicht nur PostgreSQL selbst, sondern auch...
–
Relationale Datenbanksysteme
–
Anfragesprache SQL
–
Literaturverweise
Web−Anwendungen mit Java
363
DBMS−Typen
•
Database Management System
–
•
•
Relationales DBMS (RDBMS)
–
Speichert Daten in Tabellen (Relationen).
–
Abfragesprache SQL
Objektorientiertes DBMS (OODBMS)
–
•
Speichert Objekte unmittelbar.
Objektrelationales DBMS (ORDBMS)
–
•
Oberbegriff für Datenbanksysteme
Bietet sowohl Objekt− als auch Relationensicht.
JDBC unterstützt (objekt−)relationale
Datenbanksysteme.
Web−Anwendungen mit Java
364
Datenbank
•
•
•
Tabellen (Relationen)
–
Daten
–
Beispiele: Artikel eines Katalogs, Bestellungen
Views
–
Sichten auf Daten
–
Beispiel: Artikel sortiert nach Umsatz
Indizes
–
•
»Vorsortierungen« von Tabellen
Stored Procedures
–
In der Datenbank gespeicherte Programme
Web−Anwendungen mit Java
365
Tabellen
–
Darstellung von Relationen (siehe Fachliteratur)
–
Beispiele:
PostgreSQL
•
»The most advanced open source database
management system«
•
Läuft unter Unix (diverse Varianten, u.a. Linux) und
Windows (mit Cygwin)
•
Fast vollständige Unterstützung des Standards SQL92
–
•
Transaktionen (im Unterschied zu MySQL)
Zusätzliche Features
–
ORDBMS, max. Zellengröße 1 GB, Tupelgröße
unbegrenzt u.v.a.m.
•
Geringer Hauptspeicherbedarf
•
Sehr gute Dokumentation
Web−Anwendungen mit Java
367
PostgreSQL als Client−/Server−System
•
Client−/Server−System
•
Prozeß postmaster
–
Läuft permanent auf Server−Maschine.
–
Nimmt Verbindungsaufbauwünsche über das Netz
entgegen.
•
Datenbank−Client baut Verbindung zum Postmaster
auf.
•
Postmaster startet Datenbank−Server−Prozeß
postgres für den Client.
Web−Anwendungen mit Java
368
PostgreSQL als Client−/Server−System
•
Sitzung
–
Client: schickt SQL−Anweisung zum Server.
–
Server: schickt Ergebnis zum Client.
–
usw.
•
Client beendet Verbindung.
•
Server−Prozeß terminiert.
Web−Anwendungen mit Java
369
SQL−Monitor »psql«
•
Zu PostgreSQL gehörender Datenbank−Client
•
Interaktives Arbeiten mit Datenbanken
•
–
SQL−Anweisungen.
–
Datenbanken anlegen, Tabellen definieren, Daten
ändern, Datenbankanfragen absetzen usw. usw.
Baut Verbindung zum Datenbank−Server auf
(genauer: zum Postmaster−Prozeß).
–
Beispiel: psql −h carne01 eshop
–
Baut Verbindung zum Postmaster auf Rechner carne01
auf und öffnet Datenbank eshop.
–
Weitere Informationen: Kommando »man psql«
Web−Anwendungen mit Java
370
SQL−Monitor »psql«
•
•
SQL−Anweisungen an Datenbank−Server
–
SELECT * FROM artikel;
–
SQL−Anweisungen mit »;« beenden
–
Hilfe zu SQL−Anweisungen
–
Kommando »man create_table« usw.
–
psql−Anweisung »\h create table«
Anweisungen an psql
–
Beispiel: \H schaltet HTML−Modus ein oder aus
–
Beispiel: \i datei.sql
–
–
SQl−Anweisungen aus datei.sql lesen und ausführen
Hilfe zu allen psql−Anweisungen mit »\?«
Web−Anwendungen mit Java
371
E−Shop−Datenbank einrichten
•
•
SQL−Monitor psql starten
–
psql −h carne01 template1
–
Siehe unten: PostgreSQL−Umgebung
–
Öffnet Datenbank template1 (in PostgreSQL immer
vorhanden)
Datenbank eshop erzeugen
– CREATE DATABASE eshop;
–
Statt eshop sollte jeder Benutzer einen anderen
Datenbanknamen verwenden.
–
•
Beispiel: CREATE DATABASE eshop_pkjf123;
Zu neuer Datenbank eshop wechseln
– \c eshop
Web−Anwendungen mit Java
372
E−Shop−Datenbank einrichten
•
Tabelle artikel definieren
– CREATE TABLE artikel
(id INTEGER PRIMARY KEY,
bezeichnung CHARACTER VARYING NOT NULL UNIQUE,
text CHARACTER VARYING,
preis DECIMAL(10,2) NOT NULL CHECK (preis > 0));
–
PRIMARY KEY: Wert identifiziert Artikel eindeutig.
–
CHARACTER VARYING: Textfeld variabler Länge
–
NOT NULL: Feld darf nicht leer sein.
–
UNIQUE: Feldwert ist für gesamte Tabelle eindeutig.
–
DECIMAL(10,2): Dezimalwert mit 10 Stellen Genauigkeit
und 2 Nachkommastellen
–
CHECK (preis > 0): Wert von preis muß größer 0 sein.
Web−Anwendungen mit Java
373
E−Shop−Datenbank einrichten
•
Tabelle artikel mit Daten füllen
– INSERT INTO artikel (id, bezeichnung, preis)
VALUES (4711, ’Duftwasser’, 15.95);
INSERT INTO artikel (id, bezeichnung, preis)
VALUES (0815, ’ISDN−Telefon’, 123.45);
INSERT INTO artikel (id, bezeichnung, preis)
VALUES (1234, ’Notebook’, 2500);
INSERT INTO artikel (id, bezeichnung, preis)
VALUES (538, ’Lolly’, 0.05);
•
DBMS prüft Daten auf Gültigkeit.
– INSERT INTO artikel (id, bezeichnung, preis)
VALUES (0815, ’Lolly’, 0);
–
ExecAppend: rejected due to CHECK constraint
artikel_preis
Web−Anwendungen mit Java
374
E−Shop−Datenbank einrichten
•
Tabelle kunden definieren und mit Daten füllen
– CREATE TABLE kunden
(id INTEGER PRIMARY KEY,
konto INTEGER NOT NULL,
blz INTEGER NOT NULL,
name CHARACTER VARYING);
INSERT INTO kunden VALUES
(10017, 123456700, 38070724, ’Karl Käufer’);
INSERT INTO kunden VALUES
(12659, 234567890, 44050199, ’Karin Kunde’);
–
Weitere Kundendaten wie Rechnungsadresse,
Lieferanschrift, Bonität, Rabattklasse usw. werden hier
nicht unterstützt.
Web−Anwendungen mit Java
375
E−Shop−Datenbank einrichten
•
Tabelle bestellungen definieren
– CREATE TABLE bestellungen
(artikel INTEGER REFERENCES artikel (id),
kunde INTEGER REFERENCES kunden (id),
anzahl INTEGER NOT NULL);
•
•
REFERENCES artikel (id): Feld ist Fremdschlüssel.
–
Referenziert Schlüssel id in Tabelle artikel.
–
Referenzierte Zeilen können nicht gelöscht werden
(Voreinstellung).
Tabelle mit Daten füllen
– INSERT INTO bestellungen VALUES ( 815, 10017, 1);
INSERT INTO bestellungen VALUES (1234, 10017, 1);
INSERT INTO bestellungen VALUES ( 815, 12659, 2);
Web−Anwendungen mit Java
376
Referentielle Integrität
•
Versuch scheitert, eine referenzierte Zeile zu löschen.
•
DELETE FROM artikel WHERE id = 0815;
•
ERROR: <unnamed> referential integrity violation −
key in artikel still referenced from bestellungen
Web−Anwendungen mit Java
377
Daten abfragen
•
Tabelle anzeigen: alle Artikel auflisten
–
SELECT * FROM artikel;
–
id | bezeichnung | text | preis
−−−−−−+−−−−−−−−−−−−−−+−−−−−−+−−−−−−−−−
4711 | Duftwasser
|
|
15.95
815 | ISDN−Telefon |
| 123.45
1234 | Notebook
|
| 2500.00
538 | Lolly
|
|
0.05
(4 rows)
•
SELECT−Anweisung stellt Datenbank−Anfrage
(»Query«).
•
Stern (*) selektiert alle Spalten der Tabelle.
Web−Anwendungen mit Java
378
Daten abfragen
•
Tabellen kombinieren
• SELECT * FROM artikel, bestellungen;
•
•
Kombiniert jede Zeile der ersten Tabelle mit jeder Zeile
der zweiten Tabelle (kartesisches Produkt).
Daten abfragen
•
Ergebnisrelation auf interessante Tupel einschränken
(Selektion)
•
Bestellte Artikel
• SELECT * FROM artikel, bestellungen
WHERE artikel.id = bestellungen.artikel;
•
Web−Anwendungen mit Java
380
Daten abfragen
•
Ergebnisspalten auswählen (Projektion)
•
Bezeichnung der Ergebnisspalten wählen
•
Spalteninhalt dynamisch berechnen
• SELECT name AS "Name", bezeichnung AS "Artikel",
anzahl AS "Stückzahl", preis AS "Einzelpreis",
(anzahl * preis) AS "Gesamtpreis"
FROM bestellungen, artikel, kunden
WHERE artikel.id = bestellungen.artikel
AND kunden.id = bestellungen.kunde;
•
PostgreSQL auf den Übungsrechnern
•
PostgreSQL 7.2 installiert in
/home/pkjf/pkjf000/postgresql
•
Unterverzeichnisse:
–
bin: Programme, z.B. psql, postmaster
–
lib: Shared libraries, JDBC−Implementierung
–
doc/html: Dokumentation
–
man: Manualseiten
Web−Anwendungen mit Java
382
PostgreSQL auf den Übungsrechnern
•
Umgebung(svariablen) für PostgreSQL einrichten
•
Kommandos für Shell sh bzw. bash:
–
Zum automatischen Ausführen beim Einloggen in Datei
~/.bashrc aufnehmen!
• # Installationsverzeichnis
PGROOT="/home/pkjf/pkjf000/postgresql"
# Suchpfad für Programme erweitern:
PATH="${PGROOT}/bin:${PATH}"
# Suchpfad für Shared libraries setzen
# (bei Bedarf erweitern):
LD_LIBRARY_PATH="${PGROOT}/lib"
# Suchpfad für Manualseiten erweitern:
MANPATH="${PGROOT}/man:${MANPATH}"
Web−Anwendungen mit Java
383
PostgreSQL auf den Übungsrechnern
# Suchpfad für Java−Klassen erweitern:
CLASSPATH="${CLASSPATH}:${PGROOT}/lib/postgresql.jar"
# Port des PostgreSQL−Servers:
PGPORT="5432"
# Umgebungsvariablen exportieren:
export PATH
export LD_LIBRARY_PATH
export CLASSPATH
export PGPORT
•
Shells csh und tcsh:
– set PGROOT="/home/pkjf/pkjf000/postgresql"
setenv PATH "${PGROOT}/bin:${PATH}"
# usw.
–
Zum automatischen Ausführen beim Einloggen in
Datei ~/.cshrc aufnehmen!
Web−Anwendungen mit Java
384
PostgreSQL auf den Übungsrechnern
•
Datenbank−Server läuft auf carne01.
•
Start des Datenbank−Servers erfolgt manuell unter der
Benutzerkennung pkjf000:
– postmaster −D /home/pkjf/pkjf000/postgresql/data \
−i −p 5703 \
>/tmp/pgsql.log 2>&1 &
•
Voreinstellung: maximal 32 gleichzeitige Verbindungen
•
Benutzer pjkf000 bis pkjf099 sind eingerichtet.
Web−Anwendungen mit Java
385
Eigene PostgreSQL−Konfiguration
•
PostgreSQL erlaubt den Betrieb eigener Datenbank−
Cluster
–
•
•
Wichtig, falls Postmaster auf carne01 einmal nicht laufen
sollte
Verzeichnis für Datenbank−Cluster einrichten und mit
initdb initialisieren
–
mkdir /tmp/mycluster
initdb −D /tmp/mycluster
–
Leerer Cluster belegt ca. 20 MB Plattenplatz.
Sicherheit des Clusters in Datei pg_hba.conf
konfigurieren
–
Details siehe Kommentare in dieser Datei
Web−Anwendungen mit Java
386
Eigene PostgreSQL−Konfiguration
•
•
Postmaster starten
–
postmaster −i −D /tmp/mycluster −p 5555
–
TCP/IP−Zugriff mit −i erlauben
–
Eigenes Cluster−Verzeichnis mit −D angeben
–
Eigenen Port mit −p angeben
Weitere Informationen:
–
PostgreSQL−Dokumentation
–
»man postmaster«
–
»man psql«
Web−Anwendungen mit Java
387
Sicherheit auf den Übungsrechnern
•
Die PostgreSQL−Konfiguration auf den
Übungsrechnern bietet keine hohe Sicherheit.
•
Kein Paßwortschutz
•
–
Jeder Benutzer kann sich mit jeder Datenbank verbinden.
–
Paßwort bei JDBC−Verbindungen wird ignoriert.
Tabellen gehören dem Benutzer, der sie angelegt hat.
–
Zugriffsrechte mit GRANT weitergeben
–
–
GRANT select ON mytable TO pkjf123;
Zugriffsrechte mit REVOKE entziehen
–
REVOKE ALL ON mytable FROM pkjf123;
Web−Anwendungen mit Java
388
Sicherheit auf den Übungsrechnern
•
Netzzugriff nur für Übungsrechner carne01 bis
carne12 erlaubt
•
Das heißt: kein Zugriff auf die Datenbanken von außen
•
Entspricht dem üblichen Einsatzszenario der
Dreischichtenarchitektur
–
Browser → Applikationsserver → DBMS
Web−Anwendungen mit Java
389
Dreischichtenarchitektur
»Three tier architecture«
Browser
Firewall (erlaubt nur HTTP und
HTTPS)
•
Web−Anwendungen mit Java
Applikation
s−Server
DBMS
390
Wichtige PostgreSQL−Besonderheiten
•
VACUUM [FULL]
–
•
VACUUM ANALYZE
–
•
Aktualisiert Datenbankstatistiken für Optimizer
EXPLAIN SELECT ...
–
•
Gewinnt Platz gelöschter Datensätze zurück
Ausführungsplan einer Anfrage zeigen
Programme
–
initdb initialisiert Datenbank−Cluster
–
pg_dump extrahiert eine komplette Datenbank als SQL−
Skript oder in weiteren Formaten.
–
pg_restore restauriert eine Datenbank oder Teile davon.
Web−Anwendungen mit Java
392
JDBC−Beispiel: Daten abfragen
package de.rainer_klute.jdbc;
import java.io.*;
import java.sql.*;
/**
* <p>E−Shop−Bestellungen als HTML−Tabelle.</p>
*/
public class Bestellungen
{
public static void main(String argv[])
throws ClassNotFoundException, SQLException
{
/* JDBC−Treiber laden */
Class.forName("org.postgresql.Driver");
/* JDBC−URL der Datenbank spezifizieren */
String url = "jdbc:postgresql://mark:5712/eshop";
Web−Anwendungen mit Java
393
JDBC−Beispiel: Daten abfragen
/* Datenbankverbindung aufbauen */
Connection con = DriverManager.getConnection
(url, argv[0], argv[1]);
/* Statement erzeugen */
Statement stmt = con.createStatement();
/* SQL−Abfrage ausführen −
* Ergebnis ist ein ResultSet */
String query =
"SELECT name AS \"Name\"," +
"
bezeichnung AS \"Artikel\"," +
"
anzahl AS \"Stückzahl\"," +
"
preis AS \"Einzelpreis\"," +
"
(anzahl * preis) AS" +
"
\"Gesamtpreis\"" +
" FROM bestellungen, artikel, kunden" +
" WHERE artikel.id = bestellungen.artikel" +
"
AND kunden.id = bestellungen.kunde";
ResultSet rs = stmt.executeQuery(query);
Web−Anwendungen mit Java
394
JDBC−Beispiel: Daten abfragen
/* Ergebnisrelation als HTML−Tabelle ausgeben */
PrintStream p = System.out;
p.println("<!DOCTYPE HTML PUBLIC " +
"\"−//W3C//DTD HTML 4.0//EN//\">");
p.println("<TITLE>SQL−Abfrage mit JDBC</TITLE>");
p.println("<H1>SQL−Abfrage mit JDBC</H1>");
p.println("<H2>Abfrage:</H2>");
p.println("<P>" + query + "</P>");
p.println("<H2>Ergebnistabelle:</H2>");
p.println("<TABLE BORDER=’1’>");
/* Anzahl der Spalten ermitteln */
ResultSetMetaData rsmd = rs.getMetaData();
int columns = rsmd.getColumnCount();
Web−Anwendungen mit Java
395
JDBC−Beispiel: Daten abfragen
/* Spaltennamen aus Metadaten ermitteln und in
* erste Tabellenzeile ausgeben */
p.println("<TR>");
for (int i = 1; i <= columns; i++)
p.println("<TH><P>" + rsmd.getColumnName(i) +
"</P></TH>");
p.println("</TR>");
/* Ergebniszeilen ausgeben */
while (rs.next())
{
p.println("<TR>");
for (int i = 1; i <= columns; i++)
{
/* Zelleninhalt ausgeben */
Object o = rs.getObject(i);
p.print("<TD><P>" + o + "</P></TD>");
}
p.println("</TR>");
}
Web−Anwendungen mit Java
396
JDBC−Beispiel: Daten abfragen
p.println("</TABLE>");
/* ResultSet schließen */
rs.close();
/* Statement−Objekt schließen */
stmt.close();
}
/* Datenbankverbindung schließen */
con.close();
}
Web−Anwendungen mit Java
397
JDBC−Konzepte
•
Pakete
–
java.sql enthält JDBC−Basisfunktionalität.
–
–
javax.sql enthält zusätzliche Funktionalität für Row sets
und Connection pooling.
–
•
Wird hier behandelt.
In J2EE (Java 2 Enterprise Edition) enthalten
JDBC−Treiber kapseln die DBMS−spezifischen
Mechanismen.
–
Aufbau der Verbindung zur Datenbank
–
Datenaustausch
–
Unterschiede in SQL−Dialekten
Web−Anwendungen mit Java
398
JDBC−Treiber laden
•
•
Class.forName("org.postgresql.Driver");
–
Lädt die Klasse org.postgresql.Driver.
–
JDBC−Treiber registriert sich beim DriverManager.
Alternative: JDBC−Treiber beim Programmstart als
Property jdbc.drivers spezifizieren
java \
−Djdbc.drivers=sun.jdbc.odbc.JdbcOdbcDriver:org.postgresql.Driver \
de.rainer_klute.jdbc.Bestellungen
•
Vorteile beim Verwenden von jdbc.drivers:
–
JDBC−Treiber nicht fest vorgeben
–
Nutzung eines anderen JDBC−Treibers erfordert im
Idealfall keine Änderung des Quellcodes.
Web−Anwendungen mit Java
399
JDBC−Treiber
•
JDBC selbst besteht im wesentlichen aus Interfaces.
–
•
Connection, Statement, ResultSet usw.
Implementierung der Interfaces durch den JDBC−
Treiber
–
org.postgresql.jdbc2.Connection,
org.postgresql.jdbc2.Statement,
org.postgresql.jdbc2.ResultSet usw.
•
JDBC−Treiber stammen in der Regel vom DBMS−
Anbieter.
•
Der Entwickler programmiert nur mit den Interfaces,
nicht mit den Treiberklassen.
Web−Anwendungen mit Java
400
Herunterladen