Spring mit einer einfachen Webanwendung (Tutorial)

Dieser Beitrag ist Teil einer (Tutorial-) Serie über die Einführung in das Spring Framework und beschreibt das Erstellen einer einfachen Webanwendung mit dem Spring Framework.

Die Struktur des Projektes

In diesem Beispiel wird eine Webanwendung mit Spring Framework MVC erstellt. Die verwendeten Frameworks und Werkzeuge sind hier beschrieben. Es werden die folgenden Technologien des Spring Frameworks vorgestellt:

  • Das Anlegen eines Tomcat Servers in Eclipse.
  • Das Erstellen eines Web-Projektes in Eclipse.
  • Das Konfigurieren einer Webanwendung mit Spring MVC.
  • Das Erstellen von Masken (Oberflächen, View) und Steuerungen (Controller).
  • Die Fehlerbehandlung bei Spring MVC.
  • Der Datenaustausch über ein Model.
  • Das Testen von Controllern.

Im folgendem Bild ist die Projektstruktur dargestellt.

Die Projektstruktur in Eclipse

Die Projektstruktur in Eclipse (© Frank Rahn)

Die folgende Bibliotheken werden benötigt:

Die benötigten Bibliotheken - Dependencies (© Frank Rahn)

Die Literaturempfehlungen für dieses Beispiel

Das Erzeugen eines neuen Tomcat Servers

In diesem Beispiel nutze ich die Eclipse Web Tool Platform. Dazu muss in der Perspektive Java EE perspective in der View Servers ein Tomcat Server angelegt werden. Dieses ist in der folgenden Bildgalerie dargestellt.

Das Anlegen des Projektes in Eclipse

In der folgenden Bildgalerie ist das Anlegen und Konfigurieren des Projektes mit Web Support in Eclipse beschrieben.

Die Konfiguration der Webanwendung

Die Webanwendungen, die dem Java EE 6 Standard genügen, werden mit einem Web-Deployment-Descriptor web.xml konfiguriert. Diese Datei befinden sich im Verzeichnis src/web/WEB-INF. Im folgendem Listing wird der Inhalt dieser Datei gezeigt und beschrieben.

  • In der Zeile 3 wird das Attribut metadata-complete="true" gesetzt, dadurch berücksichtigt der Applicationsserver keine Java EE Annotationen in diesem Web-Modul. Dieses hat unter anderem den Vorteil, dass der Applicationsserver keinen Klassen-Scan durchführt. Dieser Scan lädt alle Klassen in den Classloader bevor die Anwendung gestartet wird. Dieses führt zu Problemen, wenn beim Anwendungsstart Klassen durch die Anwendung (Load-Time) instrumentiert werden sollen (z. B. durch AspectJ, einen JPA-Provider oder ähnlichem), da diese schon geladen sind und nicht mehr verändert werden können.
  • Ab der Zeile 27 wird ein Filter für das Setzen des Encodings konfiguriert. Falls ein Request ohne angegebenen Encoding empfangen wird, wird das Encoding auf UTF-8 gesetzt. Damit werden auch Sonderzeichen richtig dargestellt.
  • Ab der Zeile 44 wird für das Logging ein Listener konfiguriert. Er muss der erste Listener in der Liste sein. Er lädt die Konfigurationsdatei aus Zeile 17.
  • Ab der Zeile 52 wird ein Listener für das Laden der XML Konfiguration der fachlichen Spring Beans (fachliche Logik) konfiguriert. Er verwendet die Konfigurationsdatei aus Zeile 24.
  • Ab der Zeile 62 wird das zentrale Servlet des Spring Frameworks konfiguriert. Es dient als Verteiler (Dispatcher) der Request auf die einzelnen Controller.

Das zentrale Servlet benötigt eine eigene Konfiguration. Der Name dieser XML Konfiguration verwendet den Servlet-Namen und den Postfix -servlet.xml. Der aus dieser Konfiguration entstehende ApplicationContext hat als Parent (Verschachtelung) den ApplicationContext von ContextLoaderListener mit den fachlichen Spring Beans. So können die Oberflächenelemente von der fachlichen Logik getrennt werden.

  • In der Zeile 40 wird ein Mapper zwischen URI und View definiert. Er macht aus der URI /index mit seiner Parameterisierung /WEB-INF/views/index.jsp.
  • In der Zeile 37 wird das Servlet angewiesen, alle Request ohne weiteren Pfad, an die View index zu leiten ohne einen Controller aufzurufen.

Die folgende XML Konfiguration enthält die fachlichen Spring Beans.

  • In diesem Beispiel sind die fachlichen Komponenten aus dem Beispiel Spring mit JPA und Hibernate in den Zeilen 30 und 31 noch auskommentiert. Im nächsten Beispiel werden sie hinzugenommen.

Das Anpassen der Tomcat Installation

In den Konfiguration wurde das Load-Time-Weaving aktiviert. Dieses instrumentiert Klassen direkt zum Ladezeitpunkt. Dazu muss eine spezielle Tomcat-Konfiguration erstellt werden. Diese Konfiguration weist Tomcat an einen anderen ClassLoader für diese Webanwendung zu verwenden. Diese Datei befindet sich im Verzeichnis src/web/META-INF.

Zusätzlich muss noch in das Verzeichnis ${TOMCAT_HOME}/lib die Bibliothek spring-instrument-tomcat-3.0.5.RELEASE.jar kopieren werden.

Die Masken (Oberfläche, View)

Die erste Seite (Startseite, Willkommensmaske) ist als Navigationsseite aufgebaut. Von hier aus können die einzelnen Beispiele angesprungen werden.

Die folgende Beispielseite mit Zähler verwendet in Zeile 11 ein Attribut, das im Controller gesetzt wird.

Die folgende Fehlerseite wird aufgerufen, wenn ein Controller durch einen Fehler eine Ausnahme wirft.

  • In den Zeilen 12 und 13 werden zwei Attribute aus dem Controller in die Seite eingefügt.

Auf der folgenden Maske sollen die geladenen Spring Beans in allen ApplicationContext aufgelistet werden.

  • In der Zeile 2 wird die Verwendung der JavaServer Pages Standard Tag Library deklariert.
  • In der Zeile 12 bis 44 wird über die einzelnen ApplicationContext iteriert. Die ApplicationContext können verschachtelt sein.
  • In der Zeile 33 bis 39 wird über die Spring Beans eines ApplicationContext gelaufen.

Die Steuerung (Controller)

Die Webanwendung hat nur einen einzelnen Controller SampleController. Hier befindet sich eine Diskussion, die den Unterschied zwischen einem Controller und einer Spring Bean genauer beleuchtet.

  • In der Zeile 19 wird durch die Annotation @Controller der Controller als solcher deklariert.
  • Die Methode in der Zeile 31 wird aufgerufen, wenn ein die URL http://localhost:8080/test-spring-web/sample aufgerufen wird. Dort wird bei jedem Aufruf ein Zähler hochgezählt und der View über das Modell bereitgestellt.
  • In der Zeile 43 wird nur eine Ausnahme geworfen, um die Fehlerbehandlung in der Methode handleException(Exception exception) auszuführen.
  • In der Zeile 51 ist ein Handler für Ausnahmen definiert. Sobald dieser Controller eine Ausnahme wirft, wird sie hier verarbeitet.

In der folgenden Spring XML Konfiguration wird nur das Packages mit den Controllern berücksichtigt.

Der folgende Controller stellt die Information über die verschachtelten ApplicationContext zusammen.

  • In der Zeile 22 wird für alle Methoden in dieser Klasse die Basis-Aufruf-URI definiert.
  • Dazu ist zunächst in der Zeile 29 ein Model als eine innere Klasse definiert.

  • In der Zeile 131 wird definiert, dass diese Funktion nur die HTTP-Methode GET unterstützt und in der Zeile 132 wird der Name des Models angegeben.

Die Masken

In folgender Bildgalerie werden die Screenshots der Masken im Browser dargestellt.

Der Unit Test

Für den einfachen Controller fehlt noch ein JUnit Test. Jede der drei Methoden des Controllers bekommt einen Test.

Der Quellcode und Download des Beispiels

Quellcode ansehen bei GitHub:
Spring mit einer einfachen Webanwendung

Download einer ZIP-Datei von GitHub:
Spring mit einer einfachen Webanwendung

Die Maven Befehle

Eclipse Konfiguration neu erzeugen: $ mvn eclipse:clean eclipse:eclipse

Anwendung bauen: $ mvn clean install

Update am 28.09.2012

Es wurden folgende Änderungen an allen Projekten vorgenommen.

  1. Die Projekte wurden aus meinem lokalen Apache Subversion Repository in meine öffentlichen GitHub Repositories verschoben.
  2. Die folgenden typischen Anpassungen an Git wurden an allen Projekten durchgeführt.
    • .directory gelöscht
    • .gitignore hinzugefügt
    • README.md hinzugefügt
    • COPYRIGHT.md hinzugefügt
    • In jedem Repository wurde für jeden Beitrag der Serie ein Branch angelegt.
      • develop-spring-an-einem-einfachen-beispiel
      • develop-spring-mit-aop
      • develop-spring-mit-jpa-und-hibernate
      • develop-spring-mit-einer-einfachen-webanwendung
      • develop-spring-mit-einer-webanwendung-mit-jpa-und-validierung
      • develop-spring-security-mit-einer-webanwendung
      • develop-spring-mit-restful-webservice

Updates von 06.10.2012 bis zum 14.10.2012

Es wurden folgende Änderungen an allen Projekten vorgenommen.

  1. Aktualisierung des OpenJDK auf die Version 1.7.0.
  2. Aktualisierung der Entwicklungsumgebung Eclipse auf die Version 4.2.1.
    Die benötigten Plugins aus dem Eclipse Marketplace:

  3. Aktualisierung der Datei pom.xml:
    • Anpassungen an die OpenJDK Version
    • GitHub Einträge (SCM und URL) hinzugefügt
    • Aktualisierung der Libraries auf aktuellerer Versionen (z. B. Spring Version 3.1.2.RELEASE, Hibernate Version 4.1.7.Final, JUnit Version 4.10, mockito Version 1.9.0, …)
      Die genaueren Versionen bitte aus den jeweiligen pom.xml auf GitHub entnehmen.

Frank Rahn

Frank Rahn ist Softwarearchitekt. Er unterstützt bei der Konzeption von Softwarearchitekturen mit Java-Technologie. Folge Sie ihm auf Facebook, Twitter oder Google+.

Benötigen Sie Unterstützung? Kontaktieren Sie ihn.

Hat Ihnen dieser Beitrag gefallen? Wir würden uns über Ihren Kommentar freuen! Bitte verwenden Sie Ihren bürgerlichen Namen und eine E-Mail-Adresse mit Gravatar.

Letzte Artikel von Frank Rahn (Alle anzeigen)

2 Kommentare
    • Frank Rahn
      Frank Rahn says:

      Spring setzt AOP-Proxies z.%nbsp;B. für die Behandlung von Annotationen, wie @Transactional, an Spring Beans ein. Dabei unterscheidet das Spring Framework drei Varianten (Siehe auch Spring mit AOP):

      • Dynamic Proxy des JDK’s
        In diesem Fall müssen die Annotationen an Methoden des Beans stehen, die in Interfaces deklariert worden sind. Das Proxy implementiert ausschließlich die Methoden der Interfaces, die das Spring Bean implementiert und nur dort stehen die Erweiterungen zu Verfügung. Die Annotation an anderen Methoden werden ignoriert.
      • Subclassing mit CGLIB
        In diesem Fall werden die Erweiterungen durch das Ableiten der Klasse des Spring Beans bereitgestellt. Dadurch können nur ableitbare Methoden berücksichtigt werden. Die Annotationen an private und final Methoden werden ignoriert.
      • AspectJ
        In diesem Fall werden die Erweiterungen direkt in die kompilierte Klasse eingewoben (Weaving). Dieses kann zur Laufzeit (Load-Time) oder beim Builden (Compile-Time) geschehen. AspectJ berücksichtigt alle Methode der Spring Bean.

      Bei AOP mit AspectJ kann Spring bestimmte Annotation, wie z. B. @Transactional, auch an privaten Methoden unterstützen. Daher wird hier in diesem Beispiel das Load-Time-Weaving eingeführt. Gerade bei Transaktion, die möglichst klein bzw. kurz sein sollen, ist es sinnvoll diese Technik einzusetzen. Bei häufig angewendeten Aspekten hat AspectJ leichte Vorteile in der Performance.

      Antworten

Dein Kommentar

Want to join the discussion?
Feel free to contribute!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.