# Grundaufbau der Webapp mit JSP/Servlets



## unclesam (15. Apr 2009)

Hi,
ich arbeite derzeit an einer Webapplikation welche über JSP/Servlets in verbindung mit einem TomCat Server und einer PostgreSQL Datenbank realisiert werden soll.

Die Grundlegenden Sachen wie der Login sowie Registrierung, um in den geschützten Bereich zu gelagen, funktionieren bereits.
Nun habe ich allerdings ein paar grundlegende Fragen was den Einsatz von JSP's und Servlets angeht. Meine aktuelle Umsetzung sieht wie folgt aus:
Ich navigiere derzeit ausschlißlich über JSP's (z.B. im Menü). Innerhalb der JSP's werden für Eingabeüberprüfungen Beans verwendet und für Datenbankabfragen Servlets. Die Ergebnisse aus den DBAbfragen der Servlets werden über includes in die JSP's eingebettet. Bsp.:

regis.jsp

```
<table class="regis">
            <% pageContext.include("RegisHS_SG");%>
...
</table>
```
RegisHS_SG.java (Servlet)

```
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Connection connection = null;
        PreparedStatement pstmt_sg = null;
        PreparedStatement pstmt_hs = null;
        ResultSet rs_hs = null;
        ResultSet rs_sg = null;
        try{
            connection = getConnection();
            String sql_string = "SELECT sg_name FROM studiengang";
            pstmt_sg = connection.prepareStatement(sql_string);
            sql_string = "SELECT hs_name FROM hochschule;";
            pstmt_hs = connection.prepareStatement(sql_string);
            rs_hs = pstmt_hs.executeQuery();
            rs_sg = pstmt_sg.executeQuery();
            PrintWriter out = response.getWriter();
            out.print("<tr>\n<td class=\"row1\">Hochschule:</td>\n<td><select name=\"hochschule\" size=\"1\" class=\"lang\">");
            while(rs_hs.next()) {
                out.print("<option>" + rs_hs.getString(1) + "</option>");
            }
            out.print("</select>\n</td>\n<td></td></tr>");
            out.print("<tr>\n<td class=\"row1\">Studiengang:</td>\n<td><select name=\"studiengang\" size=\"1\" class=\"lang\">");
            while(rs_sg.next()) {
                    
                out.print("<option>" + rs_sg.getString(1) + "</option>");
            }
            out.print("</select>\n</td>\n<td></td></tr>");
            connection.close();
```

Für aufwendigere Abfragen, welche beispielsweise an mehreren/unterschiedlicheren Positionen in der JSP etwas hereinschreiben sollen, ist diese Lösung sehr unpraktisch. Für diese Fälle hatte ich mir überlegt, dass ich einfach die ResultSets an den Request (als Attribute) hänge und diese in den JSP's an den jeweiligen Stellen auslese.


Nun Stelle ich mir jedoch die Frage, ob ich nicht komplett falsch an die Sache herangegangen bin und ich nicht eher über die Servlets navigieren sollte um in diesen (nach den DBAbfragen + Anhängen der ResultSets an den Request) auf die JSP's weiter zu leiten.

mfg

unclesam


----------



## maki (15. Apr 2009)

> Nun Stelle ich mir jedoch die Frage, ob ich nicht komplett falsch an die Sache herangegangen bin und ich nicht eher über die Servlets navigieren sollte um in diesen (nach den DBAbfragen + Anhängen der ResultSets an den Request) auf die JSP's weiter zu leiten.


Ja, das sehe ich auch so.
Suche mal nach Model2 bzw. MVC.
Da sind die JSP allein für das generieren von HTML zuständig, Servlets nur für Logik.
Jedenfalls ist es keine gute Idee, HTML, CSS und JavaScript von einem Servlet erzeugen zu lassen, wird sehr sehr unübersichtlich wie du siehst.

Kann dir nur empfehlen zumindest die JSTL anzusehen (Taglib für JSPs), EL (Expression Language) wäre imho auch wichtig.
Denn Java Code in JSP einzubauen ist genauso schlimm wie HTML/CSS/JavaScript in Servlets erzeugen zu lassen 

Ansonsten gibt es sehr viele Frameworks für Java Webanwendungen, denn speziell JSP ist eigentlich nicht sehr ausgereift und lässt viel Raum für Verbesserungen/Erweiterungen.
struts ist ein weit verbreitetes, wenn auch heute nicht mehr ganz aktuelles MVC Framwork.
Tiles oder Sitemesh nimmt man für sog. "Composite View", also wiederverwendbare Fragmente (Formulare oder jedes andere Fragment was man öfters mal braucht) die dann zu einer Seite zusammengesetzt werden. 

Von JSF wärest du am Anfang erst erschlagen der Komplexität wegen.


----------



## unclesam (15. Apr 2009)

Also das in die JSP kaum JavaCode rein soll, ist mir bewusst.
Das ist bei mir auch eigentlich nicht der Fall (oben war nur ein sehr kleiner Ausschnitt). Ich habe unten mal meine Regis.jsp gepostet und ich denke das dies den MVC-Ansatz (Modell1) erfüllt. Eine "umstellung" auf Modell2 würde doch im Prinzip bedeuten, dass ich die Form nicht rekursiv wieder auf die Regis.jsp verlinke, sondern auf das Servlet "Regis". Dieses würde dann die validierung der Eingabe übernehmen und entweder wieder auf die regis.jsp lenken (mit anderen Standardwerten)  oder bei positiver eingabeüberprüfung auf die regisssuccess.jsp.

Sehe ich das soweit richtig oder wäre diese Veränderung noch nicht ausreichend genug um Logik und Präsentation besser zu trennen?


```
<%@ taglib uri="/WEB-INF/tlds/layout.tld" prefix="layout" %>
<%@ taglib uri="/WEB-INF/tlds/date.tld" prefix="date" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<layout:Layout layout="header" titel="Registrieren - studplan.de" />
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@page import="java.text.SimpleDateFormat,java.util.List"%>
<%@page import="java.util.Date"%>

<%
    String jahrs = new SimpleDateFormat("yyyy").format(new Date());
    int nowjahr = new Integer(jahrs);
%>
<%-- Bean initialisieren --%>
<jsp:useBean id="checker" class="check.inputchecker" scope="request"/>
<%-- Alle request Parameter übergeben --%>
<jsp:setProperty property="*" name="checker"/>
<%
    if(checker.validate()){
        request.setAttribute("checker",checker);
        //request.getRequestDispatcher("Regis").include(request,response);
        pageContext.forward("regissuccess.jsp");
        //response.sendRedirect("regissuccess.jsp");
    }
    List<String> errors = checker.getErrors();
%>

<div id="content">
        <h1>Registrieren</h1>
        <div class="post">
            <p>Erstelle deinen eigenen kostenlosen Account.</p>
            <form method="POST" action="regis.jsp">
            <table class="regis">
                <tr>
                    <td class="row1">Nickname:
                        <%
                        if (errors.contains("nickname")) {
                    %>
                        <font color="red">*</font>
                        <%
                            }else out.print("*");
                        %>
                    </td>
                    <td><input type=text name="nickname" value="${param.nickname}"></td>
                    <td><small>Maximal 40 Zeichen lang.</small></td>        
                </tr>
                <tr>
                    <td class="row1">EMail:
                        <%
                        if (errors.contains("email")) {
                    %>
                        <font color="red">*</font>
                        <%
                            }else out.print("*");
                        %>
                    </td>
                    <td><input type=text name="email" value="${param.email}"></td>
                    <td><small>Maximal 30 Zeichen lang.</small></td>        
                </tr>
                <tr>
                    <td class="row1">Passwort:<font color="red">*</font></td>
                    <td><input type=password name="passwort" value=""></td>
                    <td></td>    
                </tr>
            </table>
            <table class="regis">
                <% pageContext.include("RegisHS_SG");%>
                <tr>
                    <td class="row1">Immatrikuliert seit:
                    </td>
                    <td>
                        <%-- Schleife für die letzen 20 Jahre.--%>
                        <select name="immatjahr" size="1">
                        <%
                            int immitjahr = checker.getImmatjahr();
                        %>
                        <date:year repeat="20" option="true" selected="2000"/>
                        
                        
                        <%--for(int i = (int)nowjahr; i >= ((int)nowjahr -20);i--){
                            if(checker.getImmatjahr() == i){
                                out.print("<option selected=\"selected\">"+i+"</option>");
                            } else {
                                out.print("<option>"+i+"</option>");
                            }
                        }--%>
                        </select>
                    </td>
                    <td></td>        
                </tr>
                <tr>
                    <td class="row1">Winter- oder Sommersemester?</td>
                    <td>
                        <select name="immatsaison" size="1">
                            <c:if test="${param.immatsaison != \"SS\"}">
                                <option value="WS" selected="selected">Wintersemester</option>
                                <option value="SS">Sommersemester</option>
                            </c:if>
                            <c:if test="${param.immatsaison == \"SS\"}">
                                <option value="WS">Wintersemester</option>
                                <option value="SS" selected="selected">Sommersemester</option>
                            </c:if>
                        </select>
                    </td>
                    <td></td>        
                </tr>
                </table>
                <p>Optionale Angaben:</p>
                <table class="regis">
                <tr>
                    <td class="row1">Vorname:
                    <% if (errors.contains("vorname")) {%>
                        <font color="red">*</font>
                    <%}%>
                    </td>
                    <td><input type=text name="vorname" value="${param.vorname}"></td>        
                </tr>
                <tr>
                    <td class="row1">Nachname:
                    <% if (errors.contains("nachname")) {%>
                        <font color="red">*</font>
                    <%}%>
                    </td>
                    <td><input type=text name="nachname" value="${param.nachname}"></td>        
                </tr>
                <tr>
                    <td class="row1">Geburtsdatum:
                    <% if (errors.contains("geburtsdatum")) {%>
                        <font color="red">*</font>
                    <%}%>
                    </td>
                    <td>
                    <select name="tag" size="1" >
                        <option value="">Nicht angeben</option>
                        <c:forEach var="i" begin="1" end="31" step="1">
                            <c:if test="${param.tag == i}">
                                <option selected="selected"><c:out value="${i}"/></option>
                            </c:if>
                            <c:if test="${param.tag != i}">
                                <option><c:out value="${i}"/></option>
                            </c:if>
                        </c:forEach>
                    </select>
                    <select name="monat" size="1">
                        <option value="">Nicht angeben</option>
                        <c:forEach var="i" begin="1" end="12" step="1">
                            <c:if test="${param.monat == i}">
                                <option selected="selected"><c:out value="${i}"/></option>
                            </c:if>
                            <c:if test="${param.monat != i}">
                                <option><c:out value="${i}"/></option>
                            </c:if>
                        </c:forEach>
                    </select>
                    <select name="jahr" size="1">
                        <option value="">Nicht angeben</option>
                        <% for(int i = (int)nowjahr; i >= ((int)nowjahr -50);i--){
                            if(checker.getJahr() == i){
                                out.print("<option selected=\"selected\">"+i+"</option>");
                            } else {
                                out.print("<option>"+i+"</option>");
                            }
                        }%>
                    </select>
                    </td>        
                </tr>
                <tr>
                    <td>Geschlecht:</td>
                    <td>
                        <select name="geschlecht" size="1">
                            <option value="">Nicht angeben</option>
                            <c:if test="${param.geschlecht == \"w\"}">
                                <option value="w" selected="selected">Weiblich</option>
                                <option value="m">Männlich</option>
                            </c:if>
                            <c:if test="${param.geschlecht == \"m\"}">
                                <option value="w">Weiblich</option>
                                <option value="m" selected="selected">Männlich</option>
                            </c:if>
                            <c:if test="${param.geschlecht == \"\" || param.geschlecht == null }">
                                <option value="w">Weiblich</option>
                                <option value="m">Männlich</option>
                            </c:if>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type=submit value="Abschicken"></td>
                </tr>
            </table>
            </form>
        </div>
    </div>
<layout:Layout layout="login" />
<layout:Layout layout="footer" />
```


----------



## The_S (15. Apr 2009)

In eine JSP gehört nicht wenig Java-Code, sondern gar keiner! Für sowas gibt es Taglibs.


----------



## maki (15. Apr 2009)

Kann The_S nur zustimmen, aber davon abgesehen ist Model1 kein MVC, sondern erst Model2 

Dabei gehen alle Request (bis auf Bilder, CSS und JS Referenzen) zuerst an ein Servlet (der Controller), dieses verarbeitet Daten und leitet dann an JSPs weiter.


----------



## unclesam (15. Apr 2009)

ah ok, dass würde also bei meinem konkreten Beispiel bedeuten:

Ich habe z.B. das Servlet "/verteiler" auf welches ich aus jeder JSP verlinke. Dieses Servlet schaut nun welches andere Servlet für die gesuchte Anfrage (z.B. für eine Registrierung -> /regis) verantworlich ist und leitet via forward den request weiter.
Das Servlet "/regis" holt sich nun z.B. eine Liste von Hochschulen aus der Datenbank und fügt diese als Attribut in den Request hinzu (oder setzt Standardwerte für Name...). 
Anschließend wird dann vom Servlet "/regis" bestimmt, dass die JSP regis.jsp aufgerufen wird in welcher die Hochschulen ausgegeben werden oder beispielweise in einem Formular, für das Inputfeld "Name" ein Standardwert eingefügt wird (${param.name}).
Sollte nun in der regis.jsp ein Formular abgeschickt werden, so wird dieses immer an das Servlet "/verteiler" geleitet, welches wiederum erkennt das die Anfrage von der regis.jsp kam und deswegen die "arbeit" an das Servlet "/regis" übergibt. Im Servlet "/regis" würde nun überprüft werden ob die Formulardaten ok sind und würde entweder bei Eingabefehlern wieder auf die regis.jsp oder bei keinen Eingabefehlern z.B. auf die regissuccess.jsp weiterleiten (in welcher einfach alle Eingaben nochmal ausgegeben werden).

Verstehe ich das soweit richtig?


EDIT: Wobei mich hier nochmal interessieren würde, wie ich bei einem normalen <a href="/verteiler"> Link, auf ein Servlet verweise und diesem mitteile das ich gerne zur registrierungsServlet möchte und nicht zum ausloggServlet.


----------



## maki (15. Apr 2009)

> Verstehe ich das soweit richtig?


Ja, denke schon.

Falls das dein erstes Java WebApp Projekt ist das so ok, man sollte es zumindest einmal "zu Fuß gemacht haben, einmal wegen dem Verständnis der Grundlagen, und dann noch dass man Framneworks zu schätzen, weil sie einem soviel abnehmen.
Für die Zukunft (oder gleich, wie du willst) kann ich dir da wie gesagt struts empfehlen.



> EDIT: Wobei mich hier nochmal interessieren würde, wie ich bei einem normalen <a href="/verteiler"> Link, auf ein Servlet verweise und diesem mitteile das ich gerne zur registrierungsServlet möchte und nicht zum ausloggServlet.


Kannst ja Parameter(GET/POST) mitschicken, woran der Controller erkennt was er damit machen soll.
Typischer Name für so einen Parameter wäre zB. "command".

Hier mal als GET Parameter

```
<a href="/verteiler?command=logout">
```

Ps: Der link wird so nicht funktionieren, da der Name des Web Contextes fehlt.


----------



## unclesam (15. Apr 2009)

In Struts hatte ich mich auch schon mal (vor einer Woche) hereingelesen, jedoch weiss ich nicht ob wir das Framework benutzen dürfen (es handelt sich hier um ein Uni Projekt), da es evtl. zuviel arbeit abnimmt.

Und da ich die Frage ob wir Struts verwenden dürfen bereits seit einer Woche noch nicht beantwortet bekommen habe (seitens der Verantworlichen  ) will ich nun auch nicht mehr länger warten und mache es halt ohne :/ ...

vielen Dank euch beiden für die nette und schnelle Hilfe!!!!

unclesam


----------

