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