Ausarbeitung - Institut für Wirtschaftsinformatik der WWU Münster ...
Ausarbeitung - Institut für Wirtschaftsinformatik der WWU Münster ...
Ausarbeitung - Institut für Wirtschaftsinformatik der WWU Münster ...
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Themensteller: Prof. Dr. Herbert Kuchen<br />
Betreuer: Christian Hermanns<br />
<strong>Institut</strong> <strong>für</strong> <strong>Wirtschaftsinformatik</strong><br />
Praktische Informatik in <strong>der</strong> Wirtschaft<br />
Westfälische Wilhelms-Universität <strong>Münster</strong><br />
<strong>Ausarbeitung</strong><br />
Application Frameworks<br />
im Rahmen des Seminars Software Engineering<br />
Birgit Hecker
Inhaltsverzeichnis<br />
1 Aufbau und Ziel <strong>der</strong> Arbeit ........................................................................................ 1<br />
2 Grundlagen ................................................................................................................ 2<br />
2.1 Application Framework ..................................................................................... 2<br />
2.2 Dependency Injection ......................................................................................... 3<br />
2.3 Aspektorientierte Programmierung .................................................................... 4<br />
3 Spring Framework ..................................................................................................... 5<br />
3.1 Beispielanwendung Bibliothek .......................................................................... 5<br />
3.2 Spring-Container ................................................................................................ 6<br />
3.3 Spring-Bean........................................................................................................ 7<br />
3.4 Dependency Injection ......................................................................................... 7<br />
3.5 Aspektorientierte Programmierung .................................................................. 10<br />
3.6 Model View Controller .................................................................................... 11<br />
3.7 Datenbankzugriff .............................................................................................. 14<br />
3.8 Sicherheit .......................................................................................................... 17<br />
4 Vergleich Spring und Java EE ................................................................................. 21<br />
5 Zusammenfassung und Ausblick ............................................................................. 22<br />
Anhang A: Klassendiagramm ......................................................................................... 23<br />
Anhang B: Quellcode ...................................................................................................... 24<br />
Literaturverzeichnis ........................................................................................................ 60<br />
II
Kapitel 1: Aufbau und Ziel <strong>der</strong> Arbeit<br />
1 Aufbau und Ziel <strong>der</strong> Arbeit<br />
Die Nachfrage nach Geschäftsanwendungen im Java-Bereich steigt. Dabei werden die<br />
Anwendungen immer komplexer. Folgen davon sind, dass eine einfache Verwendung<br />
von Java ohne Bibliotheken nicht möglich ist. Eine Bibliothek stellt Funktionen zu<br />
bestimmten Aufgabenstellungen bereit, in Form einer Sammlung von Klassen dieses<br />
Aufgabengebietes. Die Einarbeitung in eine solche Anwendung ist <strong>für</strong> den Entwickler<br />
sehr zeitintensiv. Einen Ausweg bieten Frameworks. Sie stellen eine Schicht über<br />
verschiedene Bibliotheken dar und vereinfachen somit die Softwareentwicklung [Wo07,<br />
Kap. 1.1]. Frameworks enthalten bereits Funktionalität, die in die eigentliche<br />
Implementierung eingebunden werden kann. Im Gegensatz zur Bibliothek aus <strong>der</strong> <strong>der</strong><br />
Programmierer bei Bedarf einzelne Klassen verwendet, gibt das Framework die Struktur<br />
<strong>für</strong> die Anwendung vor [GHJV04]. Der Programmierer erstellt und registriert Klassen<br />
auf Grundlage <strong>der</strong> vorgegebenen Schnittstellen. So wird die konkrete Implementierung<br />
durch das Framework gesteuert und benutzt. Es wird zwischen programmiersprachen-<br />
und zweckabhängigen Frameworks differenziert. Beispiele <strong>für</strong> Frameworks sind<br />
Java EE, .NET und Spring.<br />
Für das Java-Framework Spring bildete das Buch „Expert One-On-One J2EE Design<br />
und Development“ die Grundlage <strong>für</strong> das OpenSource-Projekt Spring. Durch die große<br />
Resonanz und Beteiligung an dem OpenSource-Projekt wurde Spring stetig<br />
weiterentwickelt.<br />
Ziel dieser Arbeit ist die detaillierte Darstellung <strong>der</strong> Softwareentwicklung mit dem<br />
Spring Framework. Dazu wird zunächst im 2. Kapitel <strong>der</strong> Begriff Framework näher<br />
beleuchtet. Außerdem werden die Programmiertechniken Dependency Injection und<br />
Aspektorientierte Programmierung beschrieben. Diese sind von großer Bedeutung <strong>für</strong><br />
das Spring Framework, welches in Kapitel 3 vorgestellt wird. Anhand von Beispielen<br />
aus <strong>der</strong> Entwicklung einer Bibliotheksanwendung wird die Softwareentwicklung mit<br />
diesem Framework erläutert. Kapitel 4 vergleicht schließlich Spring mit dem Java EE<br />
Framework. Abschließend erfolgen in Kapitel 5 eine Zusammenfassung und ein<br />
Ausblick.<br />
1
Kapitel 2: Grundlagen<br />
2 Grundlagen<br />
2.1 Application Framework<br />
In <strong>der</strong> Literatur finden sich verschiedene Definitionen <strong>für</strong> den Begriff Framework. Eine<br />
Definition, die häufig verwendet wird, stammt von [GHJV04]:<br />
„Ein Framework ist eine Menge von kooperierenden Klassen, die einen<br />
wie<strong>der</strong>verwendbaren Entwurf <strong>für</strong> einen bestimmten Anwendungskontext<br />
vorgeben. Das Framework bestimmt dabei die Architektur <strong>der</strong> Applikation.“<br />
Ein Framework ist somit eine wie<strong>der</strong>verwendbare Umgebung <strong>für</strong> die<br />
Softwareentwicklung. Für die objektorientierte Programmierung bedeutet dies, dass ein<br />
bestimmtes Paket an Klassen zur Verfügung gestellt wird, um aus diesem<br />
Softwareanwendungen erstellen zu können. Das Framework gibt durch die verfügbaren<br />
Schnittstellen und abstrakte Klassen die grobe Anwendungsstruktur und den<br />
Kontrollfluss <strong>der</strong> Anwendung vor. Mit Hilfe dieser zur Verfügung gestellten Funktionen<br />
erstellt <strong>der</strong> Entwickler eine konkrete Anwendung. Da diese Funktionen nicht ohne<br />
Berücksichtigung eines konkreten Anwendungskontextes erstellt werden können, sind<br />
Frameworks meist domänenspezifisch. Um die Anwendungsarchitektur vorzugeben,<br />
findet eine Umkehrung des Kontrollflusses (Inversion of Control) statt. Dabei werden in<br />
<strong>der</strong> Erstellung einer Anwendung auf Basis eines Frameworks Klassen und Methoden<br />
aus dem Framework aufgerufen. Dieses Prinzip wird auch als Hollywood-Prinzip<br />
(„Don’t call us, we call you“) bezeichnet [GHJV04].<br />
Ein Vorteil von Frameworks ist, dass sie bereits fertig entworfene und implementierte<br />
Softwarestrukturen bereitstellen, die wie<strong>der</strong> verwendet werden können. So muss <strong>der</strong><br />
Entwickler z. B. Grundfunktionalitäten wie das Überprüfen von Benutzerrechten, die in<br />
je<strong>der</strong> Anwendung vorkommen, nicht jedesmal neu implementieren. Durch die<br />
Kapselung von Implementierungsdetails wird die Anwendung modularer und die<br />
Softwarequalität steigt. Ein weiterer Vorteil von Frameworks ist die Erweiterbarkeit.<br />
Das Framework stellt dem Entwickler feste Punkte bereit an denen er intervenieren und<br />
das Framework konfigurieren und erweitern kann [FaSc97].<br />
Bei Frameworks differenzieren [FaSc97] zwischen Black- und White-Box-Frameworks.<br />
Die Grundlage <strong>für</strong> White-Box-Frameworks bilden Vererbung und dynamisches Binden,<br />
um Erweiterbarkeit zu gewährleisten. Die bereitgestellte Funktionalität wird<br />
2
Kapitel 2: Grundlagen<br />
wie<strong>der</strong>verwendet und kann durch Vererbung <strong>der</strong> bereitgestellten Klassen o<strong>der</strong> durch<br />
Überschreiben von vordefinierten Methoden ergänzt werden. In Black-Box-<br />
Frameworks wird die Erweiterbarkeit durch Komposition in das Framework integriert,<br />
d. h. die zur Verfügung stehenden Komponenten müssen vom Entwickler konfiguriert<br />
und zusammengesetzt werden. Bei Black-Box-Framework kennt <strong>der</strong> Benutzer daher nur<br />
die Schnittstelle und nicht die innere Struktur. Im Gegensatz dazu muss <strong>der</strong> Benutzer<br />
des White-Box-Frameworks die innere Struktur des Frameworks genau kennen. Daher<br />
sind Black-Box-Framework leichter zu verwenden und erweitern als White-Box-<br />
Frameworks. Allerdings sind Black-Box-Frameworks schwieriger zu entwickeln, da<br />
hier Schnittstellen zur Verfügung gestellt werden müssen, die eine Reihe von<br />
potentiellen Anwendungsfällen abdecken [FaSc97].<br />
In dieser <strong>Ausarbeitung</strong> wird das Application Framework Spring vorgestellt. Dabei<br />
handelt es sich um eine Mischform aus Black- und White-Box-Framework, da es<br />
Vererbung und dynamisches Binden verwendet ebenso wie Komposition. Dazu werden<br />
die Programmiertechniken Dependency Injection und Aspektorientierte<br />
Programmierung benutzen.<br />
2.2 Dependency Injection<br />
Dependency Injection ist eine Programmiertechnik, die in <strong>der</strong> objektorientierten<br />
Programmierung eingesetzt wird, um die Abhängigkeiten zwischen Objekten zu<br />
minimieren. Solche Abhängigkeiten entstehen z. B. durch den Verweis eines Objekt auf<br />
ein an<strong>der</strong>es Objekt. Ohne die Anwendung von Dependency Injection ist jedes Objekt<br />
selbst <strong>für</strong> die Erzeugung und Verwaltung seiner Abhängigkeiten zuständig. Für die<br />
Erzeugung an<strong>der</strong>er Objekte muss das abhängige Objekt Getter- und Setter-Methoden<br />
<strong>für</strong> das zu erstellende Objekt zur Verfügung stellen. Bei Dependency Injection werden<br />
diese Abhängigkeiten verringert, indem die Verantwortung <strong>für</strong> die abhänigen Objekten<br />
an das Framework übergeben wird. Die Abhängigkeiten werden zur Laufzeit den<br />
Objekten injiziert. Dies wird meistens deklarativ in XML-Dateien konfiguriert.<br />
Außerdem lassen sich Klassen so einfacher testen, da ihre abhängigen Objekte durch<br />
Mock-Objekte ersetzt werden können. Mock-Objekte dienen als Platzhalter <strong>für</strong> echte<br />
Objekte innerhalb von Tests [Wo07].<br />
Es gibt drei Varianten von Dependency Injection: Interface-Injection, Setter-Injection<br />
und Constructor-Injection. Hierbei entsteht die größte Abhängigkeit bei Interface-<br />
3
Kapitel 2: Grundlagen<br />
Injection. Bei Interface-Injection muss eine Klasse alle Interfaces und <strong>der</strong>en<br />
vorgegebene Methoden implementieren damit alle abhängigen Objekte zugeordnet<br />
werden können. Es muss also <strong>für</strong> jede Art <strong>der</strong> Abhängigkeit eine Schnittstelle definiert<br />
werden. Um <strong>für</strong> Setter-Injection Abhängigkeiten zur Laufzeit erzeugen zu können, muss<br />
<strong>der</strong> Client die entsprechende Setter-Methode zum Setzen des benötigen Objektes<br />
anbieten. Bei Constructor-Injection werden sämtliche Abhängigkeiten einer Klasse über<br />
den Konstruktor übergeben. Damit kann ein Objekt <strong>der</strong> Klasse nur erzeugt werden,<br />
wenn alle Abhängigkeiten bei <strong>der</strong> Erstellung übergeben werden [Fo04].<br />
2.3 Aspektorientierte Programmierung<br />
Aspektorientierte Programmierung (AOP) ist ein Ansatz, um Codewie<strong>der</strong>holungen zu<br />
vermeiden. Dabei werden die sich ggf. wie<strong>der</strong>holenden Codestücke ausgelagert. Dies<br />
entspricht dem Prinzip „Separation of Concerns“. Das bedeutet <strong>der</strong> Basisbestandteil<br />
einer Methode wird von speziell zweckgebundenen und sich wie<strong>der</strong>holenden Teilen wie<br />
dem Überprüfen von Benutzerrechten getrennt. Die ausgelagerten Teile werden in <strong>der</strong><br />
AOP Aspekte bezeichnet. Ein Aspekt kann z. B. <strong>für</strong> Logging, Transaktionen o<strong>der</strong><br />
Sicherheit zuständig sein. Durch AOP entfällt die Duplizierung von Code. Er wird an<br />
einer zentralen Stelle implementiert und ist dadurch wie<strong>der</strong>verwendbar. Deshalb werden<br />
Aspekte auch als Querschnittsbelange (Cross Cutting Concerns) bezeichnet. Ein<br />
Beispiel hier<strong>für</strong> ist die Sicherheit, <strong>für</strong> die in je<strong>der</strong> Methode <strong>der</strong> Benutzer und seine<br />
Rechte überprüft werden. Mit AOP ist es möglich bei einem Methodenaufruf<br />
einzugreifen und zusätzlichen Code auszuführen. Die zentrale Speicherung des<br />
Quellcodes erhöht die Verständlichkeit und Wartbarkeit des Codes [Wo07].<br />
Im Umfeld von AOP werden neben dem Begriff Aspekt noch weitere Termini<br />
verwendet, die im Weiteren näher erläutert werden. Ein Advice beschreibt die Aufgabe<br />
eines Aspektes. Außerdem gibt <strong>der</strong> Advice an, wann die Aufgabe ausgeführt wird, z. B.<br />
vor dem Methodenaufruf. Stellen, an denen in <strong>der</strong> Anwendung ein Aspekt eingebunden<br />
werden kann, werden als Joinpoint bezeichnet. Ein Joinpoint kann z. B. vor einem<br />
Methodenaufruf o<strong>der</strong> bei einem geän<strong>der</strong>ten Feldwert auftreten. Pointcuts bilden eine<br />
Teilmenge <strong>der</strong> Joinpoints. Sie schränken die Aufrufe von Aspekten ein, indem sie<br />
definieren wo <strong>der</strong> Advice ausgeführt wird. Dies kann z. B. über reguläre Ausdrücke<br />
erfolgen. Ein Aspekt ist in diesem Zusammenhang die Vereinigung von Advice und<br />
Pointcut. Es ist bekannt welcher Code wo und wann ausgeführt wird [Wa08] .<br />
4
Kapitel 3: Spring Framework<br />
3 Spring Framework<br />
Bei Spring handelt es sich um ein OpenSource-Framework, welches insbeson<strong>der</strong>e die<br />
Programmierung von Java-EE-Anwendungen erleichtert. Grundlage <strong>für</strong> das Spring<br />
Framework bildete das Buch "Expert One-On-One J2EE Design and Development“. In<br />
diesem wurden die Programmiertechniken Dependency Injection und AOP beschrieben,<br />
die die wichtigsten Merkmale in Spring darstellen. Ziel <strong>der</strong> Entwicklung von Spring war<br />
es, die Erstellung von Unternehmensanwendungen zu vereinfachen. Die Basis <strong>für</strong> jede<br />
Spring-Anwendung bilden Anwendungsobjekte, sogenannte Spring-Beans, und <strong>der</strong><br />
Spring-Container, über den die Beans konfiguriert und über den kompletten<br />
Lebenszyklus verwaltet werden. Diese werden in den beiden folgenden Abschnitten<br />
näher beschrieben. Insgesamt setzt sich das Spring Framework aus sechs Modulen<br />
zusammen. Das Kernmodul stellt den Anwendungscontainer (Spring-Container) zur<br />
Verfügung, <strong>der</strong> die Grundlage <strong>für</strong> den Gebrauch von Dependency Injection bildet. Je<br />
nach Bedarf können weitere Spring Module an das Kernmodul angebunden werden, so<br />
dass die Nutzung von z. B. Hibernate ohne Probleme möglich ist. In den einzelnen<br />
Abschnitten dieses Kapitels werden außerdem noch die Module DAO und ORM, die <strong>für</strong><br />
den Datenbankzugriff notwendig sind und die Module AOP und MVC erläutert. Die<br />
Beschreibung von Spring und dessen Elementen erfolgt anhand eines Beispiels <strong>für</strong> die<br />
Implementierung einer Bibliotheksanwendung.<br />
3.1 Beispielanwendung Bibliothek<br />
Diese Beispielanwendung besteht aus Benutzern, die Exemplare von Büchern ausleihen<br />
können. Ein Klassendiagramm hierzu befindet sich im Anhang A. Es zeigt, dass Bücher<br />
eine 1:N-Beziehung zu Exemplaren haben, d. h. es kann mehrere Exemplare von einem<br />
Buch geben. Außerdem sind einem Benutzer mehrere Ausleihen zugeordnet. In diesem<br />
werden das Ausleihdatum, <strong>der</strong> Benutzer und das ausgeliehene Exemplar gespeichert.<br />
Ein Exemplar kann einer Ausleihe zugeordnet sein. Aus diesem Klassendiagramm wird<br />
mit Hilfe des Modules MVC eine Webanwendung erstellt. Mit dieser ist es möglich sich<br />
nach erfolgreichem Login alle Bücher sowie die aktuellen Ausleihen zu dem<br />
angemeldeten Benutzer anzeigen zu lassen. Der Administrator <strong>der</strong> Anwendung kann die<br />
Benutzer <strong>der</strong> Anwendung einsehen. In dieser Arbeit wird zunächst in Abschnitt 3.4<br />
Dependency Injection anhand <strong>der</strong> Klasse User erklärt. Diese wird in Abschnitt 3.7 um<br />
5
Kapitel 3: Spring Framework<br />
einen Datenbankzugriff erweitert. Die gesamten Daten <strong>der</strong> Anwendung sind in einer<br />
MySQL Datenbank gespeichert und werden über JDBC in die Anwendung integriert. In<br />
Abschnitt 3.5 wird AOP am Beispiel vom Logging-Aspekt erläutert. Das Module MVC<br />
wird in Abschnitt 3.6 anhand <strong>der</strong> Webseite zur Anzeige aller Bücher näher beschrieben.<br />
Damit sichergestellt ist, dass <strong>der</strong> authentifizierte Benutzer auch die erfor<strong>der</strong>lichen<br />
Rechte besitzt um bestimmte Services in Anspruch zu nehmen, wird in Abschnitt 3.8<br />
vorgestellt wie ein Sicherheitsaspekt mit Hilfe es Moduls Spring Security angelegt wird.<br />
3.2 Spring-Container<br />
Die Basis <strong>für</strong> jede Spring-Anwendung bilden Spring-Beans und <strong>der</strong> Spring-Container.<br />
Der Container erstellt, verbindet, konfiguriert und verwaltet alle Anwendungsobjekte,<br />
die Spring-Beans, über <strong>der</strong>en kompletten Lebenszyklus. Dazu wird Dependency<br />
Injection eingesetzt. Es gibt zwei Typen von Spring-Containern. Der Unterschied bei<strong>der</strong><br />
liegt im Leistungsumfang. Die BeanFactory ist eine Implementierung des Factory-<br />
Entwurfsmusters. Ihre Aufgabe ist es Spring-Beans zu erstellen und zu verteilen. Es<br />
handelt sich dabei um eine Allzweck-Factory, die unterschiedliche Bean-Typen<br />
zurückgibt. Die meistverwendete BeanFactory-Implementierung ist XmlBeanFactory.<br />
Sie arbeitet nach dem Lazy-Loading-Prinzip, d. h. die Instanzierung <strong>der</strong> Spring-Bean<br />
findet erst beim Aufruf <strong>der</strong> Bean durch die Methode getBean() statt. [Wa08, Kap. 2.1]<br />
Der ApplicationContext ist mächtiger als die BeanFactory. Deshalb wird dieser in<br />
komplexeren Anwendungen verwendet. Der Kontext umfasst neben den Funktionen <strong>der</strong><br />
BeanFactory Möglichkeiten zum Auslösen von Textnachrichten, Laden von<br />
Dateiressourcen wie Bil<strong>der</strong> und Veröffentlichen von Ereignissen <strong>für</strong> registrierte Spring-<br />
Beans. Im Gegensatz zur BeanFactory werden Singleton-Beans direkt instanziiert.<br />
BeanFactory factory = new XmlBeanFactory<br />
(new FileSystemResource("applicationContext.xml"));<br />
User peter = (User) factory.getBean("U4711");<br />
Listing 1: Erzeugung einer BeanFactory<br />
Ein Spring-Container kann aus je<strong>der</strong> normalen Java-Anwendung aufgerufen werden.<br />
Der Aufruf bei<strong>der</strong> Container-Typen ist ähnlich. Zunächst wird <strong>der</strong> Container erzeugt<br />
und anschließend die Bean über die Methode getBean() des Containers aufgerufen.<br />
Listing 1 zeigt die Erzeugung einer Spring-Bean über die BeanFactory. Dabei wird mit<br />
Hilfe einer FileSystemResource ein Objekt <strong>der</strong> XmlBeanFactory erzeugt. Die Bean-<br />
Definition wird aus einer XML-Datei ausgelesen. Üblicherweise wird eine Datei <strong>für</strong> die<br />
6
Kapitel 3: Spring Framework<br />
Konfiguration einer Spring-Anwendung erstellt. Aus dieser wird im Beispiel ein User-<br />
Bean, also <strong>der</strong> konkreter Benutzer Peter mit <strong>der</strong> ID U4711, über getBean() erzeugt<br />
[Wa08, Kap. 2.1].<br />
3.3 Spring-Bean<br />
Spring-Beans stellen Java-Klassen dar, die mit Hilfe des Spring-Containers konfiguriert<br />
werden. Für jedes Spring-Bean wird zunächst eine Java-Klasse mit setter- und getter-<br />
Methoden <strong>für</strong> die Attribute bzw. einem Konstruktor erstellt. Für die Injizierung erfolgt<br />
die Konfiguration über eine XML-Datei o<strong>der</strong> über Annotationen in <strong>der</strong> jeweiligen Java-<br />
Klasse. Bei XML-basierter Konfiguration wird eine Bean unter Verwendung des Tag<br />
erzeugt. Der Name über den auf das Bean über den Spring-Container<br />
zugegriffen werden kann, wird über das Attribut id übergeben. Im Attribut class wird<br />
<strong>der</strong> vollständige Name <strong>der</strong> Java-Klasse, auf den sich das Bean bezieht, angegeben<br />
[Wa08, Kap. 2.2].<br />
In Listing 2 wird eine Bean <strong>der</strong> Klasse User erzeugt. Auf dieses kann über die ID<br />
U4711 zugegriffen werden.<br />
Geltungsbereiche <strong>für</strong> Beans<br />
Jede Bean hat einen bestimmten Gültigkeitsbereich. Dieser wird über das Tag <br />
definiert. Dabei wird zwischen Singleton, Prototype, Request, Session und Global-<br />
Session differenziert. Standardmäßig sind alle Beans Singleton-Beans. Hierbei existiert<br />
nur eine Bean pro Spring-Container. Alle Aufrufe einer konkreten Bean werden von<br />
<strong>der</strong>selben Instanz durchgeführt. Mit Prototype ist eine mehrfache Instanziierung einer<br />
Bean ist möglich. Bei jedem Aufruf einer Bean wird eine neue Instanz erzeugt. Die<br />
Geltungsbereiche Request, Session und Global-Session finden nur im Rahmen von<br />
webbasierten Anwendungen Einsatz (z. B. bei Spring MVC) [Wa08, Kap. 2.5.1].<br />
3.4 Dependency Injection<br />
In Spring können zwei Typen von Dependency Injection eingesetzt werden: Setter-<br />
Injection und Konstruktor-Injection.<br />
7
Kapitel 3: Spring Framework<br />
Setter-Injection<br />
Bei Setter-Injection werden die Attribute <strong>der</strong> Bean über das -Tag gesetzt.<br />
Da<strong>für</strong> muss die Java-Klasse die entsprechenden Setter-Methoden aufweisen.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Listing 2: Setter-Injection<br />
Das Beispiel in Listing 2 zeigt, dass das -Tag die Attribute name und value<br />
besitzt. Mit name wird das Attribut <strong>der</strong> Bean-Klasse spezifiziert und mit value wird<br />
diesem eine Ausprägung übergeben. Hier wird ein Benutzer mit <strong>der</strong> ID 4711 und dem<br />
Namen Peter Muster erzeugt. Dies ist ein Beispiel ohne die Verwendung einer<br />
Datenbank. Auf die Verwendung einer Datenbank wird in Kapitel 3.7 näher<br />
eingegangen [Wa08, Kap. 2.3].<br />
Constructor-Injection<br />
Wenn die Injektion über einen Konstruktor erfolgen soll, passiert dies mit dem Tag<br />
. Über das Attribut value wird <strong>der</strong> Wert <strong>für</strong> den ersten<br />
Konstruktorwert übergeben. Durch Wie<strong>der</strong>holung des -Tags können<br />
bei mehreren Parametern im Konstruktor diesem Werte übergeben werden [Wa08,<br />
Kap. 2.2.2].<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Listing 3: Konstruktor-Injektion<br />
In Listing 3 wird <strong>der</strong> gleiche Benutzer wie in Listing 2 erzeugt. In diesem Fall<br />
allerdings durch Übergabe <strong>der</strong> Attributwerte an den Konstruktor.<br />
Die Beispiele zeigen, dass dem Attribut value immer Strings übergeben werden. Intern<br />
wird dieser String auf den entsprechenden Datentyp des Klassenattributes gecastet. Das<br />
Attribut value kann nur <strong>für</strong> primitive Datentypen und <strong>der</strong>en entsprechende Wrapper-<br />
8
Kapitel 3: Spring Framework<br />
Klassen verwendet werden. Falls auf eine an<strong>der</strong>e Bean referenziert werden soll, ist<br />
hier<strong>für</strong> das Attribut ref zu verwenden.<br />
Collections verschachteln<br />
Falls eine Bean eine Eigenschaft, die eine Liste von Ausprägungen wie eine Collection<br />
besitzt, kann diese auf vier unterschiedliche Arten mit Spring konfiguriert werden. Die<br />
Tags und verschachteln eine Liste von Werten, wobei nur bei <br />
doppelte Werte erlaubt sind. Die dritte Möglichkeit Mehrfacheigenschaften zu<br />
konfigurieren ist über das -Tag. Diese entspricht <strong>der</strong> Collection java.util.Map.<br />
Das -Tag stellt die vierte Möglichkeit zur Konfiguration von<br />
Mehrfacheigenschaften dar und entspricht java.util.Properties [Wa08, Kap. 2.3].<br />
<br />
. . .<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Listing 4: Injizierung von Collections<br />
In Listing 4 wird über das Tag eine Collection <strong>für</strong> das Attribut lending zum<br />
Benutzer U4711 angelegt d. h. <strong>der</strong> Benutzer hat zur Zeit drei Exemplare ausgeliehen.<br />
Autowiring<br />
Statt alle Eigenschaften einer Bean über die Tags o<strong>der</strong> zu<br />
setzen, kann vor allem bei komplexen Anwendungen, die Verknüpfung <strong>der</strong> Beans<br />
untereinan<strong>der</strong> automatisch erfolgen. Dabei wird bei jedem Bean, das automatisch<br />
verbunden werden soll, die Eigenschaft autowire gesetzt. In Spring gibt es vier Typen<br />
von Autowiring. Bei Autowiring byName wird die Eigenschaft von Beans über den<br />
Namen <strong>der</strong> Eigenschaft vervollständigt. Lautet <strong>der</strong> Name <strong>der</strong> Eigenschaft z. B. „book“<br />
wird nach einem Bean mit <strong>der</strong> id „book“ gesucht. Die Vervollständigung kann auch<br />
über den Typ <strong>der</strong> Eigenschaft, also dem Klassennamen z. B. class = bib.User, erfolgen.<br />
Dies wird als Autowiring byType bezeichnet. Die dritte Variante von Autowiring ist<br />
byConstructor. Dabei wird versucht eine o<strong>der</strong> mehrere Beans auf die Parameter des<br />
Konstruktors abzubilden. Bei <strong>der</strong> vierten Variante, Autodect-Autowiring, wird<br />
Autowiring erst byType und anschließend byConstructor durchgeführt. Das<br />
9
Kapitel 3: Spring Framework<br />
automatische Verbinden aller Eigenschaften einer Bean, kann durch Angabe von<br />
Eigenschaften über das Tag überschrieben werden [Wa08, Kap. 2.4].<br />
3.5 Aspektorientierte Programmierung<br />
Vom Spring Framework werden in <strong>der</strong> AOP nur Joinpoints im Zusammenhang mit<br />
einem Methodenaufruf unterstützt. An<strong>der</strong>e AOP Funktionalitäten können über die<br />
Einbindung von <strong>der</strong> Java-AOP-Erweiterung AspectJ in das Spring Framework erzielt<br />
werden. Spring-Advices sind in Java-Klassen zu erstellen. Die dazugehörigen Pointcuts<br />
werden gewöhnlich in <strong>der</strong> XML-Konfigurationsdatei geschrieben. Aspekte werden in<br />
Spring zur Laufzeit in Spring-Beans eingebettet, indem sie in einer Proxy-Klasse<br />
gekapselt werden. Der Proxy fängt den Methodenaufruf ab, so dass die Methode um die<br />
Zusatzfunktionalität, den Advice, erweitert werden kann. Der Proxy wird ebenfalls in<br />
<strong>der</strong> Bean-Konfigurationsdatei definiert. Bei Spring AOP gibt es fünf verschiedene<br />
Typen von Advices, die über Einbindung des entsprechenden Interfaces implementiert<br />
werden. Dabei werden die Interfaces MethodBeforeAdvice, AfterReturningAdvice,<br />
ThrowsAdvice, MethodInterceptor und IntroductionInterceptor unterschieden [Wa08,<br />
Kap. 4.1].<br />
package aop;<br />
public class LoggingAdvice implements MethodInterceptor {<br />
public Object invoke(MethodInvocation methodInvocation){<br />
Log log;<br />
log = LogFactory.getLog(getClassName(methodInvocation));<br />
log.info("Class : " + getClassName(methodInvocation));<br />
log.info("Method : " + getMethodName(methodInvocation));<br />
log.info("Arguments : " + getArguments(methodInvocation));<br />
...<br />
//ausführen <strong>der</strong> eigentlichen Methode<br />
result = methodInvocation.proceed();<br />
...<br />
}<br />
...<br />
}<br />
Listing 5: LoggingAdvice<br />
Listing 5 zeigt ein typisches Beispiel <strong>für</strong> einen Advice, den LoggingAdvice. Hiermit<br />
werden zu je<strong>der</strong> Methode, die dem Advice zugeordnet wird, Logginginformationen wie<br />
die aufgerufene Methode und <strong>der</strong>en übergebene Parameter auf <strong>der</strong> Konsole ausgegeben.<br />
Dazu wird das Interface MethodInterceptor implementiert, das die Methode invoke()<br />
beinhaltet, die implementiert werden muss. Über methodeInvocation.proceed() wird die<br />
abgefangene Methode ausgeführt.<br />
10
Kapitel 3: Spring Framework<br />
Anschließend werden Pointcuts in <strong>der</strong> Konfigurationsdatei definiert. In Spring werden<br />
Pointcuts am häufigsten über reguläre Ausdrücke o<strong>der</strong> mit AspectJ-Ausdrücken<br />
festgelegt. Der reguläre Ausdruck legt fest, in welchen Methoden <strong>der</strong> zum Pointcut<br />
gehörende Advice ausgeführt wird. Dies erfolgt über einen Vergleich zwischen dem<br />
regulären Ausdruck und <strong>der</strong> Methodensignatur. In <strong>der</strong> XML-Konfigurationsdatei wird<br />
über das Attribut pattern <strong>der</strong> reguläre Ausdruck angegeben [Wa08, Kap. 4.1].<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Listing 6: Konfiguration von Advice, Pointcut und Advisor<br />
In Listing 6 ist <strong>der</strong> Pointcut loggingPointcut definiert, <strong>der</strong> <strong>für</strong> jede Methode in Package<br />
services angewandt wird. Neben dem Pointcut ist noch die Verschmelzung mit dem<br />
Advice zu konfigurieren. Dieser Aspekt wird in Spring als Advisor gehandhabt. Über<br />
die -Tags des Advisor werden <strong>der</strong> Pointcut und Advice in Listing 6 vereinigt.<br />
3.6 Model View Controller<br />
Für den Aufbau einer webbasierten Anwendung wird in Spring das Modul MVC<br />
eingesetzt. Dieses beruht auf dem Entwurfsmuster Model View Controller (MVC).<br />
Stellt ein Benutzer eine Anfrage, wenn er z. B. alle Bücher <strong>der</strong> Bibliothek einsehen<br />
möchte, wird diese in Spring zunächst an das Dispatcher Servlet gesendet, welcher auch<br />
als Frontend-Controller bezeichnet wird. Dieser agiert, wie <strong>der</strong> Begriff schon vermuten<br />
lässt, als Verteiler von Aufgaben. Diese Weitergabe und Entgegennahme <strong>der</strong> Ergebnisse<br />
visualisiert Abbildung 1.<br />
11
Kapitel 3: Spring Framework<br />
Abbildung 1: Anfrageverarbeitung über Dispatcher Servlet<br />
Wie jedes Servlet muss auch <strong>der</strong> Dispatcher in <strong>der</strong> web.xml-Datei deklariert werden.<br />
Über das -Tag wird angegeben, welche URLs das Servlet behandeln soll.<br />
Die Webanfragen behandelt ein Controller im Auftrag des Dispatcher Servlets (siehe<br />
Nr. 3 in Abbildung 1). Zur Abwicklung <strong>der</strong> Anfrage verteilt dieser die Aufgaben an die<br />
Serviceschicht und führt die übermittelten Ergebnisse anschließend zusammen. Der<br />
Controller wird als normale Java-Klasse implementiert und im Anwendungskontext als<br />
Bean konfiguriert. Für die vorgestellte Bibliotheksanwendung wird eine Webseite<br />
benötigt, die alle vorhandenen Bücher anzeigt. Der BookController in Listing 7 erbt von<br />
<strong>der</strong> Klasse AbstractController. Darin wird die Methode handleRequestInternal()<br />
implementiert. In dieser wird die Methode getBooks() des BookService aufgerufen und<br />
ein ModelAndView-Objekt zurückgeben [Wa08 , Kap. 13.1].<br />
package mvc;<br />
public class BookController extends AbstractController{<br />
private BookService bookService;<br />
private String view = "booklist";<br />
public BookService getBookService() {<br />
return bookService;<br />
}<br />
public void setBookService(BookService bookService) {<br />
this.bookService = bookService;<br />
}<br />
protected ModelAndView handleRequestInternal(HttpServletRequest<br />
request, HttpServletResponse response) throws Exception {<br />
Map model = new HashMap();<br />
model.put("books", bookService.getBooks());<br />
return new ModelAndView(view, model);<br />
}<br />
<br />
<br />
<br />
Listing 7: Implementierung und Konfiguration eines Controllers<br />
12
Kapitel 3: Spring Framework<br />
Des Weiteren wird <strong>der</strong> BookController in Listing 7 als Bean konfiguriert. Im Bean wird<br />
anstelle des Attributes id unter name die URL des Controllers mit vorausgesetztem<br />
Schrägstrich angegeben z. B. /book.htm. So wird jede Anfrage, die mit dieser URL an<br />
das Dispatcher Servlet gestellt wird, an diesen Controller weitergegeben. Anstelle <strong>der</strong><br />
Verwendung <strong>der</strong> name-Eigenschaft, könnte auch ein Handler-Mapping-Bean<br />
konfiguriert werden (siehe Nr. 2 in Abbildung 1). Ein Handler-Mapping-Bean<br />
entscheidet, welcher Controller die Anfrage bearbeitet. Im Controller-Bean wird <strong>der</strong><br />
Service, <strong>der</strong> Aufgaben ausführen soll, über Dependency Injection injiziert. Im Beispiel<br />
ist das BookService. Die Methode handleRequestInternal() zur Behandlung <strong>der</strong> Anfrage<br />
muss ein Objekt <strong>der</strong> Klasse ModelAndView zurückgeben. Dieses Objekt kapselt die<br />
View und die Modelldaten, die vom View dargestellt werden sollen. Das<br />
ModelAndView-Objekt wird vom Dispatcher Servlet an den View-Resolver weiter<br />
gegeben (siehe Nr. 5 in Abbildung 1). Der ordnet dem im ModelAndView-Objekt<br />
zurückgegebenen View-Namen eine View zu. Die View ist in den meisten Fällen eine<br />
JSP-Seite z. B. booklist.jsp. Listing 8 zeigt wie <strong>der</strong> View-Resolver über den<br />
Anwendungskontext zu konfigurieren ist. Dabei wird <strong>für</strong> JSP-Seiten<br />
InternalResourceViewResolver verwendet. Mit ihm können über die Attribute prefix<br />
und suffix an den View-Namen Werte vor- bzw. angehangen werden, so dass sich eine<br />
vollständige URL ergibt. Für das Beispiel in Listing 8 ergibt sich die URL „/WEB-<br />
INF/jsp/booklist.jsp“. An diese URL leitet das Dispatcher Servlet die Anfrage weiter,<br />
um die Webseite <strong>für</strong> den Benutzer dazustellen. Die JSP-Seite die dabei aufgerufen wird<br />
findet sich in Listing 9. In <strong>der</strong> JSP-Seite wird dabei auf das Model „books“<br />
zurückgegriffen. Somit bekommt <strong>der</strong> Benutzer eine Liste mit allen Büchern angezeigt<br />
[Wa08 , Kap. 13.1].<br />
<br />
<br />
<br />
<br />
Listing 8: Konfiguration eines View-Resolvers<br />
<br />
<br />
<br />
<br />
<br />
<br />
Bücherliste<br />
13
Kapitel 3: Spring Framework<br />
<br />
<br />
Willkommen in <strong>der</strong> Bibliothek<br />
Hier sehen Sie alle verfügbaren Bücher<br />
<br />
BuchAutor<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Listing 9: View books.jsp<br />
3.7 Datenbankzugriff<br />
Für eine praktische Verwendung benötigt fast jede Anwendung eine Datenpersistenz.<br />
Spring integriert eine ganze Reihe an Datenzugriffs-Frameworks, die mit vielen<br />
Datenzugriffstechnologien verbunden werden können. Dies sind u. a. JDBC o<strong>der</strong> O/R<br />
Mapper wie Hibernate, iBATIS o<strong>der</strong> JPA. In diesem Unterkapitel wird die Anbindung<br />
von JDBC und als Beispiel <strong>für</strong> einen O/R Mapper JPA vorgestellt.<br />
Data Access Objects (DAO) kapseln den Datenbankzugriff in Spring. Dies geschieht<br />
unter Verwendung des Entwurfsmusters <strong>der</strong> Schablonenmethode (Template Method).<br />
Die generelle Struktur eines Datenzugriffs wird unabhängig von <strong>der</strong> verwendeten<br />
Technologie in einer abstrakten Oberklasse (Template) definiert. Bestimmte<br />
Operationen des Datenbankzugriffs können in den Unterklassen überschrieben werden,<br />
ohne die Struktur des Zugriffs zu än<strong>der</strong>n. Zu den feststehenden Teilen des Zugriffs<br />
zählen die Steuerung von Transaktionen, die Ressourcenverwaltung und die<br />
Exceptionbehandlung. Des Weiteren bietet Spring noch Supportklassen zur<br />
Vereinfachung des Zugriffs auf das Template. Den Zusammenhang zeigt Abbildung 2<br />
[Wa08, Kap. 5.1].<br />
Abbildung 2: Beziehung zwischen Anwendungs-DAO, DAO-Supportklasse und Schablonenklasse<br />
[Wa08, Kap. 5.1]<br />
14
Kapitel 3: Spring Framework<br />
Diese Implementierung trennt die Datenzugriffschicht in Spring vom Rest <strong>der</strong><br />
Anwendung. Dies hat zur Folge, dass eine konsistente Exception-Hierarchie über alle<br />
DAO-Frameworks hinweg verfügbar ist. Es werden nicht die Exceptions aus JDBC<br />
o<strong>der</strong> an<strong>der</strong>en OR-Mappern in das Spring Framework übernommen, da JDBC<br />
Exceptions universell sind und Exceptions von OR-Mapper spezifisch auf die<br />
Datenbank bzw. das Framework zu geschnitten sind. Diese Exception werden<br />
abgefangen und intern verarbeitet. Zurückgegeben werden Spring eigene Exceptions,<br />
die von RuntimeException abgeleitet sind. Für diese ist keine Behandlung notwendig.<br />
So kann sich <strong>der</strong> Programmierer den catch-Block sparen [Wa08, Kap. 5.1].<br />
JDBC-Anbindung<br />
Grundlage <strong>für</strong> den Datenbankzugriff ist die Definition eines Datenquellen-Beans<br />
DataSource. Da<strong>für</strong> stehen in Spring zwei Klassen zur Verfügung.<br />
DriverManagerDataSource gibt bei je<strong>der</strong> Anfrage eine neue Verbindung zurück,<br />
während SingleConnectionDataSource immer dieselbe Verbindung wie<strong>der</strong>gibt. Da<br />
beide Verbindungen über keinen Pool zur Verbindungsverwaltung verfügen, sind sie <strong>für</strong><br />
komplexere Anwendungen nicht geeignet. Das Beispiel in Listing 10 zeigt wie das<br />
dataSource-Bean konfiguriert wird. Das Attribut driverClassName enthält den JDBC-<br />
Datendatenbanktreiber, url die Adresse <strong>der</strong> verwendete Datenbank und username und<br />
password den zugehörigen Benutzer und das Kennwort [Wa08, Kap. 5.3].<br />
<br />
<br />
<br />
<br />
<br />
<br />
Listing 10: JDBC Anbindung<br />
Anschließend ist ein AnwendungsDAO zu erstellen. Da<strong>für</strong> wird zunächst eine DAO-<br />
Klasse implementiert. Diese kann von <strong>der</strong> von Spring bereitgestellten Supportklasse <strong>für</strong><br />
JDBC-Datenbanken NamedParameterJdbcDaoSupport abgeleitet werden. Mit dieser<br />
Klasse ist neben <strong>der</strong> Bereitstellung von Standard-JDBC-Funktionen in SQL-Statements<br />
die Verwendung von benannten Parametern anstatt von indizierten Parametern möglich.<br />
Da<strong>für</strong> werden <strong>der</strong> Methode zur Ausführung eines SQL-Statements das Statement und<br />
eine HashMap mit den Parametern des Statements übergeben. Listing 11 zeigt dies am<br />
15
Kapitel 3: Spring Framework<br />
Beispiel <strong>für</strong> das Auslesen aller Bücher <strong>für</strong> die Bibliotheksanwendung. Diese werden mit<br />
Hilfe eines RowMappers in einer Liste von Büchern konvertiert [Wa08, Kap. 5.3].<br />
package jdbc;<br />
public class BookDAO extends NamedParameterJdbcDaoSupport implements<br />
IBookDao{<br />
public List getAll() {<br />
return (List) getJdbcTemplate().query(<br />
"SELECT DESCRIPTION, ISBN, AUTOR, ID FROM Book ",<br />
new BookRowMapper());<br />
}<br />
… }<br />
Listing 11: JDBC Anfrage<br />
JPA-Anbindung<br />
Die JPA-Anbindung erfolgt sowohl in JPA direkt als auch in Spring über einen Entity-<br />
Manager. Des Weiteren wird <strong>für</strong> die JPA-Anbindung wie<strong>der</strong> mit einem Template<br />
gearbeitet (siehe Listing 12). Das JpaTemplate erfüllt die gleichen Aufgaben wie an<strong>der</strong>e<br />
Templates <strong>für</strong> Datenbankanbindungen in Spring auch. Zudem sorgt es da<strong>für</strong>, dass <strong>der</strong><br />
Entity-Manager wie benötigt geschlossen und geöffnet wird und stellt weitestgehend<br />
dieselben Persistenzmethoden wie ein Entity-Manager <strong>für</strong> JPA zur Verfügung [Wa08,<br />
Kap. 5.5].<br />
Als Entity-Manager kann ein anwendungsverwalten<strong>der</strong> o<strong>der</strong> containerverwalten<strong>der</strong><br />
Entity-Manager eingesetzt werden. Der Unterschied zwischen beiden liegt in <strong>der</strong><br />
Konfiguration. Diese erfolgt <strong>für</strong> anwendungsverwaltende Entity-Manager über eine<br />
Konfigurationsdatei namens persistenxe.xml, bei containerverwalten<strong>der</strong> Konfiguration<br />
im Spring-Anwendungskontext. Listing 12 zeigt wie ein containterverwalten<strong>der</strong> Entity-<br />
Manager in Spring mithilfe von LocalContainerEntityManagerFactoryBean<br />
konfiguriert wird.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
16
Kapitel 3: Spring Framework<br />
<br />
Listing 12: Konfiguration einer containerverwaltenden EntityManagerFactory-Bean<br />
Die Konfiguration <strong>der</strong> Datenquelle, welche vom Entity-Manager benutzt wird, erfolgt<br />
über die Eigenschaft dataSource und ist vergleichbar mit <strong>der</strong> Konfiguration in Listing<br />
10. Über die Eigenschaft jpaVendorAdapter können Details zur verwendeten JPA-<br />
Implementierung angeführt werden. In diesem Fall ist das TopLink Essentials.<br />
Nach <strong>der</strong> Konfiguration des Entity-Managers wird die DAO-Klasse eingerichtet. Wie<br />
bereits bemerkt, bietet Spring da<strong>für</strong> Support-Klassen an, von denen die selbst zu<br />
erstellende DAO-Klasse erbt. Für die JPA-Anbindung wird JpaDaoSupport verwendet.<br />
Diese Verwendung zeigt Listing 13 am Beispiel <strong>der</strong> Klasse JpaUserDAO. Für die<br />
dauerhafte Speicherung eines Objekts in <strong>der</strong> Datenbank muss die Methode persist des<br />
JpaTemplate Objekts aufgerufen werden [Wa08, Kap. 5.5].<br />
public class JpaUserDAO extends JpaDaoSupport implements IUserDAO {<br />
public void createUser(User user) throws CreateFailureException<br />
{<br />
getJpaTemplate().persist(user);<br />
}<br />
}<br />
Listing 13: Klasse JpaUserDAO<br />
3.8 Sicherheit<br />
Das Sicherheits-Framework in Spring stellt umfangreiche Sicherheitslösungen <strong>für</strong> die<br />
Authentifizierung und Autorisierung auf Webanfrage- und Methodenaufrufebene zur<br />
Verfügung. Spring Security nutzt da<strong>für</strong> DI und AOP. Mit Hilfe des Authentification-<br />
Managers erfolgt die Überprüfung des Benutzernamens und des dazugehörigen<br />
Passworts. Nach erfolgreicher Authentifizierung wird über den Access-Decision-<br />
Manager kontrolliert, ob die Anfrage o<strong>der</strong> Methode von Benutzer ausgeführt werden<br />
darf [Wa08, Kap. 7.1].<br />
Authentifizierung<br />
Der Authentication-Manager verifiziert die eingegebenen Benutzerdaten über die<br />
Methode authenticate(). Bei erfolgreicher Authentifizierung gibt die Methode ein<br />
Authentication-Objekt zurück, das Information über den Benutzer und dessen Rechte<br />
enthält. An<strong>der</strong>nfalls wird eine AuthenticationException ausgelöst. Für die meisten Fälle<br />
<strong>der</strong> Benutzerprüfung wird <strong>der</strong> Provi<strong>der</strong>Manager, eine Implementierung des<br />
17
Kapitel 3: Spring Framework<br />
AuthenticationManager, benutzt. Dabei kann <strong>der</strong> Benutzer gegenüber mehreren Quellen<br />
zur Identitätsverwaltung authentifiziert werden. Dazu werden die Benutzereingaben an<br />
Provi<strong>der</strong> weitergegeben. Der Provi<strong>der</strong>Manager erhält im Attribut provi<strong>der</strong> eine Liste <strong>der</strong><br />
Authentifizierungsdienste. Im Allgemeinen wird nur ein Dienst benötigt. Für die<br />
Authentifizierung mit Hilfe einer Datenbank bietet Spring Security den<br />
DaoAuthenticationProvi<strong>der</strong>. Die Konfiguration des Provi<strong>der</strong>Managers findet sich im<br />
oberen Teil von Listing 14. Dieser kann über die authenticationManager referenziert<br />
werden und beinhaltet einen AuthenticationProvi<strong>der</strong>, <strong>der</strong> weiter unten definiert ist<br />
[Wa08, Kap. 7.2].<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
SELECT USERNAME, PASSWORD, ENABLE as enabled<br />
FROM USER<br />
WHERE USERNAME = ?<br />
<br />
<br />
<br />
<br />
SELECT u.USERNAME as username, AUTORITY as authority<br />
FROM AUTORITY a , USER u<br />
WHERE a.USERNAME = u.USERNAME<br />
AND u.USERNAME = ?<br />
<br />
<br />
<br />
Listing 14: Konfiguration des Authentification Managers<br />
Des Weiteren wird in Listing 14 das AuthenticationDAO konfiguriert, das eine<br />
Instanzierung von JdbcDaoImpl ist. Diese erwartet, dass die Benutzerangaben in den<br />
Tabellen Users und Authorities mit den Attributen username, password und enabled<br />
bzw. username und authority vorliegt. Falls dies nicht <strong>der</strong> Fall ist, können wie in Listing<br />
18
Kapitel 3: Spring Framework<br />
14 über die Eigenschaften usersByUsernameQuery und authoritiesByUsernameQuery<br />
die entsprechenden SQL-Statements angegeben werden.<br />
Autorisierung<br />
Als nächster Schritt nach <strong>der</strong> Authentifizierung erfolgt die Autorisierung. Da<strong>für</strong> wird<br />
zunächst festgelegt, wie die Entscheidung <strong>für</strong> den Zugriff auf das angefragte Objekt<br />
getroffen werden soll. Es gibt dazu drei Implementierungen des<br />
AccessDecisionManager. Die Konfiguration <strong>für</strong> alle ist gleich.<br />
Listing 15 zeigt den Typ UnianimousBased, <strong>der</strong> den Zugriff gewährt, wenn alle<br />
Abstimmenden <strong>für</strong> den Zugriff gestimmt haben. Als nächstes werden eine o<strong>der</strong> mehrere<br />
Instanzen konfiguriert, welche kontrollieren, ob die Benutzerrechte mit den Rechten, die<br />
<strong>für</strong> den Zugriff auf das Objekt benötigt werden, übereinstimmen. Jede Instanz<br />
implementiert dabei das Interface AccessDecisionVoter. In<br />
Listing 15 wird eine Instanz roleVoter konfiguriert. Diese stimmt <strong>für</strong> den Zugriff, wenn<br />
<strong>der</strong> Benutzer zur Rolle mit dem Präfix „ROLE_“ gehört [Wa08, Kap. 7.3].<br />
Weitere Möglichkeiten, die <strong>der</strong> Authentication-Manager bietet sind Passwort-<br />
Verschlüsselung, Caching von Benutzerdaten und Authentifizierung gegenüber LDAP<br />
[Wa08, Kap. 7.2].<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Listing 15: Konfiguration des AccessDecisionManagers<br />
Zuordnung zu Methoden<br />
<br />
<br />
<br />
<br />
19
Kapitel 3: Spring Framework<br />
<br />
<br />
<br />
<br />
services.BookService.getBooks*=ROLE_USER<br />
services.LendingService.getLendings*=ROLE_USER<br />
services.UserService.getUsers*=ROLE_ADMIN<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
securityInterceptor<br />
<br />
<br />
<br />
<br />
services.BookService<br />
services.LendingService<br />
services.UserService<br />
<br />
<br />
<br />
Listing 16: Zuordnung und Konfiguration von Zugriffrechten zu Methoden<br />
Listing 16 zeigt wie Zugriffsrechte <strong>für</strong> Methoden vergeben werden. Dazu wird ein<br />
securityInterceptor konfiguriert, dem <strong>der</strong> AuthenticationManager und<br />
AccessDecisionManager zugeordnet wird. Über die Eigenschaft objectDefinitionSource<br />
werden einzelnen Methoden Rollen zugeordnet, z. B. darf nur <strong>der</strong> Admin die Methode<br />
getUsers() aufrufen und damit alle Benutzer einsehen. Außerdem dürfen Benutzer mit<br />
<strong>der</strong> Rolle ROLE_USER Bücher und Ausleihen aufrufen ebenso wie <strong>der</strong> Admin. Neben<br />
<strong>der</strong> Zugriffrechtezuordnung muss zudem ein Proxy <strong>für</strong> den securityInterceptor definiert<br />
werden. Somit werden bei Aufruf <strong>der</strong> Beans BookService, LendingService und<br />
UserService zunächst über den Proxy die Zugriffsrechte des Benutzers überprüft. Hier<br />
findet also AOP ihre Anwendung. Wenn <strong>der</strong> Benutzer nicht authentifiziert ist, wird eine<br />
AuthentificationException ausgelöst. Eine AccessDecisionException wird geworfen,<br />
wenn <strong>der</strong> Benutzer nicht die erfor<strong>der</strong>lichen Rechte aufweist [Wa08, Kap. 7.6].<br />
20
Kapitel 4: Vergleich Spring und Java EE<br />
4 Vergleich Spring und Java EE<br />
Spring ist entstanden, um die Entwicklung von Java EE-Anwendungen zu vereinfachen<br />
ohne auf Vorteile <strong>der</strong> Java-EE-Umgebung verzichten zu müssen. Aus diesem Grund<br />
wird es auch als Lightweight-Framework bezeichnet. Dieses leichtgewichtige Modell<br />
baut auf POJOs (Plain Old Java Objects) auf, also auf „ganz normalen“ Objekten.<br />
Dennoch verlangt auch Spring eine gründliche Auseinan<strong>der</strong>setzung mit dem Framework<br />
damit diese angewandt werden kann. Java EE ist neben seiner Komplexität auch sehr<br />
flexibel. Deshalb werden größere Anwendungen in Java EE implementiert. Mittlerweile<br />
unterstützt auch Java EE durch die Spezifikation EJB 3.0 ein POJO-basiertes<br />
Programmiermodell, das die Anwendung schlichter macht [Wo07, Kap. 1.3].<br />
Java EE und Spring nutzen beide Dependency Injection. In Spring erfolgt die<br />
Konfiguration meistens über Deskriptoren also XML. Dahingegen werden in Java EE<br />
meistens Annotationen verwendet. Deskriptoren können aber <strong>für</strong> das Überschreiben von<br />
Methoden verwendet werden. Ebenso ist es in Spring möglich Annotationen zu<br />
benutzen. Java EE verwendet <strong>für</strong> die Geschäftslogik EJBs, die nur zusammen mit einem<br />
Java-Server lauffähig sind. In Spring wird die Geschäftslogik unabhängig vom Server<br />
verwaltet. Ein weiteres Ziel von Spring ist die Integration an<strong>der</strong>er Frameworks zu<br />
vereinfachen [Wo07, Kap 1.3].<br />
Das Interceptor-Konzept <strong>für</strong> EJB 3.0 erlaubt die Behandlung von Querschnittsbelangen<br />
wie Sicherheitsaspekten. Dies ist die erste und einfache Form von AOP in einer Java-<br />
EE-Anwendung. In Spring stellt AOP einer Grundfunktionalität dar. Dabei werden<br />
Methoden Pointcuts unterstützt. Für einen größeren Funktionsumfang kann AspectJ in<br />
Spring eingebunden werden. Somit bietet Spring eine umfangreichere AOP Umsetzung<br />
als Java EE an [Wo07, Kap 1.3].<br />
Bei Java EE handelt es sich um einen Standard. Dies hat zum Vorteil, dass<br />
Herstellerunabhängigkeit erreicht wird. Des Weiteren ist viel Wissen über Java EE auf<br />
dem Markt verfügbar. Das reduziert den Einarbeitungsaufwand und es können schneller<br />
Lösungen <strong>für</strong> Probleme gefunden werden. Diese Vorteile können auch in einem Spring<br />
Projekt genutzt werden. Dazu muss Spring als Abstraktion über eine Java-EE-<br />
Umgebung verwendet werden [Wo07, Kap 1.3].<br />
21
Kapitel 5: Zusammenfassung und Ausblick<br />
5 Zusammenfassung und Ausblick<br />
In dieser Arbeit wurde zunächst <strong>der</strong> Begriff Framework näher erläutert. Dabei handelt<br />
es sich um ein Rahmenwerk, das <strong>für</strong> die Softwareentwicklung bestimmte<br />
Funktionalitäten zur Verfügung stellt. Diese können genutzt und erweitert werden. So<br />
wird vermieden, dass wie<strong>der</strong> verwendbare Funktionalitäten jedes Mal neu<br />
implementiert werden müssen.<br />
Anschließend wurden die Programmiertechniken Dependency Injektion und<br />
Aspektorientierte Programmierung erläutert. Dieses sind die wichtigsten<br />
Programmiertechniken, die im Spring Framework verwendet werden. In Kapitel 3<br />
wurde dieses Framework anhand einer Bibliotheksanwendung näher dargelegt. Dabei<br />
wurden zunächst Spring-Beans und <strong>der</strong> Spring-Container anhand von Beispielen<br />
veranschaulicht. Spring-Beans stellen Anwendungsobjekte dar, die über eine<br />
Konfigurationsdatei erstellt und über den Spring-Container verwaltet werden. Im<br />
Anschluss daran wurden Dependency Injektion und AOP in Spring vorgestellt. In<br />
Spring können die Typen Setter- und Constructor-Injektion verwendet werden.<br />
Nachfolgend wurde die Konfiguration einer Datenbankanbindung über JDBC und JPA<br />
beschrieben. Außerdem wird <strong>für</strong> die Gewährleistung <strong>der</strong> Sicherheit im System eine<br />
verlässige Authentifizierung von Benutzer benötigt. Dazu werden in Spring auch<br />
Aspekte eingesetzt.<br />
Nach <strong>der</strong>en Vorstellung, schließt die Arbeit mit einem Vergleich zwischen den<br />
Frameworks Spring und Java EE. Dabei wurden herausgestellt, dass Spring als<br />
leichtgewichtige Entwicklung zu Java EE entwickelt wurde. Mittlerweile ist in Java EE<br />
durch die Spezifikation EJB 3.0 die Java-Entwicklung einfacher. In beiden Frameworks<br />
kann Dependency Injection und AOP eingesetzt werden.<br />
In dieser Arbeit wurden einige Funktionen bzw. Module des Spring Frameworks näher<br />
dargelegt. Diese können je nach Bedarf in das Framework eingebunden werden. Sie<br />
vereinfachen die Entwicklung von Java-Anwendungen und sind <strong>für</strong> den Entwickler eine<br />
gute Unterstützung. Die Funktionen bzw. Module, die in dieser Arbeit nicht vorgestellt<br />
wurden, sind in zahlreichen Büchern über das Spring Framework und auf Webseiten<br />
dokumentiert. Ausblickend lässt sich festhalten, dass aufgrund des hohen Interesses, das<br />
am Spring Framework <strong>der</strong>zeit besteht, davon ausgegangen werden kann, dass es auch<br />
zukünftig verwendet und weiterentwickelt wird.<br />
22
Anhang A: Klassendiagramm<br />
Anhang A: Klassendiagramm<br />
Abb. 1: Klassendiagramm Bibliothek<br />
23
Anhang B: Quellcode<br />
Anhang B: Quellcode<br />
LoggingAdvice.java<br />
package aop;<br />
import java.util.Arrays;<br />
import org.aopalliance.intercept.MethodInterceptor;<br />
import org.aopalliance.intercept.MethodInvocation;<br />
import org.apache.commons.logging.Log;<br />
import org.apache.commons.logging.LogFactory;<br />
/**<br />
* Logging Advice, den zu den zugeordneten Methoden<br />
Tracinginformationen<br />
* wie Methodenname, Parameter und Startzeit hinzufügt<br />
* @author Birgit<br />
*<br />
*/<br />
public class LoggingAdvice implements MethodInterceptor {<br />
private static long invocationID = 0;<br />
private static synchronized long getInvocationID() {<br />
return invocationID++;<br />
}<br />
/**<br />
* Methode, den zu den zugeordneten Methoden<br />
Tracinginformationen<br />
* wie Methodenname, Parameter und Startzeit hinzufügt<br />
* @param methodInvocation Methode, die erweitert wird<br />
*/<br />
public Object invoke(MethodInvocation methodInvocation)<br />
throws Throwable {<br />
Object result;<br />
}<br />
/**<br />
long startMillis;<br />
long endMillis;<br />
long id;<br />
Log log;<br />
log =<br />
LogFactory.getLog(getClassName(methodInvocation));<br />
id = getInvocationID();<br />
startMillis = System.currentTimeMillis();<br />
logMethodStart(log, methodInvocation, id,<br />
startMillis);<br />
try {<br />
result = methodInvocation.proceed();<br />
} catch (Throwable throwable) {<br />
endMillis = System.currentTimeMillis();<br />
logMethodException(log, methodInvocation, id,<br />
startMillis, endMillis, throwable);<br />
throw throwable;<br />
}<br />
endMillis = System.currentTimeMillis();<br />
logMethodEnd(log, methodInvocation, id, startMillis,<br />
endMillis, result);<br />
return result;<br />
24
Anhang B: Quellcode<br />
* ermittelt die Parameterwerte <strong>der</strong> aufgerufenen Methode<br />
* @param methodInvocation Methodenaufruf<br />
* @return gibt die Parameterwerte zurück<br />
*/<br />
private static String getArguments(MethodInvocation<br />
methodInvocation) {<br />
String result;<br />
Object[] args;<br />
args = methodInvocation.getArguments();<br />
if (args == null) {<br />
result = "[]";<br />
} else {<br />
result = Arrays.asList(args).toString();<br />
}<br />
return result;<br />
}<br />
/**<br />
* ermittelt den Methodennamen <strong>der</strong> aufgerufenen Methode<br />
* @param methodInvocation Methodenaufruf<br />
* @return Methodenname<br />
*/<br />
private static String getMethodName(MethodInvocation<br />
methodInvocation) {<br />
return methodInvocation.getMethod().getName();<br />
}<br />
/**<br />
* ermittelt den Klassenname <strong>der</strong> aufgerufenen Methode<br />
* @param methodInvocation Methodenaufruf<br />
* @return Klassename<br />
*/<br />
private static String getClassName(MethodInvocation<br />
methodInvocation) {<br />
String result;<br />
Object target;<br />
target = methodInvocation.getThis();<br />
if (target == null) {<br />
result = "null";<br />
} else {<br />
result = target.getClass().getName();<br />
}<br />
return result;<br />
}<br />
/**<br />
* gibt Logginginformation zur Exception des Methodenaufrufes<br />
aus<br />
* @param log Logger<br />
* @param methodInvocation Methodenaufruf<br />
* @param id Aufrufid<br />
* @param startMillis Startzeit <strong>der</strong> Methode<br />
* @param endMillis Endzeit <strong>der</strong> Methode<br />
* @param throwable Exception<br />
*/<br />
private void logMethodException(Log log,<br />
MethodInvocation methodInvocation,<br />
long id, long startMillis, long endMillis,<br />
Throwable throwable) {<br />
if (log.isInfoEnabled()) {<br />
StringBuffer sb = new StringBuffer();<br />
sb.append("MethodInvocation " + id<br />
+ " EXCEPTION");<br />
25
Anhang B: Quellcode<br />
}<br />
}<br />
sb.append("\n Class : " +<br />
getClassName(methodInvocation));<br />
sb.append("\n Method : " +<br />
getMethodName(methodInvocation));<br />
sb.append("\n Arguments : " +<br />
getArguments(methodInvocation));<br />
sb.append("\n Start:" + startMillis<br />
+ " ms");<br />
sb.append("\n End:" + endMillis + " ms");<br />
sb.append("\n Duration : " +<br />
(endMillis - startMillis) + " ms");<br />
sb.append("\n Result : " + throwable);<br />
log.info(sb);<br />
/**<br />
* gibt Logginginformation zum Start des Methodenaufrufes aus<br />
* @param log Logger<br />
* @param methodInvocation Methodenaufruf<br />
* @param id Aufrufid<br />
* @param startMillis Startzeit <strong>der</strong> Methode<br />
* @param endMillis Endzeit <strong>der</strong> Methode<br />
*/<br />
private void logMethodStart(Log log, MethodInvocation<br />
methodInvocation, long id, long startMillis) {<br />
if (log.isInfoEnabled()) {<br />
StringBuffer sb = new StringBuffer();<br />
sb.append("MethodInvocation " + id<br />
+ " START");<br />
sb.append("\n Class : " +<br />
getClassName(methodInvocation));<br />
sb.append("\n Method : " +<br />
getMethodName(methodInvocation));<br />
sb.append("\n Arguments : " +<br />
getArguments(methodInvocation));<br />
sb.append("\n Start : " + startMillis<br />
+ " ms");<br />
log.info(sb);<br />
}<br />
}<br />
/**<br />
* gibt Logginginformation zum Ende des Methodenaufrufes aus<br />
* @param log Logger<br />
* @param methodInvocation Methodenaufruf<br />
* @param id Aufrufid<br />
* @param startMillis Startzeit <strong>der</strong> Methode<br />
* @param endMillis Endzeit <strong>der</strong> Methode<br />
* @param result Ergebnis des Methodenaufrufs<br />
*/<br />
private static void logMethodEnd(Log log,<br />
MethodInvocation methodInvocation, long id,<br />
long startMillis, long endMillis, Object result) {<br />
if (log.isInfoEnabled()) {<br />
StringBuffer sb = new StringBuffer();<br />
sb.append("MethodInvocation " + id<br />
+ " END");<br />
sb.append("\n Class : " +<br />
getClassName(methodInvocation));<br />
sb.append("\n Method : " +<br />
26
Anhang B: Quellcode<br />
}<br />
Book.java<br />
}<br />
package bib;<br />
/**<br />
* Klasse Buch<br />
* @author Birgit<br />
*<br />
*/<br />
public class Book{<br />
/**<br />
* BuchID<br />
*/<br />
protected int id;<br />
/**<br />
* Beschreibung/Titel des Buchs<br />
*/<br />
protected String description;<br />
/**<br />
* ISBN des Buchs<br />
*/<br />
protected String isbn;<br />
/**<br />
* Author des Buchs<br />
*/<br />
protected String autor;<br />
}<br />
}<br />
getMethodName(methodInvocation));<br />
sb.append("\n Arguments : " +<br />
getArguments(methodInvocation));<br />
sb.append("\n Start : " + startMillis<br />
+ " ms");<br />
sb.append("\n End:" + endMillis + " ms");<br />
sb.append("\n Duration : " +<br />
(endMillis - startMillis) + " ms");<br />
sb.append("\n Result : " + result);<br />
log.info(sb);<br />
public Book(String description, String isbn, String autor) {<br />
this.description = description;<br />
this.isbn = isbn;<br />
this.autor = autor;<br />
}<br />
public int getId(){return id;}<br />
public void setId(int id){<br />
this.id = id;<br />
}<br />
public String getDescription(){return description;}<br />
public void setDescription(String description){<br />
this.description = description;<br />
}<br />
public String getISBN(){return isbn;}<br />
public void setISBN(String nr){isbn = nr;}<br />
public String getAutor(){return autor;}<br />
public void setAutor(String a){autor = a;}<br />
27
Anhang B: Quellcode<br />
Exemplar.java<br />
package bib;<br />
/**<br />
* Klasse Exemplar (Exemplar eines Buches)<br />
* @author Birgit<br />
*<br />
*/<br />
public class Exemplar {<br />
/**<br />
* ID des Exemplars<br />
*/<br />
protected int id;<br />
/**<br />
* Buch, das zu dem Exemplar gehört<br />
*/<br />
protected Book book;<br />
/**<br />
* mögliche Ausleihe des Exemplars<br />
*/<br />
protected Lending lending;<br />
public Exemplar(int id, Book book) {<br />
super();<br />
this.id = id;<br />
this.book = book;<br />
}<br />
public int getId()<br />
{<br />
return id;<br />
}<br />
public void setId(int id)<br />
{<br />
this.id = id;<br />
}<br />
public Book getBook()<br />
{<br />
return book;<br />
}<br />
public void setBook(Book b)<br />
{<br />
book = b;<br />
}<br />
public Lending getLending()<br />
{<br />
return lending;<br />
}<br />
public void setLending(Lending l)<br />
{<br />
lending = l;<br />
}<br />
}<br />
Lending.java<br />
28
Anhang B: Quellcode<br />
package bib;<br />
import java.util.Date;<br />
/**<br />
* Klasse Ausleihe<br />
* @author Birgit<br />
*<br />
*/<br />
public class Lending {<br />
/**<br />
* ID <strong>der</strong> Ausleihe<br />
*/<br />
protected int id;<br />
/**<br />
* Startdatum <strong>der</strong> Ausleihe<br />
*/<br />
protected Date date;<br />
/**<br />
* Benutzer, des das Exemplar ausgeliehen hat<br />
*/<br />
protected User user;<br />
/**<br />
* Exemplar, das ausgeliehen wurde<br />
*/<br />
protected Exemplar exemplar;<br />
{<br />
}<br />
User.java<br />
public Lending(int id, Date date, User user, Exemplar exemplar)<br />
super();<br />
this.id = id;<br />
this.date = date;<br />
this.user = user;<br />
this.exemplar = exemplar;<br />
}<br />
public int getId(){return id;}<br />
public void setId(int id){this.id = id;}<br />
public Date getDate(){return date;}<br />
public void setDate(Date d){date = d;}<br />
public User getUser(){return user;}<br />
public void setUser(User u){<br />
user = u;<br />
}<br />
public Exemplar getExemplar(){return exemplar;}<br />
public void setExemplar(Exemplar e){<br />
exemplar = e;<br />
}<br />
package bib;<br />
import java.util.ArrayList;<br />
import java.util.Collection;<br />
/**<br />
* Klasse Benutzer<br />
29
Anhang B: Quellcode<br />
* @author Birgit<br />
*<br />
*/<br />
public class User {<br />
/**<br />
* BenutzerID<br />
*/<br />
protected int id;<br />
/**<br />
* Anmeldename/User<br />
*/<br />
protected String username;<br />
/**<br />
* Vorname<br />
*/<br />
protected String firstname;<br />
/**<br />
* Nachname<br />
*/<br />
protected String lastname;<br />
/**<br />
* Password<br />
*/<br />
protected String password;<br />
protected Collection lending =<br />
new ArrayList();<br />
public User (String firstname,String lastname){<br />
}<br />
this.firstname = firstname;<br />
this.lastname = lastname;<br />
public int getId(){return id;}<br />
public void setId(int id){this.id = id;}<br />
public String getFirstname(){return firstname;}<br />
public void setFirstname(String firstname){<br />
this.firstname = firstname;<br />
}<br />
public String getLastname(){return lastname;}<br />
public void setLastname(String lastname){<br />
this.lastname = lastname;<br />
}<br />
public Collection getLending(){return lending;}<br />
public void setLending(Collection coll){<br />
lending = coll;<br />
}<br />
public String getPassword() {<br />
return password;<br />
}<br />
public void setPassword(String password) {<br />
this.password = password;<br />
}<br />
30
Anhang B: Quellcode<br />
}<br />
IBookDAO.java<br />
package dao;<br />
import java.util.List;<br />
public String getUsername() {<br />
return username;<br />
}<br />
public void setUsername(String username) {<br />
this.username = username;<br />
}<br />
import bib.Book;<br />
/**<br />
* Schnittstelle <strong>für</strong> DAO <strong>für</strong> Bücher<br />
* @author Birgit<br />
*<br />
*/<br />
public interface IBookDAO {<br />
}<br />
/**<br />
* gibt Liste aller Bücher zurück<br />
* @return Bücherliste<br />
*/<br />
List getAll();<br />
/**<br />
* gibt alle Bücher zur eingegeben Beschreibung zurück<br />
* @param description Beschreibung<br />
* @return Bücherliste<br />
*/<br />
List getByDescription(String description);<br />
/**<br />
* speichert das eingegebene Buch<br />
* @param book Buch<br />
* @return gespeicherte Buch<br />
*/<br />
Book save(Book book);<br />
/**<br />
* löscht alle Bücher zur eingegeben Beschreibung<br />
* @param description Beschreibung<br />
*/<br />
void deleteByDescription(String description);<br />
/**<br />
* gibt ein Buch zur eingegebenen ID zurück<br />
* @param id<br />
* @return Buch<br />
*/<br />
Book getByID(int id);<br />
/**<br />
* löscht das Bücher zur eingegeben ID<br />
* @param id<br />
*/<br />
void deleteByID(int id);<br />
/**<br />
* än<strong>der</strong>t das eingegebene Buch<br />
* @param book Buch<br />
*/<br />
void update(Book book);<br />
31
Anhang B: Quellcode<br />
IExemplarDAO.java<br />
package dao;<br />
import java.util.List;<br />
import bib.Exemplar;<br />
/**<br />
* Schnittstelle <strong>für</strong> DAO Exemplar<br />
* @author Birgit<br />
*<br />
*/<br />
public interface IExemplarDAO {<br />
/**<br />
* gibt Exemplare zur BuchID zurück<br />
* @param bookid BuchID<br />
* @return Exemplarliste<br />
*/<br />
List getByBook(String bookid);<br />
/**<br />
* speichert ein Exemplar<br />
* @param exemplar Exemplar<br />
* @return gespeichertes Exemplar<br />
*/<br />
Exemplar save(Exemplar exemplar);<br />
}<br />
ILendingDAO.java<br />
package dao;<br />
/**<br />
* gibt zur ID Exemplar zurück<br />
* @param id<br />
* @return Exemplar<br />
*/<br />
Exemplar getByID(int id);<br />
/**<br />
* löscht Exemplar zur ID<br />
* @param id<br />
*/<br />
void deleteByID(int id);<br />
/**<br />
* än<strong>der</strong>t ein Exemplar<br />
* @param exemplar Exemplar<br />
*/<br />
void update(Exemplar exemplar);<br />
import java.util.List;<br />
import bib.Lending;<br />
/**<br />
* Schnittstelle <strong>für</strong> DAO Ausleihe<br />
* @author Birgit<br />
*<br />
*/<br />
public interface ILendingDAO {<br />
/**<br />
* speichert eine Ausleihe<br />
* @param lending Ausleihe<br />
* @return gespeicherte Ausleihe<br />
32
Anhang B: Quellcode<br />
}<br />
*/<br />
public Lending save(Lending lending);<br />
/**<br />
* gibt Ausleihen zu einer Benutzerid zurück<br />
* @param userid Benutzerid<br />
* @return Ausleihenliste<br />
*/<br />
public List getByUserID(int userid);<br />
/**<br />
* gibt alle Ausleihen zurück<br />
* @return Ausleihenliste<br />
*/<br />
public List getAll();<br />
IUserDAO.java<br />
package dao;<br />
import java.util.List;<br />
import bib.User;<br />
/**<br />
* Schnittstelle DAO Benutzer<br />
* @author Birgit<br />
*<br />
*/<br />
public interface IUserDAO {<br />
/**<br />
* gibt den Benutzer zum Anmeldenamen zurück<br />
* @param username Anmeldename<br />
* @return Benutzer<br />
*/<br />
User getByName(String username);<br />
/**<br />
* speichert einen Benutzer<br />
* @param user Benutzer<br />
* @return gespeicherter Benutzer<br />
*/<br />
User save(User user);<br />
/**<br />
* löscht einen Benutzer zum Anmeldenamen<br />
* @param name Anmeldename<br />
*/<br />
void deleteByName(String name);<br />
/**<br />
* gibt einen Benutzer zur ID zurück<br />
* @param id<br />
* @return Benutzer<br />
*/<br />
User getByID(int id);<br />
/**<br />
* löscht eine Benutzer zur ID<br />
* @param id<br />
*/<br />
void deleteByID(int id);<br />
/**<br />
* gibt alle Benutzer zurück<br />
* @return Benutzerliste<br />
*/<br />
List getAll();<br />
}<br />
33
Anhang B: Quellcode<br />
bookDAO.java<br />
package jdbc;<br />
import java.sql.ResultSet;<br />
import java.sql.SQLException;<br />
import java.util.List;<br />
import javax.sql.DataSource;<br />
import org.springframework.dao.EmptyResultDataAccessException;<br />
import org.springframework.jdbc.core.RowMapper;<br />
import<br />
org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSourc<br />
e;<br />
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;<br />
import<br />
org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;<br />
import bib.Book;<br />
import dao.IBookDAO;<br />
/**<br />
* DAO <strong>für</strong> Bücher<br />
* @author Birgit<br />
*<br />
*/<br />
public class BookDAO extends NamedParameterJdbcDaoSupport implements<br />
IBookDAO {<br />
/**<br />
* innere Klasse die eine RowMapper <strong>für</strong> Bücher zur Verfügung<br />
stellt<br />
*<br />
*/<br />
private static final class BookRowMapper implements RowMapper {<br />
/**<br />
* Methode zu Mappen von Bücher<br />
* @param rs Ergebnis <strong>der</strong> SQL-Abfrage<br />
* @param rowNum Anzahl Zeilen<br />
* @return Buchobjekt<br />
*/<br />
public Object mapRow(ResultSet rs, int rowNum) throws<br />
SQLException {<br />
Book Book = new<br />
Book(rs.getString(1),rs.getString(2),rs.getString(3));<br />
Book.setId(rs.getInt(4));<br />
return Book;<br />
}<br />
}<br />
public BookDAO(){<br />
}<br />
/**<br />
* Konstruktor<br />
* @param dataSource Datenquelle<br />
*/<br />
public BookDAO(DataSource dataSource) {<br />
setDataSource(dataSource);<br />
}<br />
/**<br />
* gibt alle Bücher zur eingegeben Beschreibung zurück<br />
* @param description Beschreibung<br />
* @return Bücherliste<br />
34
Anhang B: Quellcode<br />
*/<br />
public List getByDescription(String description) {<br />
MapSqlParameterSource params = new MapSqlParameterSource();<br />
params.addValue("description", description);<br />
return getNamedParameterJdbcTemplate()<br />
.query(<br />
"SELECT DESCRIPTION, ISBN, AUTOR, ID FROM Book<br />
WHERE DESCRIPTION=:description",<br />
params, new BookRowMapper());<br />
}<br />
/**<br />
* gibt ein Buch zur eingegebenen ID zurück<br />
* @param id<br />
* @return Buch<br />
*/<br />
public Book getByID(int id) {<br />
return (Book) getNamedParameterJdbcTemplate().<br />
queryForObject(<br />
"SELECT DESCRIPTION, ISBN, AUTOR, ID FROM Book<br />
WHERE ID=:id",<br />
new MapSqlParameterSource("id", id), new<br />
BookRowMapper());<br />
}<br />
/**<br />
* speichert das eingegebene Buch<br />
* @param book Buch<br />
* @return gespeicherte Buch<br />
*/<br />
public Book save(Book Book) {<br />
initTemplateConfig();<br />
getNamedParameterJdbcTemplate().update(<br />
"INSERT INTO Book (DESCRIPTION, ISBN, AUTOR)<br />
VALUES(:description, :isbn, :autor)",<br />
new BeanPropertySqlParameterSource(Book));<br />
return Book;<br />
}<br />
/**<br />
* löscht alle Bücher zur eingegeben Beschreibung<br />
* @param description Beschreibung<br />
*/<br />
public void deleteByDescription(String description) {<br />
getNamedParameterJdbcTemplate().update(<br />
"DELETE FROM Book WHERE DESCRIPTION=:description",<br />
new MapSqlParameterSource("description",<br />
description));<br />
}<br />
/**<br />
* löscht das Bücher zur eingegeben ID<br />
* @param id<br />
*/<br />
public void deleteByID(int id) {<br />
getNamedParameterJdbcTemplate().update("DELETE FROM Book WHERE<br />
ID=:id",<br />
new MapSqlParameterSource("id", id));<br />
}<br />
/**<br />
* än<strong>der</strong>t das eingegebene Buch<br />
* @param book Buch<br />
*/<br />
public void update(Book Book) {<br />
getNamedParameterJdbcTemplate()<br />
35
Anhang B: Quellcode<br />
}<br />
.update(<br />
"UPDATE Book SET<br />
DESCRIPTION=:description,ISBN=:isbn,AUTOR=:autor<br />
WHERE ID=:id",<br />
new BeanPropertySqlParameterSource(Book));<br />
}<br />
/**<br />
* gibt Liste aller Bücher zurück<br />
* @return Bücherliste<br />
*/<br />
public List getAll() {<br />
return (List) getJdbcTemplate().query(<br />
"SELECT DESCRIPTION, ISBN, AUTOR, ID FROM Book ",<br />
new BookRowMapper());<br />
}<br />
ExemplarDAO.java<br />
package jdbc;<br />
import java.sql.ResultSet;<br />
import java.sql.SQLException;<br />
import java.util.List;<br />
import javax.sql.DataSource;<br />
import org.springframework.jdbc.core.RowMapper;<br />
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;<br />
import<br />
org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;<br />
import bib.Book;<br />
import bib.Exemplar;<br />
import dao.IBookDAO;<br />
/**<br />
* Klasse <strong>für</strong> DAO Exemplar<br />
* @author Birgit<br />
*<br />
*/<br />
public class ExemplarDAO extends NamedParameterJdbcDaoSupport<br />
implements dao.IExemplarDAO{<br />
/**<br />
* BuchDAO<br />
*/<br />
private static IBookDAO bookDAO;<br />
/**<br />
*<br />
* innere Klasse, die einen RowMapper <strong>für</strong> Exemplar zur Verfügung<br />
stellt<br />
*<br />
*/<br />
private static final class ExemplarRowMapper implements<br />
RowMapper {<br />
/**<br />
* Methode zu mappen einer SQL Abfrage auf Exemplar-Objekte<br />
* @param rs Ergebnis <strong>der</strong> SQL-Abfrage<br />
* @param rowNum Anzahl Zeilen<br />
* @return Exemplarobjekt<br />
*/<br />
public Object mapRow(ResultSet rs, int rowNum) throws<br />
36
Anhang B: Quellcode<br />
}<br />
}<br />
SQLException {<br />
Book book = bookDAO.getByID(rs.getInt(2));<br />
Exemplar exemplar = new Exemplar(rs.getInt(1),book);<br />
return exemplar;<br />
public ExemplarDAO() {<br />
}<br />
/**<br />
* Konstruktor<br />
* @param dataSource Datenquelle<br />
*/<br />
public ExemplarDAO(DataSource dataSource) {<br />
setDataSource(dataSource);<br />
}<br />
/**<br />
* gibt Exemplare zur BuchID zurück<br />
* @param bookid BuchID<br />
* @return Exemplarliste<br />
*/<br />
public List getByBook(String bookid){<br />
MapSqlParameterSource params = new<br />
MapSqlParameterSource();<br />
params.addValue("bookid", bookid);<br />
return getNamedParameterJdbcTemplate()<br />
.query( "SELECT ID, BOOKID FROM Exemplar WHERE<br />
BOOKID=:bookid",<br />
params, new ExemplarRowMapper());<br />
}<br />
/**<br />
* speichert ein Exemplar<br />
* @param exemplar Exemplar<br />
* @return gespeichertes Exemplar<br />
*/<br />
public Exemplar save(Exemplar exemplar){<br />
initTemplateConfig();<br />
getJdbcTemplate()<br />
.update(<br />
"INSERT INTO Exemplar (ID, BOOKID)<br />
VALUES(?, ?)",<br />
new Object[] {exemplar.getId(),<br />
exemplar.getBook().getId()});<br />
return exemplar;<br />
}<br />
/**<br />
* gibt zur ID Exemplar zurück<br />
* @param id<br />
* @return Exemplar<br />
*/<br />
public Exemplar getByID(int id){<br />
return (Exemplar) getNamedParameterJdbcTemplate().<br />
queryForObject(<br />
"SELECT ID, BOOKID FROM Exemplar WHERE ID=:id",<br />
new MapSqlParameterSource("id", id), new<br />
ExemplarRowMapper());<br />
}<br />
/**<br />
* löscht Exemplar zur ID<br />
* @param id<br />
37
Anhang B: Quellcode<br />
}<br />
*/<br />
public void deleteByID(int id){<br />
getNamedParameterJdbcTemplate().update("DELETE FROM<br />
Exemplar WHERE ID=:id",<br />
new MapSqlParameterSource("id", id));<br />
}<br />
/**<br />
* än<strong>der</strong>t ein Exemplar<br />
* @param exemplar Exemplar<br />
*/<br />
public void update(Exemplar exemplar){<br />
getJdbcTemplate()<br />
.update(<br />
"UPDATE Exemplar SET ID=?,BOOKID=? WHERE ID=?",<br />
new Object[] {exemplar.getId(),<br />
exemplar.getBook().getId()});<br />
}<br />
public IBookDAO getBookDAO() {<br />
return bookDAO;<br />
}<br />
public void setBookDAO(IBookDAO bookDAO) {<br />
this.bookDAO = bookDAO;<br />
}<br />
LendingDAO.java<br />
package jdbc;<br />
import java.sql.ResultSet;<br />
import java.sql.SQLException;<br />
import java.util.List;<br />
import javax.sql.DataSource;<br />
import org.springframework.jdbc.core.RowMapper;<br />
import org.springframework.jdbc.core.SqlParameter;<br />
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;<br />
import<br />
org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;<br />
import bib.User;<br />
import bib.Exemplar;<br />
import bib.Lending;<br />
import dao.IExemplarDAO;<br />
import dao.IUserDAO;<br />
/**<br />
* Klasse <strong>für</strong> DAO Ausleihe<br />
* @author Birgit<br />
*<br />
*/<br />
public class LendingDAO extends NamedParameterJdbcDaoSupport<br />
implements dao.ILendingDAO {<br />
/**<br />
* Exemplar DAO<br />
38
Anhang B: Quellcode<br />
{<br />
}<br />
*/<br />
private static IExemplarDAO exemplarDAO;<br />
/**<br />
* Benutzer DAO;<br />
*/<br />
private static IUserDAO userDAO;<br />
/**<br />
* innere Klasse, die RowMapper <strong>für</strong> Ausleihen zur Verfügung stellt<br />
*<br />
*/<br />
private static final class LendingRowMapper implements RowMapper<br />
}<br />
/**<br />
* Methode zum Mappen von SQL-Ergebnis auf AusleihObjekte<br />
* @param rs Ergebnis <strong>der</strong> SQL-Abfrage<br />
* @param rowNum Anzahl Zeilen<br />
* @return Ausleihobjekt<br />
*/<br />
public Object mapRow(ResultSet rs, int rowNum) throws<br />
SQLException {<br />
User user = userDAO.getByID(rs.getInt(3));<br />
Exemplar exemplar = exemplarDAO.getByID(rs.getInt(4));<br />
Lending lending = new Lending(rs.getInt(1),rs.getDate(2),<br />
user, exemplar);<br />
return lending;<br />
}<br />
public LendingDAO() {<br />
super();<br />
public LendingDAO(DataSource dataSource, IExemplarDAO<br />
exemplarDAO, IUserDAO userDAO) {<br />
setDataSource(dataSource);<br />
this.exemplarDAO = exemplarDAO;<br />
this.userDAO = userDAO;<br />
}<br />
/**<br />
* speichert eine Ausleihe<br />
* @param lending Ausleihe<br />
* @return gespeicherte Ausleihe<br />
*/<br />
public Lending save(Lending lending) {<br />
initTemplateConfig();<br />
getJdbcTemplate()<br />
.update(<br />
"INSERT INTO Lending (ID, DATE, USERID,<br />
EXEMPLARID) VALUES(?, ?, ?, ?)",<br />
new Object[] {lending.getId(),<br />
lending.getDate(), lending.getUser().getId(),<br />
lending.getExemplar().getId()});<br />
return lending;<br />
}<br />
/**<br />
* gibt Ausleihen zu einer Benutzerid zurück<br />
39
Anhang B: Quellcode<br />
}<br />
UserDAO.java<br />
package jdbc;<br />
* @param userid Benutzerid<br />
* @return Ausleihenliste<br />
*/<br />
public List getByUserID(int userid) {<br />
MapSqlParameterSource params = new<br />
MapSqlParameterSource();<br />
params.addValue("userid", userid);<br />
return getNamedParameterJdbcTemplate()<br />
.query(<br />
"SELECT ID, DATE, USERID, EXEMPLARID<br />
FROM Lending WHERE USERID=:userid",<br />
params, new LendingRowMapper());<br />
}<br />
/**<br />
* gibt alle Ausleihen zurück<br />
* @return Ausleihenliste<br />
*/<br />
public List getAll() {<br />
MapSqlParameterSource params = new<br />
MapSqlParameterSource();<br />
return getNamedParameterJdbcTemplate()<br />
.query(<br />
"SELECT ID, DATE, USERID, EXEMPLARID<br />
FROM Lending",<br />
params, new LendingRowMapper());<br />
}<br />
public IExemplarDAO getExemplarDAO() {<br />
return exemplarDAO;<br />
}<br />
public void setExemplarDAO(IExemplarDAO exemplarDAO) {<br />
this.exemplarDAO = exemplarDAO;<br />
}<br />
public IUserDAO getUserDAO() {<br />
return userDAO;<br />
}<br />
public void setUserDAO(IUserDAO userDAO) {<br />
this.userDAO = userDAO;<br />
}<br />
import java.sql.ResultSet;<br />
import java.sql.SQLException;<br />
import java.util.HashMap;<br />
import java.util.List;<br />
import java.util.Map;<br />
import javax.sql.DataSource;<br />
import org.springframework.jdbc.core.RowMapper;<br />
import<br />
org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;<br />
40
Anhang B: Quellcode<br />
import bib.User;<br />
import dao.IUserDAO;<br />
/**<br />
* Klasse <strong>für</strong> DAO Benutzer<br />
* @author Birgit<br />
*<br />
*/<br />
public class UserDAO extends NamedParameterJdbcDaoSupport implements<br />
IUserDAO{<br />
/**<br />
* innere Klasse, die RowMapper <strong>für</strong> Benutzer zur Verfügung stellt<br />
*<br />
*/<br />
private static final class UserResultSetRowMapper implements<br />
RowMapper {<br />
/**<br />
* Methode zum Mappen von SQL-Ergebnis auf BenutzerObjekte<br />
* @param rs Ergebnis <strong>der</strong> SQL-Abfrage<br />
* @param rowNum Anzahl Zeilen<br />
* @return Benutzerobjekt<br />
*/<br />
public Object mapRow(ResultSet rs, int rowNum) throws<br />
SQLException {<br />
User user = new User( rs.getString(3),rs.getString(4));<br />
user.setId(rs.getInt(1));<br />
user.setUsername(rs.getString(2));<br />
return user;<br />
}<br />
}<br />
}<br />
public UserDAO() {<br />
super();<br />
public UserDAO(DataSource dataSource) {<br />
setDataSource(dataSource);<br />
}<br />
/**<br />
* löscht eine Benutzer zur ID<br />
* @param id<br />
*/<br />
public void deleteByID(int id) {<br />
Map parameters = new HashMap();<br />
parameters.put("id", id);<br />
getNamedParameterJdbcTemplate().update<br />
("DELETE FROM USER WHERE ID=?",<br />
parameters);<br />
}<br />
/**<br />
* gibt einen Benutzer zur ID zurück<br />
* @param id<br />
* @return Benutzer<br />
*/<br />
public User getByID(int id) {<br />
Map parameters = new HashMap();<br />
parameters.put("ID", id);<br />
return (User) getNamedParameterJdbcTemplate().queryForObject(<br />
"SELECT * FROM USER WHERE ID = (:ID)" ,<br />
parameters<br />
41
Anhang B: Quellcode<br />
}<br />
, new UserResultSetRowMapper());<br />
}<br />
/**<br />
* gibt den Benutzer zum Anmeldenamen zurück<br />
* @param username Anmeldename<br />
* @return Benutzer<br />
*/<br />
public User getByName(String username) {<br />
Map parameters = new HashMap();<br />
parameters.put("USERNAME", username);<br />
return (User) getNamedParameterJdbcTemplate()<br />
.queryForObject(<br />
"SELECT * FROM USER WHERE USERNAME=<br />
(:USERNAME)",<br />
parameters, new UserResultSetRowMapper());<br />
}<br />
/**<br />
* löscht einen Benutzer zum Anmeldenamen<br />
* @param name Anmeldename<br />
*/<br />
public void deleteByName(String name) {<br />
getJdbcTemplate().update("DELETE FROM USER WHERE USERNAME=?",<br />
new Object[] { name });<br />
}<br />
/**<br />
* speichert einen Benutzer<br />
* @param user Benutzer<br />
* @return gespeicherter Benutzer<br />
*/<br />
public User save(User user) {<br />
Map parameters = new HashMap();<br />
parameters.put("firstname", user.getFirstname());<br />
parameters.put("lastname", user.getLastname());<br />
parameters.put("username", user.getUsername());<br />
parameters.put("password", user.getPassword());<br />
getNamedParameterJdbcTemplate().update(<br />
"INSERT INTO<br />
USER(FIRSTNAME,LASTNAME,USERNAME,PASSWORD) " +<br />
"VALUES(:firstname,:lastname,:username,:password)",<br />
parameters);<br />
return user;<br />
}<br />
/**<br />
* gibt alle Benutzer zurück<br />
* @return Benutzerliste<br />
*/<br />
public List getAll() {<br />
List result = (List) getJdbcTemplate().query(<br />
"SELECT * FROM USER",<br />
new Object[] {}, new UserResultSetRowMapper());<br />
return result;<br />
}<br />
42
Anhang B: Quellcode<br />
BookController.java<br />
package mvc;<br />
import services.BookService;<br />
import java.util.HashMap;<br />
import java.util.Map;<br />
import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
import org.springframework.web.servlet.ModelAndView;<br />
import org.springframework.web.servlet.mvc.AbstractController;<br />
/**<br />
* Controller, <strong>der</strong> das Modell und die View zu einer Bücheranfrage<br />
zurückgibt<br />
* @author Birgit<br />
*<br />
*/<br />
public class BookController extends AbstractController{<br />
/**<br />
* Verweis auf Bücherservice<br />
*/<br />
private BookService bookService;<br />
/**<br />
* Viewname<br />
*/<br />
private String view = "booklist";<br />
}<br />
public BookService getBookService() {<br />
return bookService;<br />
}<br />
public void setBookService(BookService bookService) {<br />
this.bookService = bookService;<br />
}<br />
/**<br />
* gibt das Modell und die View zu einer Bücheranfrage<br />
zurückgibt<br />
* @param request HttpRequest<br />
* @param response HTTP Response<br />
*/<br />
protected ModelAndView handleRequestInternal(HttpServletRequest<br />
request, HttpServletResponse response) throws Exception {<br />
}<br />
LendingController.java<br />
package mvc;<br />
Map model = new HashMap();<br />
model.put("books", bookService.getBooks());<br />
return new ModelAndView(view,model);<br />
import java.util.HashMap;<br />
import java.util.Map;<br />
43
Anhang B: Quellcode<br />
import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
import org.springframework.security.context.SecurityContextHol<strong>der</strong>;<br />
import org.springframework.web.servlet.ModelAndView;<br />
import org.springframework.web.servlet.mvc.AbstractController;<br />
import services.LendingService;<br />
/**<br />
* Controller, <strong>der</strong> das Modell und die View zu einer Ausleihanfrage<br />
zurückgibt<br />
* @author Birgit<br />
*<br />
*/<br />
public class LendingController extends AbstractController{<br />
/**<br />
* Viewname<br />
*/<br />
private String view = "lendinglist";<br />
/**<br />
* Service Ausleihe<br />
*/<br />
private LendingService lendingService;<br />
/**<br />
* gibt das Modell und die View zu einer Anfrage zurückgibt<br />
* @param request HttpRequest<br />
* @param response HTTP Response<br />
*/<br />
protected ModelAndView<br />
handleRequestInternal(HttpServletRequest request,<br />
HttpServletResponse response) throws Exception {<br />
}<br />
String user = (String)<br />
SecurityContextHol<strong>der</strong>.getContext().<br />
getAuthentication().getName();<br />
Map model = new HashMap();<br />
model.put("lendings",<br />
lendingService.getLendings(user));<br />
return new ModelAndView(view,model);<br />
}<br />
public LendingService getLendingService() {<br />
return lendingService;<br />
}<br />
public void setLendingService(LendingService lendingService) {<br />
this.lendingService = lendingService;<br />
}<br />
LoginController.java<br />
package mvc;<br />
import java.util.HashMap;<br />
import java.util.Map;<br />
import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
44
Anhang B: Quellcode<br />
import org.springframework.web.servlet.ModelAndView;<br />
import org.springframework.web.servlet.mvc.AbstractController;<br />
/**<br />
* Controller, <strong>der</strong> das Modell und die View zu einer LoginAnfrage<br />
zurückgibt<br />
* @author Birgit<br />
*<br />
*/<br />
public class LoginController extends AbstractController{<br />
/**<br />
* gibt die View zu einer LoginAnfrage zurückgibt<br />
* @param request HttpRequest<br />
* @param response HTTP Response<br />
*/<br />
protected ModelAndView handleRequestInternal(HttpServletRequest<br />
request,HttpServletResponse response) throws Exception {<br />
return new ModelAndView("login");<br />
}<br />
}<br />
StartController.java<br />
package mvc;<br />
import java.util.HashMap;<br />
import java.util.Map;<br />
import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
import org.springframework.security.Authentication;<br />
import org.springframework.security.context.SecurityContextHol<strong>der</strong>;<br />
import org.springframework.web.servlet.ModelAndView;<br />
import org.springframework.web.servlet.mvc.AbstractController;<br />
import services.UserService;<br />
/**<br />
* Controller, <strong>der</strong> das Modell und die View zu einer Anfrage zurückgibt<br />
* @author Birgit<br />
*<br />
*/<br />
public class StartController extends AbstractController{<br />
/**<br />
* gibt das Modell und die View zu einer Anfrage zurückgibt<br />
* @param request HttpRequest<br />
* @param response HTTP Response<br />
*/<br />
protected ModelAndView handleRequestInternal(HttpServletRequest<br />
request, HttpServletResponse response) throws Exception {<br />
Authentication auth =<br />
SecurityContextHol<strong>der</strong>.getContext().getAuthentication();<br />
if(SecurityContextHol<strong>der</strong>.getContext()<br />
.getAuthentication().getName().toString().<br />
equals("anonymousUser")<br />
|| ! (auth.isAuthenticated()))<br />
return new ModelAndView("login");<br />
for (int i= 0; i
Anhang B: Quellcode<br />
}<br />
}<br />
Usercontroller.java<br />
package mvc;<br />
import java.util.HashMap;<br />
import java.util.Map;<br />
return new ModelAndView("admin/user");<br />
}<br />
}<br />
return new ModelAndView("start");<br />
import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
import org.springframework.web.servlet.ModelAndView;<br />
import org.springframework.web.servlet.mvc.AbstractController;<br />
import services.UserService;<br />
/**<br />
* Controller gibt das Modell und die View zu einer Anfrage<br />
zurückgibt<br />
* @author Birgit<br />
*<br />
*/<br />
public class UserController extends AbstractController{<br />
/**<br />
* Viewname<br />
*/<br />
private String view = "admin/userlist";<br />
/**<br />
* Service User<br />
*/<br />
private UserService userService;<br />
/**<br />
* gibt das Modell und die View zu einer Anfrage zurückgibt<br />
* @param request HttpRequest<br />
* @param response HTTP Response<br />
*/<br />
protected ModelAndView<br />
handleRequestInternal(HttpServletRequest request,<br />
HttpServletResponse response) throws Exception {<br />
Map model = new HashMap();<br />
model.put("users", userService.getUsers());<br />
return new ModelAndView(view,model);<br />
}<br />
}<br />
public UserService getUserService() {<br />
return userService;<br />
}<br />
public void setUserService(UserService userService) {<br />
this.userService = userService;<br />
}<br />
BookService.java<br />
package services;<br />
46
Anhang B: Quellcode<br />
import java.util.List;<br />
import dao.IBookDAO;<br />
/**<br />
* Serivceschicht Book<br />
* @author Birgit<br />
*<br />
*/<br />
public class BookService {<br />
/**<br />
* DAO Book<br />
*/<br />
private IBookDAO bookDAO;<br />
/**<br />
* gibt alle Bücher zurück<br />
* @return Bücherliste<br />
*/<br />
public List getBooks(){<br />
return bookDAO.getAll();<br />
}<br />
public IBookDAO getBookDAO() {<br />
return bookDAO;<br />
}<br />
public void setBookDAO(IBookDAO bookDAO) {<br />
this.bookDAO = bookDAO;<br />
}<br />
}<br />
LendingService.java<br />
package services;<br />
import java.util.List;<br />
import dao.ILendingDAO;<br />
import dao.IUserDAO;<br />
import bib.Lending;<br />
import bib.User;<br />
/**<br />
* Serviceschicht Lending<br />
* @author Birgit<br />
*<br />
*/<br />
public class LendingService {<br />
/**<br />
* DAO Lending<br />
*/<br />
private ILendingDAO lendingDAO;<br />
/**<br />
* DAO User<br />
*/<br />
private IUserDAO userDAO;<br />
/**<br />
* gibt alle Ausleihen eines Benutzers zurück<br />
* @param username Benutzername<br />
* @return Ausleihliste<br />
*/<br />
public List getLendings(String username){<br />
User user = (User) userDAO.getByName(username);<br />
47
Anhang B: Quellcode<br />
}<br />
}<br />
int userid = user.getId();<br />
return lendingDAO.getByUserID(userid);<br />
public ILendingDAO getLendingDAO() {<br />
return lendingDAO;<br />
}<br />
public void setLendingDAO(ILendingDAO lendingDAO) {<br />
this.lendingDAO = lendingDAO;<br />
}<br />
public IUserDAO getUserDAO() {<br />
return userDAO;<br />
}<br />
public void setUserDAO(IUserDAO userDAO) {<br />
this.userDAO = userDAO;<br />
}<br />
UserService.java<br />
package services;<br />
import java.util.List;<br />
import bib.User;<br />
import dao.IUserDAO;<br />
/**<br />
* Serviceschicht User<br />
* @author Birgit<br />
*<br />
*/<br />
public class UserService {<br />
/**<br />
* User DAO<br />
*/<br />
private IUserDAO userDAO;<br />
/**<br />
* gibt alle Benutzer zurück<br />
* @return Benutzerliste<br />
*/<br />
public List getUsers(){<br />
return userDAO.getAll();<br />
}<br />
/**<br />
* legt einen Benutzer in <strong>der</strong> DB an<br />
* @param user Benutzer<br />
*/<br />
public void createUser(User user) {<br />
userDAO.save(user);<br />
}<br />
public IUserDAO getUserDAO() {<br />
return userDAO;<br />
}<br />
public void setUserDAO(IUserDAO userDAO) {<br />
this.userDAO = userDAO;<br />
48
Anhang B: Quellcode<br />
}<br />
}<br />
applicationContext.xml<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
49
Anhang B: Quellcode<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
SELECT USERNAME, PASSWORD, ENABLE as enabled<br />
FROM USER<br />
WHERE USERNAME = ?<br />
<br />
<br />
50
Anhang B: Quellcode<br />
<br />
<br />
SELECT u.USERNAME , a.AUTORITY as authority<br />
FROM AUTORITY a , USER u<br />
WHERE a.USERNAME = u.USERNAME<br />
AND u.USERNAME = ?<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
CONVERT_TO_LOWERCASE_BEFORE_COMPARISON<br />
PATTERN_TYPE_APACHE_ANT<br />
/book.htm=ROLE_USER<br />
/lending.htm=ROLE_USER<br />
/admin/user.htm=ROLE_ADMIN<br />
<br />
51
Anhang B: Quellcode<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON<br />
PATTERN_TYPE_APACHE_ANT<br />
/**=httpSessionContextIntegrationFilter,logoutFilter,<br />
authenticationProcessingFilter,exceptionTranslationFilter,<br />
filterSecurityInterceptor<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Anhang B: Quellcode<br />
logout.SecurityContextLogoutHandler"/><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
services.BookService.getBooks=ROLE_USER<br />
services.LendingService.getLendings=ROLE_USER<br />
services.UserService.getUsers=ROLE_ADMIN<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
securityInterceptor<br />
loggingInterceptor<br />
<br />
<br />
<br />
<br />
bookService<br />
lendingService<br />
userService<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
53
Anhang B: Quellcode<br />
springapp-servlet.xml<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
web.xml<br />
<br />
<br />
<br />
<br />
org.springframework.web.context.<br />
54
Anhang B: Quellcode<br />
ContextLoa<strong>der</strong>Listener<br />
<br />
<br />
<br />
filterChainProxy<br />
org.springframework.security.util.<br />
FilterToBeanProxy<br />
<br />
targetClass<br />
org.springframework.security.<br />
util.FilterChainProxy<br />
<br />
<br />
<br />
filterChainProxy<br />
/*<br />
<br />
SpringApp<br />
<br />
index.html<br />
index.htm<br />
index.jsp<br />
<br />
<br />
springapp<br />
org.springframework.web.servlet.<br />
DispatcherServlet<br />
1<br />
<br />
<br />
springapp<br />
*.htm<br />
<br />
<br />
index.jsp<br />
<br />
<br />
<br />
start.jsp<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Bibliothek<br />
<br />
55
Anhang B: Quellcode<br />
<br />
<br />
Willkommen <br />
auf <strong>der</strong> Webseite <strong>der</strong> Bibliothek!<br />
<br />
Was möchten Sie tun?<br />
Bücherliste einsehen<br />
aktuelle Ausleihen<br />
Logout<br />
<br />
<br />
<br />
login.jsp<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Bibliothek: Anmeldung<br />
<br />
<br />
<br />
Willkommen <strong>der</strong> Webseite <strong>der</strong> Bibliothek!<br />
<br />
Sie müssen sich anmelden bevor Sie unseren Service<br />
in Anspruch nehmen können.<br />
<br />
Benutzer: <br />
Password: <br />
<br />
<br />
<br />
<br />
<br />
lending.jsp<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Ausleihen<br />
<br />
56
Anhang B: Quellcode<br />
<br />
Willkommen: <br />
Hier sehen Sie alle von Ihnen ausgeliehenen Bücher<br />
<br />
<br />
DatumBenutzerExemplar<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
booklist.jsp<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Bücherliste<br />
<br />
<br />
<br />
Willkommen: <br />
Hier sehen Sie alle verfügbaren Bücher<br />
<br />
<br />
BuchAutor<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
user.jsp<br />
<br />
<br />
57
Anhang B: Quellcode<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Bibliothek: Userverwaltung<br />
<br />
<br />
<br />
Willkommen: <br />
Was möchten Sie tun?<br />
Benutzerliste einsehen<br />
Logout<br />
<br />
<br />
<br />
userlist.jsp<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Bibliothek: Benutzer<br />
<br />
<br />
<br />
Willkommen: <br />
Hier sehen Sie eine Liste aller Benutzer<br />
<br />
<br />
IDUsernameVorname<br />
Nachname<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
58
Anhang B: Quellcode<br />
<br />
<br />
<br />
<br />
59
Literaturverzeichnis<br />
[FaSc97] Fayad, Mohamed E.; Schmidt, Douglas C.: Object-Oriented Application<br />
Frameworks. ACM, 40, S. 32-38, ACM, 1997.<br />
[Fo04] Fowler, Martin: Inversion of Control Containers and the Dependency<br />
Injection Pattern. http://martinfowler.com/articles/injection.html.<br />
Abrufdatum: 28.09.2008.<br />
[GHJV04] Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John:<br />
Entwurfsmuster - Elemente wie<strong>der</strong>verwendbarer objektorientierter<br />
Software. Addison Wesley Verlag, 2004.<br />
[Wa08] Walls, Craig: Spring im Einsatz. Hanser Verlag, 2008.<br />
[Wo07] Wolff, Eberhard: Spring 2. dpunkt, 2007.