JSP CMS Logik - MVC

Michoel

Aktives Mitglied
Hallo Leute,
ich will eine Kleinigkeit mit Login programmieren. Am Besten nach dem MVC-Modell.
Genutzt wird Tomcat mit JSP.


Findet ihr diesen folgenden Aufbau schlecht.

Die erste index.jsp leitet auf folgendes Schema weiter:
domain.tld/webapp/main.jsp?page=firstpage

D.h., alle Seiten werden zentral über eine main.jsp eingebettet mit:
<jsp:include page="<%= page+&quot;.jsp&quot; %>" />

Die main.jsp baut eine Mysql-Verbindung auf und speichert es in die Session. D.h., die eingebetteten Seiten könnten auf die Mysql-Verbindung zugreifen.
Man soll aber natürlich keine Java-Codes in JSP-Seiten einfügen. Habe aber auch keine Erfahrung mit Beans, weswegen bei mir etwas Code eingebettet wird.

Wie würdet ihr die Seiten nach dem main.jsp-Prinzip dann in etwa aufbauen? (Die Variablen usw., die in main.jsp deklariert werden, können ja in der firstpage usw. nicht genutzt werden. Eventuell hätte diese main.jsp dann wenig Vorteil ne? (Wobei man in main.jsp immer schön einen Header und Footer einfügen könnte oder muss dies explizit in allen Seiten manuell machen.

Über Meinungen und Tipps wäre ich auch sehr dankbar.

Grüße
M.
 
N

nillehammer

Gast
Was Du hier mit main.jsp umsetzt, nennt sich FrontController. Das ist ein gängiges Verfahren. Insofern ist die Idee schon recht gut. Allerdings wird sowas dann eher mit Servlets gemacht. Versuche, in JSPs wirklich nur die Tags für die Darstellung zu implementieren. Sämtliche Links und Formular-Actions gehen auf Servlets mit entsprechenden doGet- bzw. doPost-Methoden.

P.S. Abgesehen davon ist das Programmieren gerade mit JSPs (und mit Einschränkungen auch Servlets) doch sehr old- fashioned. Ich finde die für das Lernen von Grundlagen zwar noch recht gut. Aber denke darüber nach, möglichst schnell auf ein Webapp-Framework umzusteigen.
 

Michoel

Aktives Mitglied
Hi,
danke für die schnelle Antwort und die Anregung. Ein Framework will ich noch nicht einsetzen, um den Ablauf selber erst noch etwas zu verstehen und mich in das Coding (JSP, Java, HTML) etwas einzufinden.

Wie ruft man jedoch in der URL als FrontController direkt ein Servlet auf, statt eine JSP?
Die Servlets sind ja nicht über die Adresszeile erreichbar.

D.h., das Servlet würde dann die JSP einbinden, bzw. auf die JSP redirekten?
Ich müsste mir dann noch anschauen, wie ich von einem Form (doGet) wieder auf das Servlet verweise. Ein Formular schickt ja in Prinzip wie die Frage oben den Befehl über die Adresszeile.

Hier fehlt mir noch die Verlinkung irgendwie :)

Grüße
 

Michoel

Aktives Mitglied
Einwenig vorangekommen bin ich schon.
Über die web.xml kann ich vom Namen der URL auf ein Servlet verweisen.
D.h., ich kann meine Programmierung im Servlet machen. Bsp. den Usernamen, Passwort vom Request genauso einlesen, die Prüfung machen, ob Passwort stimmt.

Nun könnte man zwar im Servlet auch gleich die Ausgabe erzeugen mit put.println. Das wäre aber wieder nicht sinnvoll.
Wie komme ich praktisch vom Servlet wieder zurück zurück in die JSP, bzw. mache ich die Ausgabe in JSP. (Indem der Front-Controller jedoch auch immer angesprochen bleibt in der URL?)


Noch eine kleine Zusatzfrage. Baut ihr pro Request immer eine DB-verbindung auf und schließt sie wieder (Bsp. im Front-controller) oder speichert ihr die Verbindung irgendwie zwischen (Bsp. Session?) (Woanders könnte man das ja nicht sinnvoll speichern denke ich?)

Grüße
 
N

nillehammer

Gast
Wie komme ich praktisch vom Servlet wieder zurück zurück in die JSP, bzw. mache ich die Ausgabe in JSP. (Indem der Front-Controller jedoch auch immer angesprochen bleibt in der URL?)
Je nach Anwendungsfall machst Du einen forward (die Anfrage wird intern weitergeleitet) oder einen redirect (die Anfrage wird mit der Aufforderung an den Browser beantwortet, sich die seite neu zu laden
Java:
public void doGet(HttpServletRequest request, HttpServletResponse response) {
   // Forward geht so. Die Anfrage wird intern weitergeleitet, also gibtst Du hier die jsp an
   String nextJSP = "/searchResults.jsp";
   RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(nextJSP);
   dispatcher.forward(request,response);

   // Redirect geht so: die U R L muss also so sein,
   // wie der Browser sie aufrufen soll (als hättest Du sie in einem Link)
  response.sendRedirect("/UrlZumFrontController?page=neueSeite");
}
Noch eine kleine Zusatzfrage. Baut ihr pro Request immer eine DB-verbindung auf und schließt sie wieder (Bsp. im Front-controller) oder speichert ihr die Verbindung irgendwie zwischen (Bsp. Session?) (Woanders könnte man das ja nicht sinnvoll speichern denke ich?)
So klein ist die garnicht. Wenn Du es ganz richtig machen willst, lässt Du Deinen Webcontainer die Connections managen und holst sie Dir über JNDI. Für den Anfang kann man bei jedem Request die Connection aufmachen. Das ist zwar nicht geeignet für Produktivcode, aber Du willst ja schrittweise lernen.
 
Zuletzt bearbeitet von einem Moderator:
N

nillehammer

Gast
Zwei Tipps noch:
- Wenn Du zuverlässig verhindern willst, dass ein Nutzer Deine JSPs unter Umgehung Deines Frontcontrollers direkt aufruft (weil er die Namen kennt und die Adresszeile entsprechend ändert), dann leg sie in einen Ordner unter WEB-INF ab, bspw WEB-INF/jsp. Der Forward-Code muss dann entspr. angepasst werden
- Für Sachen, die bei jedem Request passieren sollen, bietet es sich an, einen javax.servlet.Filter zu implementieren und in der web.xml zu registrieren (geht so ähnlich wie bei Servlets).
 

Michoel

Aktives Mitglied
Vielen Dank für die Tipps.


Wenn Du zuverlässig verhindern willst, dass ein Nutzer Deine JSPs unter Umgehung Deines Frontcontrollers direkt aufruft (weil er die Namen kennt und die Adresszeile entsprechend ändert), dann leg sie in einen Ordner unter WEB-INF ab, bspw WEB-INF/jsp. Der Forward-Code muss dann entspr. angepasst werden

Die Seiten, die eingebunden werden sind ja eh JSP-Seiten, die nur Design enthalten sollten. Von daher wäre ja ein direkter Aufruf nicht tragisch


Eine andere Frage, wenn der Controller kein Servlet wäre, sondern ein JSP und der Controller dieSeite per include page einfügt.

Sollte die eingefügte Seite (include page) eigentlich auf die Variablen usw. vom Controller zugreifen können?


Vielen lieben Dank auch für den Anwedungsfall. Dann ist mir klar, wie ich vom Servlet wieder zurückkomme. JSP hat ja bestimmte Tags, wo man dann größere Mengen von Ergebnisse (bsp. Listen) durchzählen und dementsprechend wie HTML ausgeben kann. Das schaue ich mir heute noch an. Ansonsten wenn ich ein Ergebnis in einem Vector habe und nicht mit den bestimmten Tags arbeiten will, sondern doch einwenig Java-Code im JSP, dann kann ich ein Vector ja nicht über den Request übergeben.


So klein ist die garnicht. Wenn Du es ganz richtig machen willst, lässt Du Deinen Webcontainer die Connections managen und holst sie Dir über JNDI. Für den Anfang kann man bei jedem Request die Connection aufmachen. Das ist zwar nicht geeignet für Produktivcode, aber Du willst ja schrittweise lernen.
Danke, JNDI sagt mir nichts, werde mich aber in dein Stichwort einarbeiten. (Wobei ich für den Webcontainer Tomcat kein Beispiel gefunden habe: JNDI (Java Naming and Directory Interface)). Da schaue ich aber noch.
Ansonsten könnte ich die SQL Verbindung in eine Session speichern. Ist halt nur blöd, wenn viele Nutzer die Applikation ohne Logout verlassen.
Wie gesagt, JNDI hört sich gut an. Danke nochmals.
 
N

nillehammer

Gast
Michoel hat gesagt.:
Die Seiten, die eingebunden werden sind ja eh JSP-Seiten, die nur Design enthalten sollten. Von daher wäre ja ein direkter Aufruf nicht tragisch
Naja schon, wenn Du bspw. in einer JSP die Daten eines Objekts anzeigst, dass Du im Controller in den einen der Scopes (Request, Session, Application) gespeichert hast, ist dieses bei direktem Aufruf der JSP-Seite null und du bekommst u.U. eine Exception. Außerdem disziplinierst Du Dich damit selbst und baust keine Direktlinks auf JSPs in Deine Anwendung, weil die ja schlicht nicht funktionieren.

Michoel hat gesagt.:
Eine andere Frage, wenn der Controller kein Servlet wäre, sondern ein JSP und der Controller dieSeite per include page einfügt.

Sollte die eingefügte Seite (include page) eigentlich auf die Variablen usw. vom Controller zugreifen können?
Wenn ich richtig in Erinnerung habe, geht das nicht. Das ist anders als bei PHP. Jede JSP ist wie eine eigene Java-Klasse mit ihren eigenen (privaten) Variablen (im Hintergrund macht der Tomcat aus JSPs tatsächlich erstmal Java-Klassen, die er dann kompiliert). Der gemeinsame Speicherbereich sind die Scopes (Request, Session, Application). Aber wenn Du Lust hast, bau ein kleines Beispiel und straf mich evtl. Lügen. Dann gibt's ein Danke von mir. ;)

Michoel hat gesagt.:
Ansonsten wenn ich ein Ergebnis in einem Vector habe und nicht mit den bestimmten Tags arbeiten will, sondern doch einwenig Java-Code im JSP, dann kann ich ein Vector ja nicht über den Request übergeben.
Bin nicht sicher, ob ich Deine Frage/Deine Aussage verstanden habe... Du kannst in den Scopes (Request, Session, Application) Objekte beliebigen Typs unter einem frei wählbaren Namen mit der Methode setAttribute speichern. Also im Servlet einen Vector unter einem bestimmten Namen in den Request rein, dann forwarden, in der JSP rausholen und anzeigen geht schon. Bei einem redirect geht das natürlich nicht. Hier kannst du nur Parameter an die redirect-URL anhängen, weil dies zu einem neuen Request führt und die Daten des alten damit verloren sind. Aber die Session lebt ja länger...

Michoel hat gesagt.:
Wobei ich für den Webcontainer Tomcat kein Beispiel gefunden habe
Die Anleitung zum Thema Datasource/Connections über JNDI im Tomcat findest Du hier:Apache Tomcat 7 (7.0.27) - JNDI Datasource HOW-TO
Die Anleitung zu JNDI allgemein hier: Apache Tomcat 7 (7.0.27) - JNDI Resources HOW-TO
Damit bin ich ganz gut zurecht gekommen.
 
Zuletzt bearbeitet von einem Moderator:
N

nillehammer

Gast
Habe mir den Thread gerade nochmal durchgelesen und bin auf Deine Aussage gestoßen:
Michoel hat gesagt.:
Ich müsste mir dann noch anschauen, wie ich von einem Form (doGet) wieder auf das Servlet verweise. Ein Formular schickt ja in Prinzip wie die Frage oben den Befehl über die Adresszeile.
Bei einem Suchformular kann man es machen. Dann hat man die Suchparameter in der Url und der Nutzer kann sie sich ggf. als Favoriten speichern.

Aber bei allem, was irgendwas auf dem Server ändert (Login-Formular, Edit-Formulare etc.), nimm bitte Post. Im Form-Tag wählst Du dafür die Action post und handelst den Request in der doPost-Methode ab. Um die lästigen Meldungen beim Betätigen des Back-buttons zu umgehen, implementierst Du das Post-Redirect-Get-Pattern. Sprich Du antwortest auf Post-Requests nie direkt mit einem Response, sondern immer mit einem Redirect. (Wie das geht, weißt Du ja schon und damit hast du auch endlich einen Anwendungsfall)

Puuh, das ist für den Anfang schon eine ganze Menge. Viel Spaß erstmal beim Ausprobieren.
 

Michoel

Aktives Mitglied
Wenn ich richtig in Erinnerung habe, geht das nicht. Das ist anders als bei PHP. Jede JSP ist wie eine eigene Java-Klasse mit ihren eigenen (privaten) Variablen (im Hintergrund macht der Tomcat aus JSPs tatsächlich erstmal Java-Klassen, die er dann kompiliert). Der gemeinsame Speicherbereich sind die Scopes (Request, Session, Application). Aber wenn Du Lust hast, bau ein kleines Beispiel und straf mich evtl. Lügen. Dann gibt's ein Danke von mir.

Ja, ich habe es getestet. Wenn ich solch einen Aufbau habe "domain.tld/webapp/main.jsp?page=firstpage" und in main.jsp die "firstpage" include, kann man in firstpage nicht auf die variablen von main.jsp zugreifen. Wenn man jedoch in fristpage ein include von secondpage hat, kann man in secondpage auf die variablen zugreifen, die man in firstpage definiert hat.



Aber bei allem, was irgendwas auf dem Server ändert (Login-Formular, Edit-Formulare etc.), nimm bitte Post. Im Form-Tag wählst Du dafür die Action post und handelst den Request in der doPost-Methode ab. Um die lästigen Meldungen beim Betätigen des Back-buttons zu umgehen, implementierst Du das Post-Redirect-Get-Pattern. Sprich Du antwortest auf Post-Requests nie direkt mit einem Response, sondern immer mit einem Redirect. (Wie das geht, weißt Du ja schon und damit hast du auch endlich einen Anwendungsfall)

Perfekt. Meine ersten kleinen Seiten mit Login funktioniert schon sehr gut. Aber nicht ganz MVC. Deshalb versuche ich das nun zu optimieren.
Mein Aufbau sieht in etwa so aus, angelehnt an diese Grafik:

MVC-Applied-JSP-Model2.gif

Bzw. wie folgt, wobei das Model, die Datenbank usw. nicht an den JSPs, sondern am Controller hängt:
08_05.gif



Ich habe nun den URL-Aufbau modifiziert:
domain.tld/webapps/Frontcontroller/?param1=test&param2=bla
Die web.xml habe ich dementsprechend angepasst.

Nun kann ich wie von dir geschrieben, die Parameter auslesen, die Bearbeitung machen und dementsprechend auf eine JSP forwarden oder redirecten. (Derzeit habe ich aber im Frontcontroller Servlet statt doPost, doGet drin, da ich die URL wie oben direkt aufrufe und bei der doPost Methode folgende Fehlermeldung erscheint: "HTTP method GET is not supported by this URL")

Nun muss ich weiterüberlegen, wie ich die JSP-Seiten aufbaue und deshalb meine Fragen:
1. D.h., die Servlet könnte bei einem falschen Login auf eine error.jsp weiterleiten und bei einem erfolgreichen Login auf logged.jsp. Den USerObjekt kann ich entweder wie du mir bereits auch erklärt hast in Scope (Session usw.) reinhängen und von der JSP abfragen. Bzw. session.setAttribute("paramname", Objekt). setAttribute und Scope ist ja nicht dasselbe ne?


2. Die error.jsp, logged.jsp würde dann am Anfang und am Ende eine Header.jsp und einen Footer.jsp einfügen. (Müsste ich halt in jeder einzelnen JSP einfügen und frage mich, wie ich das sonst besser machen könnte)

3. Nun frage ich mich auch, wie ich eine news.jsp gestalten würde, bei der sich beispiel der Navibereich bei einem eingeloggten User anders aussieht und bei einem nicht geloggten User ein Loginformular einblendet.

4. Wenn da auch viele Sachen wie Gästebuch, News, Profil usw. usw., wird der Controller sehr überladen. Und er müsste auch auch sehr viele und auch verschiedene Parameter in der URL reagieren. (Ich denke, die letzte Frage wäre etwas komplizierter, weswegen man sich auch die Antwort ersparen könnte)

Grüße
 

Michoel

Aktives Mitglied
Bzgl. Frage 1 mit setAttribute habe ich etwas gefunden:
das HTTP-Session-Objekt. Es kann dazu benutzt werden, Information über den Benutzer von einem Request zum nächsten weiterzureichen.
Dann wäre mir das klar. Dann wäre hier nur die Frage, wie Tomcat das HTTP-Session-Objekt regelt. Wie lang zum Beispiel für ein Client das Objekt gilt, bevor es gelöscht wird, bzw. nicht mehr existiert. Wie man die Scopes einfügt, habe ich nur für die JSP in Bezug auf Beans gefunden, aber nicht, wie man Objekte in Servlets setzen kann?

Code:
<jsp:useBean id="myBean" class="com.example.foo.MyBean" scope="request">
   </jsp:useBean>
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
borobudur Servlet Business-Logik wird bei jedem Request neu erstellt Web Tier 13

Ähnliche Java Themen

Neue Themen


Oben