Skip to content

16. MVC-Webanwendung in einer 3-Tier-Architektur – Beispiel 2

16.1. Einführung

Wir haben die Anwendung [people-01] mit folgender Struktur geschrieben:

Die [dao]-Schicht implementierte die Liste der Personen mithilfe eines [ArrayList]-Objekts. Dadurch konnten wir eine übermäßige Komplexität der [dao]- und [service]-Schichten vermeiden und uns auf die [web]-Schicht konzentrieren. Wir möchten die Anwendung in Richtung einer realistischeren Umgebung weiterentwickeln, in der die Liste der Personen in einer Datenbanktabelle gespeichert wird. Dazu müssen wir die [dao]-Schicht ändern. Dies wird sich auf die beiden anderen Schichten auswirken. Um die durch Spring IoC gebotene Schichtunabhängigkeit zu nutzen, nehmen wir die Anwendung [people-01] und konfigurieren sie mit Spring IoC:

Die neue Anwendung wird [people-02] heißen. Sobald sie fertiggestellt ist, wissen wir, dass wir die [DAO]- und [service]-Schichten ändern können, ohne den Code in der [web]-Schicht zu ändern. Genau das ist unser Ziel.

Wir erstellen ein neues Eclipse-Projekt [people-02], indem wir das Projekt [people-01] kopieren und einfügen, wie in Abschnitt 6.2 beschrieben:

In [1] sehen wir die Konfigurationsdatei, in der wir die Beans für die [dao]- und [service]-Schichten definieren werden. Ihr Inhalt lautet wie folgt:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- the dao class -->
    <bean id="dao" class="istia.st.mvc.personnes.dao.DaoImpl" init-method="init"/>
    <!-- service class -->
    <bean id="service" class="istia.st.mvc.personnes.service.ServiceImpl">
        <property name="dao">
            <ref local="dao" />
        </property>
    </bean>
</beans>
  • Zeile 5: Definiert die Bean mit dem Namen [dao] als Instanz der Klasse [DaoImpl]. Nach der Instanziierung wird die Methode [init] der Instanz ausgeführt.
  • Zeilen 7–10: Definieren die Bean mit dem Namen [service] als Instanz der Klasse [ServiceImpl].
  • Zeilen 8–10: Die Eigenschaft [dao] der Instanz [DaoImpl] wird mit dem Verweis auf die in Zeile 5 erstellte [dao]-Schicht initialisiert. Zur Erinnerung: Die Klasse [ServiceImpl] verfügt tatsächlich über die Eigenschaft [dao] und den entsprechenden Setter:
public class ServiceImpl implements IService {

    // the [dao] layer
    private IDao dao;

    public IDao getDao() {
        return dao;
    }

    public void setDao(IDao dao) {
        this.dao = dao;
    }
...

Natürlich bewirkt diese Datei allein noch nichts. Der [Application]-Controller wird sie in seiner [init]-Methode verwenden, um die [service]-Schicht zu instanziieren. Erinnern wir uns an die vorherige Version der [init]-Methode des Controllers:

@SuppressWarnings("serial")
public class Application extends HttpServlet {
...
    // service
    ServiceImpl service = null;

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
        // dao] layer instantiation
        DaoImpl dao = new DaoImpl();
        dao.init();
        // instantiation of the [service] layer
        service = new ServiceImpl();
        service.setDao(dao);
    }

In Zeile 5 mussten wir die Implementierungsklasse der [service]-Schicht explizit benennen, und in Zeile 12 die der [dao]-Schicht. Mit Spring IoC sieht die [init]-Methode wie folgt aus:

@SuppressWarnings("serial")
public class Application extends HttpServlet {
    // instance parameters
    ...

    // service
    private IService service = null;

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
    ...
        // instantiation of the [service] layer
        service = (IService) new XmlBeanFactory(new ClassPathResource("spring-config.xml")).getBean("service");
    }
  • Zeile 7: Das private Feld [service] ist nicht mehr vom Typ [ServiceImpl], sondern vom Typ [IService], d. h. vom Typ der Schnittstelle der [service]-Schicht. Die [web]-Schicht ist daher nicht mehr an eine bestimmte Implementierung dieser Schnittstelle gebunden.
  • Zeile 14: Initialisierung des Feldes [service] aus der Konfigurationsdatei [spring-config.xml].

Dies sind die einzigen Änderungen, die vorgenommen werden müssen. Integrieren wir diese neue Anwendung in Tomcat, starten wir sie und rufen wir dann die URL [http://localhost:8080/personnes-02] auf:

Image

16.2. Archivierung der Webanwendung

Wir haben ein Eclipse/Tomcat-Projekt für eine 3-Tier-Anwendung entwickelt:

In einer zukünftigen Version wird die Gruppe von Personen in einer Datenbanktabelle gespeichert.

  • Dies erfordert eine Neuprogrammierung der [DAO]-Schicht. Das ist leicht zu verstehen.
  • Auch die [Service]-Schicht wird geändert. Derzeit besteht ihre einzige Aufgabe darin, den synchronisierten Zugriff auf die von der [DAO]-Schicht verwalteten Daten sicherzustellen. Zu diesem Zweck haben wir alle Methoden in der [Service]-Schicht synchronisiert. Wir haben erläutert, warum diese Synchronisation in dieser Schicht und nicht in der [DAO]-Schicht platziert wurde. In der neuen Version wird die [Service]-Schicht weiterhin die alleinige Aufgabe haben, den Zugriff zu synchronisieren, doch dies wird durch Datenbanktransaktionen und nicht durch die Synchronisation von Java-Methoden erfolgen.
  • Die [Web-]Ebene bleibt unverändert.

Um den Übergang von einer Version zur nächsten zu erleichtern, erstellen wir ein neues Eclipse-Projekt [mvc-personnes-02B], eine Kopie des vorherigen Projekts [mvc-personnes-02], bei dem jedoch die Schichten [Web, Service, DAO, Entities] in .jar-Archiven abgelegt wurden:

Der Ordner [src] enthält nun nur noch die Spring-Konfigurationsdatei [spring-config.xml]. Zuvor enthielt er auch den Quellcode für die Java-Klassen. Diese Elemente wurden entfernt und durch ihre kompilierten Versionen ersetzt, die in den in [1] gezeigten [people-*.jar]-Archiven abgelegt sind:

Das Projekt [mvc-personnes-02B] wurde so konfiguriert, dass es die [personnes-*.jar]-Archive in seinen ClassPath aufnimmt.

Wir stellen das Webprojekt [mvc-personnes-02B] in Tomcat bereit:

Um das Projekt zu testen, starten wir Tomcat und rufen dann die URL [http://localhost:8080/personnes02B] auf:

Image

Der Leser ist eingeladen, weitere Tests durchzuführen.

In der Datenbankversion werden wir die Schichten [service] und [dao] ändern. Wir möchten zeigen, dass es dann ausreicht, die Archive [personnes-dao.jar] und [personnes-service.jar] im vorherigen Projekt durch die neuen Archive zu ersetzen, damit unsere Anwendung nun mit einer Datenbank funktioniert. Die Archive der Schichten [web] und [entities] müssen wir nicht ändern.