MVC in Java pur / Controller als Instanz? / Theorie!

HankScorpio

Mitglied
Hallo zusammen,

ich stelle mir gerade im Moment die Frage, wie man am besten
- ohne Framework,
- die Controller gestaltet und
- den Aufruf des passenden Controllers zu einem Request realisieren könnte.

Meine Lösungsidee war ungefähr die:
- Alle Requests gehen an ein zentrales Servlet, das "Dispatcher"-Servlet.
- In einer HashMap mit <String,String> ordne ich jeweils einem "Action-Wort" (z.B. "invokeMeasurement") den Klassennamen einer Controllerklasse zu (z.B. "MeasurementInvoker").
- Alle Controllerklassen implementieren das Interface "AllgemeinerController", das die Methode verarbeiteRequest vorschreibt.
- In dem "Dispatcher"-Servlet empfange ich das Action-Wort - sagen wir mal als GET-Parameter.
- Das Dispatcher-Servlet führt allerhand Dinge aus, die für jeden Request durchgeführt werden müssen, egal, was für eine Action angefordert wird.
- In der HashMap wird dann nachgeschaut, welcher Klassenname zu dem Action-Wort gehört.
- Für den Request wird eine Instanz dieser Controller-Klasse erzeugt, nur auf Grundlage des Klassennamens als String.
- Da die Controller-Instanzen alle auf das Interface "AllgemeinerController" hören, wird beim frisch erzeugten Objekt (der Controllerklasse XY...) die Methode "verarbeiteRequest" aufgerufen.

Stellt sich die Frage:
Hat es überhaupt Sinn, für jeden Request eine Instanz des jeweiligen Controllers zu erzeugen? Oder reicht eine einzige Instanz für alle Requests (auch exakt gleichzeitige), solange nicht künstlich irgendwelche Threadsafety-kaputtmachenden Dinge gemacht werden (z.B. konkurrierender Zugriff auf Variablen im Klassen- oder Objekt-Scope).
Denn sonst könnte man ja auch statt der eingangs vorgeschlagenen HashMap<String,String> (ActionWort -> Klassenname) auch direkt machen HashMap<String,AllgemeinerController>, sodass jedem Actionwort eine Instanz eines Objekts zugeordnet wäre, das das Interface erfüllt. Diese Zuordnung könnte ja in einem static initializer des Dispatchers erfolgen. So würde die eine (ganz zu Beginn erzeugte) Instanz des Controllers aus der HashMap alle Requests handlen.

D.h. ganz kurz reduziert: Controllerklassenname als String in die HashMap oder gleich eine aufrufbare Instanz der spezifischen Controllerklasse? Was spricht für das eine, was für das andere?

Zum Sinn der Sache: Es geht mir jetzt gerade nicht darum, wie man das am effektivsten und zeitsparendsten in einem Echtprojekt löst (Da implementiert man natürlich nicht alles mühsam zu Fuß, das ist klar, Frameworks gibt es nicht bloß zum Spaß), sondern es ist heute eher die akademische Überlegung, wie MVC in "Java/Servlet-pur" am besten angenähert werden kann, ohne eine bestimmte Third-Party-Framework-Lösung heranzuziehen. D.h. es soll so allgemein gehalten sein wie möglich.
Es geht darum, das Konzept mal in Java-pur zu sehen und nicht es mit Fertigkomponenten möglichst komfortabel und schnell zu produzieren.

Die üblichen Beispiele dazu mit Plain-Servlet sind ja i.d.R. so primitiv (insb. kein zentraler Controller, über den erst mal alle Requests geleitet werden), dass sie sich gedanklich auf reale Probleme kaum übertragen lassen (ein Servlet, eine JSP-Seite als View zum Draufforwarden und eine JavaBean für die View-Daten oder so ungefähr). Klar, man kann für jedes Formular als POST-Datenempfänger ein eigenes Servlet als Controller implementieren, aber das wär ja ziemlich redundant und unübersichtlich, wenn gemeinsamer, gleicher Verarbeitungscode in x verschiedenen Servlets vorkäme.

Gruß und danke euch schon mal für alles Mit-Überlegen,
Hank Scorpio

PS: Achja, und ein schönes Wochenende an alle! ...und ein noch schöneres für alle, die Überlegungen beisteuern... :D
 
Zuletzt bearbeitet:

Ullenboom

Bekanntes Mitglied
Wenn ich das mal mit anderen GUIs vergleiche, werden die Controller/Presenter immer neu aufgebaut pro Request. Objekterzeugung koste in Java quasi nix mehr. Warum eine Map füllen? Das ist ja Zustand und den möchte man i.d.R. vermeiden. Je zustandsloser desto besser.
 

HankScorpio

Mitglied
Hallo Herr Ullenboom,

vielen Dank für die schnelle Antwort und, wo ich schon mal die Gelegenheit habe: Vielen Dank für Ihr Standardwerk zur Java-Programmierung! Das Java-Insel-Buch war mir schon oft sehr nützlich und ich habe es auch vielfach weiterempfohlen.

Wenn ich das mal mit anderen GUIs vergleiche, werden die Controller/Presenter immer neu aufgebaut pro Request.
Gut, danke für den Hinweis! Dann werd ich das auch in der Richtung weiterüberlegen.

Warum eine Map füllen? Das ist ja Zustand und den möchte man i.d.R. vermeiden. Je zustandsloser desto besser.
Auf die Map war ich gekommen, als ich überlegt habe, wie man die "Staffelholz-Übergabe" vom zentralen Controller/Dispatcher an die einzelnen "Sub-Controller"/Actions machen könnte, also den logischen Link zwischen einem Query-String-Parameter-Wert ("action=XY") und der dafür aufzurufenden Controller-Klasse ("XYController").

Da waren mir verschiedene Möglichkeiten eingefallen:
  1. die besagte Map als "Controller-Verzeichnis", entweder als <String,String(Klassenname)> oder <String,Controller(Instanz)>
    Da die Information, welche Klasse zu welchem Action-Wort gehören soll, über den ganzen Lebenszyklus der Anwendung hinweg unverändert bliebe und für jeden Request nur ausgelesen werden würde, dachte ich, es wäre vielleicht nicht verkehrt, sie als Quasi-Konstante/Zustand zu behalten
  2. Reflexion: nach allen Klassen suchen, die als Controller taugen (--> Annotation auswerten)
  3. ein langer if-elseif-...-Block a la
    Java:
    //Pseudocode auf die Schnelle
    AllgemeinerController zustaendigerController = null;
    if (action.equals("invokeMeasurement")) {
      zustaendigerController = new MeasurementInvoker();   // public class MeasurementInvoker implements AllgemeinerController { ...
    } else if (action.equals("prepareTea")) {
      zustaendigerController = new TeaPot();   // public class TeaPot implements AllgemeinerController { ...
    } else if (...) {
      ...
    }
    if (zustaendigerController == null) {
       System.err.println("Ups, kein passender Controller gefunden. Das wäre ein 404er.");
    } else {
       zustaendigerController.verarbeiteRequest(...);
    }
    So wäre es wohl am einfachsten, aber das ist natürlich auch nicht gerade "schön". :/ Eine Map mit der Zuordnung ("Action"-->Klassenname) hingegen könnte man auch einfach aus einer externen XML-/CSV-/...-Datei aufbauen und bräuchte sie gar nicht fest im Code zu hinterlegen.

Nach Klassen zu suchen, die eine Annotation als Controller haben und dann daraus die Informationen zum "Action-Wort" auszulesen (Variante 2 / Reflexion), wäre vielleicht die eleganteste Lösung, oder? [size=-2](wäre zugegebenermaßen keine ganz eigene Neuerfindung :) )[/size]

Gruß,
Hank Scorpio
 

Ullenboom

Bekanntes Mitglied
Wenn die Web-App geladen wird, alle Klassen suchen, die eine Annotation tragen. Die Map als Assoziativspeicher ist dann ein Cache, ja das ist ratsam, denn pro Request alle Klassen suchen ist nicht so pralle. Wichtig ist, wo man den Cache "ablegt" (Klassenlader bedenken). Auf den Cache kann der Front-Controller zurückgreifen und dann weiterleiten. Den Weg über die Annotationen gehen einige Fameworks, finde ich nett. Sicherlich lohnt es sich, zu lernen, wie andere Frameworks wie Wicket, Spring MVC, Stripes arbeiten.
 
M

maki

Gast
struts 1.x hat so ähnlich funktioniert, erwähnehnenswert ist da auch das Commandpattern, typisiert wäre dann sowas wie eine Map<Command,Controller> möglich.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
LimDul Komplexe Generierung von Java-Klassen aus WSDL Web Tier 1
E Java Servlet doPost request, Mehrere Parameter mit demselben Namen aus Tabellenzeilen Web Tier 2
platofan23 Java Login Überprüfung ohne Srciptlets in der JSP Web Tier 4
Dimax JSP Progress Bar in JSP nur mit Java Web Tier 4
S Einträge aus Datenbank einzeln darstellen (JSP, JAVA, HTML) Web Tier 9
R JavaScript für Java Enterprise Entwickler Web Tier 1
O JSF Java Unsigned Applet PrivilegedActionException Problem Web Tier 2
S JSP Hm... Vorlage für Java Basierende Webseite? Web Tier 0
S Button klick soll Java methode aufrufen Web Tier 2
R Tomcat - java.lang.OutOfMemoryError: PermGen space Web Tier 0
F JSP jSP Datei mit normalem Java Programm auslesen? Web Tier 5
T Spark Java Web Framework Web Tier 0
G Probleme mit Java + Tomcat | Cannot switch on a value of type String for source level below 1.7 Web Tier 8
S java.lang.ExceptionInInitializerError: Wieso??? Web Tier 3
N JSP Free Webhoster Java Backend? PHP? Web Tier 1
D Java EE Servlet login Problem Web Tier 1
L Servlet Java Entschlüsselungsprogramm in Webapplikation einbinden Web Tier 0
Streeber java.lang.NoClassDefFoundError: org/sqlite/NativeDB Web Tier 0
M GWT - Externe Java Libs auf Server Seite - zB. JDBC Web Tier 6
S Java Bean und Java Servlet Web Tier 2
L java.io.NotSerializableException für domain Objekte - Design Problem? Web Tier 12
T Einsteigerfragen zu Servlets/Webprogrammierung mit Java Web Tier 11
J Übergabe von Parameter aus JSP an Java Web Tier 2
nrg Java-Code in Taglib wird nicht richtig ausgeführt. Web Tier 7
D JSF Überprüfen der Session ID in JSF und JAVA Web Tier 9
H JSP, Eclipse, Tomcat - Java Klasse wird nicht gefunden Web Tier 8
B JSF Mojarra 2.1.5: java.lang.IllegalStateException: Cannot create a session after the response has been Web Tier 7
A Parameterübergabe an Servlet und Aufruf von Servlets per Java Code Web Tier 7
J JSF Java Beans Konventionen Web Tier 2
P Blog in Java/JSP Web Tier 5
S Per JavaScript Java ansteuern - Welche Technik? Web Tier 2
T Seam-Komponenten oder Java Bean soll direkt nach Appserver-Start "leben" Web Tier 4
B Thread start bei Java Web Anwendung Web Tier 6
M Suche Java Framework Web Tier 2
B Tomcat 6 ergibt Fehler - java.net.SocketException Web Tier 2
G Probleme mit EclipseLink und Java.util.Date Web Tier 3
ruutaiokwu js kalendar, der mit java.text.SimpleDateFormat kombatibel ist... Web Tier 4
B Java EE 6 Problem (EL) Web Tier 4
F Migration eines CMS von PHP nach JAVA Web Tier 3
R GWT 2.1.1 mit Java 1.6 statt 1.5 Web Tier 8
W JSP - Attribut-Werte aus JAVA-Klasse ? Web Tier 8
T Werte aus java Klasse in jsp nutzen Web Tier 5
N java.lang.NoClassDefFoundError: org/jdom/JDOMException Web Tier 3
M JSP Ausgabe von Java-Objekten Web Tier 7
D JSP, Java Applets einbinden Web Tier 2
LadyMilka java.lang.NumberFormatException: For input string: ... Web Tier 5
H Probleme beim Aufrufen von Java- oder Servlet-Methoden aus Javascript Web Tier 2
K Bilder in Java-Webapplikationen Web Tier 12
S Java Servlet Content Type Web Tier 3
K Analye einer Seite (Java, JSP, ...) Web Tier 12
J rich:modalpanel vom java-code aus öffnen und schliessen Web Tier 2
S Expression Language in Java Web Tier 13
A Ssh connection mit java jsch? Web Tier 2
W Java code aus JSP-File durch JSTL code ersetzen Web Tier 8
M Body onUnload Java Methode aufrufen Web Tier 13
F Frage zu Java Beans Web Tier 17
M Java Framework für größere Projekte verwenden Web Tier 5
U access denied bei Datei Schreiben mit Java unter Linux trotz gesetzter Rechte Web Tier 2
P Java-Program -> Web Programm Web Tier 6
F Java Applets in html einbinden Web Tier 10
A SSL-Zertifikat in Java-Webanwendungen laden Web Tier 4
ruutaiokwu Wert hinter JSP-Tag nach Java-String in Skriptlet Web Tier 4
N java bean in eclipse Web Tier 6
S Java Code in JSF Web Tier 10
N Servlet und java.lang.NoClassDefFoundError Web Tier 4
D request.contextPath in Java-Klasse ausführen Web Tier 5
T In einem Struts Tag Werte mit Java einfügen Web Tier 2
G [JAVA / JSP] ArrayList in JSTL foreach verarbeiten Web Tier 4
G CSV-Anbindung an Java Web Tier 2
G Java Server Face Performancelastig? Web Tier 2
H Java Servlet und HTML Form Web Tier 3
U Java Application auf Tomcat Web Tier 5
G Validierung mit Java Server Faces Web Tier 4
M webapp controller funktioniert nicht Web Tier 3
K Servlet + JSP: JSP-Seite ein Array/ArrayList überliefern vom Controller-Servlet Web Tier 8
H JSF Daten aus ManagedBean können vom Controller gelesen werden Web Tier 6
ruutaiokwu HttpServletRequest-instanz in servlet und JSP unterschiedlich? Web Tier 5
G Eine Instanz pro Managed Bean? Web Tier 2

Ähnliche Java Themen

Neue Themen


Oben