MVC Architektur in Java Web Anwendungen

Transcription

MVC Architektur in Java Web Anwendungen
l
MVC Architektur in
Java Web Anwendungen
© Libra 2003
1
Patterns, Frameworks und der Begriff "MVC".................................................. 3
J2EE Webanwendungen............................................................................... 7
Servlet JSP Entwicklung .............................................................................. 8
Servlet ................................................................................................... 8
JSP ...................................................................................................... 10
Request Dispatch................................................................................... 12
User Interface Muster................................................................................ 14
Servlet JSP Collaboration ........................................................................... 16
Patterns im Web Bereich ........................................................................... 19
View Helper .......................................................................................... 19
Composite View ..................................................................................... 20
Front Controller ..................................................................................... 20
Intercepting Filter .................................................................................. 20
Dispatcher View..................................................................................... 21
© Libra 2003
2
Patterns, Frameworks und der Begriff "MVC"
Eine Webanwendung ist nicht ein einzelnes Servlet, das HTML Text ausgibt, oder
eine einzelne JSP Seite. So notwendig es ist, die Technologiebasis eines Servlets
und einer JSP Seite genau zu verstehen, ist eine Webanwendung nicht bloß eine
Aneinanderreihung vieler Servlets, sondern deren Einbettung in eine
umfassendere Architektur, die "Framework" genannt wird. Frameworks
beinhalten zwar in ihrer Basis die Servlet Technologie, verlangen aber in ihrer
konsequenten Anwendung von Patterns eine strengere Systematik.
Sobald die Anforderungen an das User Interface und die Funktionalität der
Anwendung steigen, Datenbanken, Transaktionssteuerung und
Berechtigungssysteme einbezogen sind, wird die Einhaltung von "Patterns"
notwendig. Vor allem Wiederverwendung und Einmal-Entwicklung von Code –
also klassische Prinzipien Objektorientierten Designs – bleiben bei Servlets, die
HTML durch Stringoperationen ausgeben, und JSP Seiten, die Scriptlet Code
enthalten, durch die Ineinanderverstrickung von Modell, Zustandsveränderung
und Darstellung auf der Strecke.
Im Folgenden nähern wir uns, ohne uns auf ein bestimmtes Framework
einzulassen, dem Grunddesign einer Webanwendung in einer MVC Architektur.
"MVC" ist nicht als einzelnes Pattern sondern eher als ein – im Bereich
graphischer Userinterfaces sehr erfolgreiches – Paradigma und Denkmodell im
Design von Softwaresystemen zu sehen, innerhalb dessen eine Vielzahl von
Patterns zur Anwendung kommt.
Die Model/View/Controller Dreiteilung wurde zum ersten Mal in Smalltalk-80 in
der Entwicklung von graphischen User Interfaces begrifflich geprägt. Model steht
hierbei für das Anwendungsobjekt, View für die Präsentation des Objekts auf
dem Bildschirm und Controller für die Art und Weise, wie das User Interface auf
Benutzereingaben reagiert.
© Libra 2003
3
Keyboard
Mouse
Controller
View 1
Object
View 2
View n
Zuvor waren in User Interfaces die drei Ebenen in der Regel miteinander
verwoben. MCV identifiziert die drei Bereiche und versucht, sie voneinander zu
trennen.
Die Entflechtung geschieht in erster Linie durch ein Subscribe/Notify Protokoll
zwischen den wesentlichen Komponenten. Ein View registriert sich beim Model
als Listener. Ändert sich das Modell, werde alle seine Listener aufgerufen.
Innerhalb dieses Aufrufs haben die Listener die Gelegenheit, das Modell
abzufragen und sich selbst "upzudaten". Diese Technik vereinfacht die
Darstellung eines Objekts in verschiedenen Fenstern erheblich.
© Libra 2003
4
Controller
• definiert
User Interaktion
Anwendungsverhalten
• transformiert User Aktion zu
Model Update
View
Festlegung
„State“
änderung
• bestimmt View für Response
Benachrichtigung
View
Model
• zeigt das Model
• nimmt Update Information aus Model
• gibt User Verhalten an Controller weiter
• erlaubt Controller View zu bestimmen
• beinhaltet den Application
State
• benachrichtigt View über
Änderungen
„State“abfrage
Es hat sich in der weiteren Entwicklung gezeigt, dass die Entflechtung in
unabhängige Komponenten und die kontrollierte Verständigung der
Komponenten über Kontrakte in Zusammenhang mit User Interfaces nur ein
spezialisierter Fall noch allgemeinerer Muster sind, für die sich dann der Begriff
"Patterns" herausgeprägt hat.
© Libra 2003
5
Zu nennen sind hier vor allem die Arbeiten von Erich Gamma, Richard Helm,
Ralph Johnson und John Vlissides, deren gemeinsames Buch "Design Patterns"
von 1994 zu einem Klassiker der modernen Softwaretheorie geworden ist.
© Libra 2003
6
J2EE Webanwendungen
Firewall
Client
Client
Web Container
Client
Database
ERP Legacy
Applications
Servlets
JSP, HTML
Client
Client Tier
Middle Tier
EIS Tier
Die Elemente einer Java Webanwendung:
Servlet
JSP
Tags
JSTL
Filter
© Libra 2003
7
Servlet JSP Entwicklung
Servlet
Die einfachste Form einer Webanwendung ist die eines an ein Servlet gehenden
Requests, das diesen Request untersucht und an den http Client im gleichen
Server Zyklus einen entsprechenden HTML Strom zurücksendet.
Das HTML für die Seite, die der Browser anzeigt, wird in der einfachsten Figur im
Servlet selbst generiert. Dabei zeigt sich der Technologiebruch zwischen Java
und HTML. HTML Konstrukte sind innerhalb eines Servlets einfache Strings, die
beliebig zusammengesetzt werden und durch Java keiner semantischen
Überprüfung unterzogen werden. Die Erstellung erfolgt in einem
zeitaufwendigen, iterativen Trial und Error Verfahren, da man erst durch EditCompile und Web Server Context Reload Zyklen Ergebnisse und Veränderungen
in der Präsentation der HTML Seite "sieht". Mühseliger noch gestaltet sich das
Einbinden von eingestreuten Programmwerten. Resultat ist jedenfalls ein
zweifelhafter Code, der sich für kleinere Lösungen, schwerlich jedoch für größere
Anwendungen vertreten lässt.
Historisch gesehen, lag hierin die Motivation der JSP Technologie, also die Sache
genau umzukehren und "den Mantel von der anderen Seite zu tragen". Wenn in
Servlets die Erzeugung von HTML mitten in Java eingebettet ist und damit für
HTML Designer praktisch nicht mehr zugänglich ist – einmal abgesehen von dem
unwartbaren Code, der durch die ungeordnete Koexistenz von
Präsentationsfragmenten und Anwendungslogik entsteht – so ist umgekehrt bei
JSP Seiten, deren Körper zunächst einmal alles darstellt, was direkt an den
Browser zurück geschickt wird, Java als Scriptlet Code in den HTML Body
eingestreut. Die Nachteile dieses Paradigmas liegen ebenso sehr auf der Hand.
Dass JSP Seiten durch einen Übersetzungsprozess in Servlets übersetzt werden,
also genau in die Technologie, deren Schwächen zu heilen sie entwickelt wurden,
ändert an den eigenen Schwächen, die sich durch den eingestreuten Scriptlet
Code auftun, nichts, wenn nicht sogar gerade dieser Umstand ihre eigenen
Schwächen mit bedingt hat. Allerdings ist der Übersetzungsmechanismus und
ihre Technologiebasis als solche nicht zu kritisieren – was zählt ist, wie sich JSP
Seiten dem Entwickler – und auch Seitenautor – in ihrer Verwendung darstellen.
© Libra 2003
8
HTML Form
KdNr
4711
Name
Floh
Ort
Köln
"Server Cycle"
Speichern
Servlet
Request Parameter Map
KdNr=4711
Name=Floh
Ort=Köln
Datenbank Operationen
Erzeugung HTML Form
mit Daten Einbindung
Kunde Nr
Name
Ort
...
4711
Floh
Köln
...
© Libra 2003
9
JSP
Java Server Pages eignen sich besser als Servlets, die Aufbereitung des HTML,
das an den Browser am Ende eines Server Zyklus geschickt wird zu übernehmen.
Wie sie sich dem Webentwickler nach außen hin darstellen, sind sie nichts
anderes als HTML Seiten – mit dem Unterschied, dass in sie durch spitze
Klammern ("<%" und "%>") markierter Java Code eingebettet ist, der zum
Zeitpunkt, wo das umgebende HTML an den Browser gesendet wird, zur
Ausführung kommt und so die Gelegenheit bietet, das gesendete HTML
programmatisch zu verändern und zu ergänzen.
Wenn eine Form wieder angezeigt wird – das JSP Servlet also wieder das HTML
für die Form an den Browser sendet – dann sollte beispielsweise das "value"
Attribute eines Input Tags mit einem entsprechenden String Wert gesetzt
werden, damit mindestens die vom User in diesem Textfeld getätigte Eingabe,
die die Webanwendung als Requestparameter erreicht hat, erhalten bleibt.
Mindestens also sollten die decodierten Requestparameter programmatisch in
das HTML für die Form eingearbeitet werden. Als Mechanismus hierfür ist von der
JSP Spezifikation die Verwendung von Java Beans vorgesehen.
Bean
Vorname
Beanproperty
Nachname
JSP
Vorname
Nachname
© Libra 2003
10
Die Bean wird vor ihrer ersten Verwendung auf der JSP Seite deklariert durch ein
vordefiniertes Action Tag
<jsp:useBean id="pizzaOrderBean" scope="session" class="schulung.servlet.PizzaOrderBean"/>
wodurch sie als Objekt vom Typ schulung.servlet.PizzaOrderBean im SessionObjekt – falls nicht bereits dort vorhanden – erzeugt wird und für den folgenden
Scriptlet Code der JSP Seite unter der Variable "pizzaOrderBean" zur Verfügung
steht.
Vom Java Beans Standard, der ursprünglich im GUI Swing Umfeld entwickelt
wurde, werden von der JSP Technologie nur Minimalanforderungen an eine Bean
gestellt, die sie als Bean von einer normalen Java Klasse unterscheiden – nämlich
dass sie einen Default Konstruktor und symmetrische Accessor Methoden (deren
Namen jeweils mit set und get beginnen) für ihre Properties hat.
Wenn die JSP Seite nicht – wie wir in der Folge sehen werden – ein
vorgeschaltetes Servlet hat, sondern direkt vom "action" Attribut des "form" Tags
angesprochen wird, werden nach ihrer Deklaration typischerweise die
Requestparameter der Bean über eine weiteres vordefiniertes Action Tag gesetzt
<jsp:setProperty name="pizzaOrderBean" property="street" param="street" />
Hiermit "hält" die Bean, die als Objekt im Session Scope die einzelnen Server
Zyklen überdauert, als Properties die vom Benutzer in den Input Elementen der
Form gemachten Eingaben.
Wenn auf der JSP Seite die Input Felder der Form als HTML angegeben werden,
können die "value" Attribute der Input Elemente durch die Properties der Bean
programmatisch gesetzt werden
. . . <input type="text" name="street"
value="<jsp:getProperty name="pizzaOrderBean" property="street"/>"
> <p> . . .
Der Versuch, das Servlet auf diese Weise durch JSP Seiten zu ersetzen, ist
jedoch nicht unproblematisch.
Zwar kann die programmatische Untersuchung der Requestparameter noch von
der Bean mit übernommen werden, aber eine anschließende Entscheidungslogik
zeigt sich – sowohl auf der JSP Seite als auch in die Bean verlagert –
fehlplaziert. Auch ist ein Laden der Bean aus einem Datenbank Satz oder ein
Datenbank Update oder Insert innerhalb der Bean gleichfalls problematisch,
weshalb die Logik für solche Operationen dann in einem wachsenden Maß die JSP
Seite in Form von Scriptlet Code bevölkern wird. Nicht nur wird aber durch eine
© Libra 2003
11
Verzahnung der Anwendungslogik mit der HTML Präsentation die
Wiederverwendung der Anwendungslogik in anderen Präsentationskontexten
unmöglich, sondern wir werden auch recht bald den Zustand erreichen, dass
entweder auf einer JSP Seite das HTML für völlig unterschiedliche HTML Seiten
vorhanden ist oder aber, dass durch die Entscheidungslogik einer JSP Seite auf
eine ganz andere JSP Seite verzweigt wird, mithin das eigene HTML der JSP Seite
gegenstandslos ist.
Diese Probleme haben in ihrer Konsequenz dazu geführt, Requestparameter
Decodierung, Entscheidungslogik und Anwendungslogik doch wieder in einem
Servlet vorzunehmen, das anders jedoch – als in der reinen Servlet Variante –
JSP Seiten, die die HTML Aufbereitung übernehmen, nur vorgeschaltet ist.
Request Dispatch
Im Action Attribut der Form wird eine URL codiert, die nicht die JSP Seite mit der
Form, sondern ein Servlet zum Empfang der Formeingaben als Request
Parameter bestimmt. Das Servlet untersucht die Request Parameter und führt
die sich anschließende Anwendungslogik und etwaige Datenbankoperationen aus,
die insgesamt zu einer Veränderung des Modells der im Session Kontext
verankerten Beans führen. Die Entscheidungslogik des Servlets mündet in der
Verzweigung des Servlets auf eine JSP Seite, deren HTML, das um Werte aus der
Modellschicht der Java Beans angereichert wird, an den Browser als Ergebnis des
Server Cycle zurückgeschickt wird.
© Libra 2003
12
Pizza Bestellung
Name
Floh
Straße
Kölner Str.5
"Server Cycle"
Pepperoni
Pilze
Artischocken
Servlet
Bestellen
Untersuchung Request
Set Bean Properties
Eingaben
OK?
JSP "Success" Page
JSP "Pizza
Bestellung" Page
Pizza
Order Bean
Messages
Bean
© Libra 2003
13
User Interface Muster
In allen Anwendungen lassen sich wiederkehrende Muster im Ablauf des User
Interfaces wieder finden. Ein solches "Paradigma" ist die Darstellung von
Objekten in einer Liste mit der Selektionsmöglichkeit eines einzelnen Objekts und
anschließender Bearbeitung des Einzelobjekts. Bei der Darstellung des
Einzelobjekts lassen sich vier Bearbeitungsmodi unterscheiden: View, Edit, New,
Delete.
Product Id
Product
Einheit
16
Chianti
Classico
Cotes du
Rhone
Chablis
fl
17
18
fl
fl
Product Id
17
Produkt
Cotes du Rhone
Maßeinheit
Change
© Libra 2003
14
Wenn ein solches Liste-Einzelobjekt Ablaufschema in Webtechnologie realisiert
werden soll, erfolgt die Auswahl des Einzelobjekts in der Regel über einen Anchor
in der Liste. (Alternative: Form Buttons die auf der Einzelzeile platziert sind.)
Der Anwendungsteil, der den HTML Code für die Liste generiert, muss also
genügend Information in den Querystring-Teil des Anchors einfügen, dass das
Einzelobjekt bei einer nachfolgenden Request Verarbeitung identifiziert werden
kann.
Bei der Realisierung eines solchen Ablaufs lassen sich folgende Komponenten
identifizieren:
-
Produktion der Liste
Verarbeitung des Requests, der aus der Selektion aus der Liste resultiert
Verarbeitung des Requests, der aus dem Betätigen des "Update" Buttons
bei der Formularanzeige resultiert.
© Libra 2003
15
Servlet JSP Collaboration
Die Verarbeitung der Requests wird in Servlets realisiert.
Wenn wir die Requestverarbeitung Servlets überlassen, ist es der Part der JSP
Seiten hingegen, die Presentation der HTML Formulare zu übernehmen. Denn
sowenig wir Scriptletcode in JSP Seiten wollen, sowenig wollen wir HTML in Java
Code.
Das Request-Processing des Servlets endet mit einem Forwarding über den
RequestDispatcher des Servlet Contexts auf die anzuzeigende JSP Seite. Aufgabe
des JSP Processings ist es, die aus dem Request Processing resultierenden Daten
in den mit Action Tags versehenen HTML Code der JSP Seite einzusetzen.
© Libra 2003
16
Incoming Request:
Display product 17 for
update
Browser
Client
Request
Prozessor
Servlet
Setup Model
Forward to JSP
pure HTML
Model:
Produkt Object
JSP Page
merge model data into HTML
© Libra 2003
17
In der Request Verarbeitung innerhalb des Servlets wird ein Produkt Object
instantiiert, das die Werte des Produkts, das mit dem Primary Key eindeutig
identifiziert wird, widerspiegelt. Der Primary Key für das Objekt wird den Request
Parametern entnommen, die im Query String der Links der List-Page mitcodiert
sind. (Die Bestandteile des Primary Keys, die das Servlet aus dem Request als
Request Parameter extrahiert, müssen unter Umständen um weitere
Bestandteile, die im Anchor nicht explizit codiert wurden – wie zum Beispiel
typische Organisationsbegriffe wie Mandant, Buchungskreis, Einkaufsorganisation
– und die sich im Zusammenhang der Session ergeben, komplettiert werden.
Mit Hilfe des Primary Keys werden aus der Datenbank die restlichen Werte
gelesen, die zum Konstruieren eines Value Objekts erforderlich sind. Die Value
Objekte, die Kopien der Objekte im persistenten Store sind, werden im Session
bezogenen Kontext gespeichert (setAttribute()) und bleiben dort über die
einzelnen Requestzyklen einer Session erhalten.
Die JSP Seite, die den View auf das Objekt übernimmt, und an die das Servlet
die Kontrolle des Dispatchers weitergibt, kann das Objekt aus dem Session
Kontext über vereinbarte Identifikationsstrings mit den Mitteln der Standard
Action Tags zur Verwendung von Java Beans wieder verwenden und in den HTML
Strom an den geeigneten Stellen einfügen.
© Libra 2003
18
Patterns im Web Bereich
Intercepting Filter
Front Controller
Context Object (new)
Application Controller (new)
View Helper
Composite View
Service to Worker
Dispatcher View
View Helper
Ein View soll nach Möglichkeit nur Code zur Formatierung und Präsentation von
Informationen enthalten. Auch wenn das Request Processing von einem Servlet
übernommen wird, das dann eine JSP Seite aufruft, wird diese JSP Seite immer
noch Scriptlet Code beinhalten.
Um diesen Scriptlet Code zu eliminieren und sowohl Abstraktion als auch
Wiederverwendung zu ermöglichen, werden so genannte View Helper in JSP
Seiten eingesetzt.
View Helper sind
Java Beans
Custom Tags
Die Java Beans sind hierbei "Abziehbilder" der Modellschicht.
Custom Tags haben in der JSP Seite eine XML Syntax und werden durch Java
Klassen, die bestimmte normierte Interfaces erfüllen, implementiert.
© Libra 2003
19
Composite View
Die Seite, die angezeigt wird, ist eine "logische" Seite.
Das Servlet zeigt eine Template JSP Seite an.
Durch Konfigurationsinformationen aus der "logischen Seite" werden die Insert
Tags aufgelöst und die JSP Fragmente in das Template eingebunden.
Front Controller
Nicht für jeden Browser Request wird ein neues Servlet eingesetzt. Durch
Abstraktion lassen sich alle Aufgaben des Controllers, der eingehende User
Requests verarbeitet, von einem einzigen Servlet übernehmen.
Das Main Servlet steuert die Request Verarbeitung, stellt Security Funktionen zur
Verfügung, delegiert Events an die Applikationsschicht und übernimmt die Flow
Logik, die bestimmt welche JSP Seite angezeigt wird. Das Main Servlet handhabt
auftretende Fehler.
Die spezifische Verarbeitung der Requests wird von spezifischen Requesthandlern
übernommen, die vom Main Servlet aufgerufen werden. Um spezifische
Requesthandler bestimmten URLs zuzuordnen, benötigt der Front Controller eine
Zuordnungstabelle, die er in seiner Initialisierung lädt.
Die Request Handler decodieren den eingehenden Request, übernehmen dessen
Daten und generieren daraus "Commands" oder "Application Events", die vom
Front Controller an die Business Schicht delegiert werden.
Intercepting Filter
Pre- und Post processing
Security, IP address validation
Compression, Encoding
Überprüfung, ob der Browsertyp die Anforderungen erfüllt.
HTML Save
© Libra 2003
20
Dispatcher View
Allgemeine Steuerung für Flow Handling, durch die bestimmt wird, auf welche
Seite nach Rückkehr aus der Anwendungsschicht verzweigt wird.
© Libra 2003
21