Java™ Servlet Technologie
zurück weiter
Java™ Servlet Technologie

Anwendungsbeispiel


Die Hilfsklasse PageGenerator

Im Kapitel Grundlagen wurde an einem einfachen Beispiel erklärt, wie man mit Hilfe eines Servlets eine dynamische HTML-Seite generieren kann. Dabei konnte man erkennen, daß der gesamte HTML-Code der zu erzeugenden Web-Seite innerhalb des Quell-Codes des Servlets formuliert wurde. Das angesprochene Beispiel wird nachfolgend nochmals auszugsweise dargestellt.

    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
    {
        // Medientyp festlegen und PrintWriter spezifizieren
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        // Generierung der HTML-Seite
        out.println("<HTML><HEAD></HEAD><BODY>");
        out.println("Serverzeit: " + new Date() + "<BR>");
        // Ermitteln der Client-URL aus dem Request
        out.println("URL des Client: " + request.getRemoteHost());
        out.println("</BODY></HTML>");
    }
    
Außerdem ist zu berücksichtigen, daß auch eine dynamisch generierte HTML-Seite einen statischen Anteil besitzt, der in der Regel nur um dynamische Inhalte erweitert wird. In unserem Beispiel besteht der dynamische Anteil aus der darzustellenden Serverzeit und der URL des Client.

Soll nun eine Web-Seite generiert werden, deren Inhalt sehr umfangreich ist, so kann dies im Quell-Code des Servlets infolge sehr vieler println()-Befehle ziemlich unübersichtlich werden. Außerdem ergibt sich auch die Problematik, daß bei einer eventuell erforderlichen Änderung des oft sehr großen statischen Anteils des HTML-Codes die Veränderungen am Quell-Code des Servlets vorgenommen werden müssen und somit eine erneute Kompilierung erforderlich wird. Um nun diese Problematik zu umgehen, stellt die Klasse PageGenerator die Methoden readPage(String filename) und replaceParam(String src, String ins, String dummy) zur Verfügung. Die Idee dabei ist, den statischen Anteil einer HTML-Seite aus einer vorgefertigten Textdatei einzulesen, in der die dynamischen Anteile durch eindeutig erkennbare Platzhalter gekennzeichnet sind. Diese Platzhalter brauchen dann nur noch innerhalb des Servlets durch die zur Laufzeit erzeugten dynamischen Anteile ersetzt werden, bevor das PrintWriter-Objekt die generierte Web-Seite an den Client zurückgibt. Nachfolgend wird nun zunächst die Methode readPage(String filename) vorgestellt.


    // Einlesen einer HTML-Datei und Speichern in einem String
    public String readPage(String filename) throws Exception {
        RandomAccessFile inFile = new RandomAccessFile(filename,"r");
        // Puffer entsprechend Dateigröße bereitstellen
        byte buffer[] = new byte[(int)inFile.length()];
        // Datei einlesen
        inFile.read(buffer);
        // Dateiinhalt in Form eines String zurückgeben
        return (new String(buffer));
    }
    
Zur Kennzeichnung der Platzhalter wird im Beispielprojekt folgende Notation verwendet: @Platzhaltername@. Die Notation ist natürlich frei wählbar, muß aber innerhalb der HTML-Quelldatei eindeutig sein. Die Methode replaceParam(String src, String ins, String dummy) besitzt drei Übergabeparameter. Der String src beinhaltet dabei den Inhalt der mittels readPage(String filename) eingelesenen Textdatei. Während nun der String ins dynamisch generierten Inhalt enthält, bezeichnet dummy den eindeutigen Platzhalter, der durch den Inhalt von ins ersetzt werden soll. Nachfolgend wird diese Methode nun näher beschrieben.

    // Ersetzen von Platzhaltern
    public String replaceParam(String src, String ins, String dummy) {
        // Position des ersten Vorkommens des Platzhalters innerhalb des Strings src ermitteln
        int pos = src.indexOf(dummy);
        // String src unverändert zurückgeben, falls Platzhalter nicht vorkommt
        if (pos == -1) return src;
        // ansonsten StringBuffer-Objekt zur String-Manipulation anlegen
        StringBuffer buf = new StringBuffer(src);
        // alle Vorkommen des Platzhalters suchen und ersetzen
        do {
            // Ersetzung eines gefundenen Platzhalters durchführen
            buf.replace(pos,pos+dummy.length(),ins);
            // nach weiterem Vorkommen des Platzhalters suchen
            pos = buf.indexOf(dummy);
        } while (pos != -1);
        // manipulierte String zurückgeben
        return buf.toString();
    }
    
Neben einfachen Zeichenfolgen, wie etwa im obigen Beispiel, handelt es sich bei den dynamischen Anteilen einer zu generierenden HTML-Seite auch oft um Tabellen oder Auswahlboxen. Um die bei Datenbankabfragen ermittelten Ergebnismengen, welche in Form eines Vector()-Objektes vorliegen, als Tabelle beziehungsweise Auswahlbox darstellen zu können, macht sich eine entsprechende Formatierung im HTML-Standard erforderlich. Zu diesem Zweck stellt die Klasse PageGenerator die beiden Methoden formatTable(Vector list, int cols, String[] param) und formatSelect(Vector list, String[] param, String selected, int mode) bereit, die im Folgenden näher beschrieben werden sollen.

Die Methode formatTable(Vector list, int cols, String[] param) generiert anhand der Inhalte eines Vector()-Objektes, welches im Übergabeparameter list enthalten ist, eine Tabelle gemäß HTML-Syntax. Der Parameter cols gibt dabei an, wie viele Spalten die zu generierende Tabelle enthalten soll. Außerdem können über den Übergabeparameter param Formatierungsparameter für Tabellen-Tags (z.B. Festlegen der Hintergrundfarbe einer Tabellenzeile) und Tabelleninhalte (z.B. Formatierung von Schriften) festgelegt werden.


    // Generierung von Tabellen im HTML-Format
    public String formatTable(Vector list, int cols, String[] param) {
        String result = "";
        // Prüfung, ob Vector()-Objekt nicht null ist
        if (list != null) {
            // Anzahl der Einträge im Vector()-Objekt ermitteln
            int anz = list.size();
            // Anzahl der Zeilen ermitteln
            int rows = anz/cols + anz%cols;
            // Tabellenzeilen generieren
            for(int i=0; i<rows; i++) {
                // einleitender TR-Tag mit event. Parametern
                result += "<TR";
                if (param[0] != "") result += " " + param[0];
                result += ">\n";
                // Spalteninhalte
                for (int j=0; j<cols; j++) {
                    // einleitender TD-Tag mit event. Parametern
                    result += "<TD";
                    // eventuellen Parameter einfügen
                    if (param[1] != "") result += " " + param[1];
                    // einleitender TD-Tag schließen
                    result += ">";
                    // event. einleitenden Parameter innerhalb der Spalte
                    if (param[2] != "") result += param[2];
                    // eigentlichen Spalteninhalt aus Stringliste einfügen
                    if (i*cols+j <=anz) result += (String)list.elementAt(i*cols+j);
                    // event. abschließenden Parameter innerhalb der Spalte
                    if (param[3] != "") result += param[3];
                    // schließender TD-Tag
                    result += "</TD>\n";
                }
                // schließender TR-Tag
                result += "</TR>\n";
            }
        }
        // Rückgabe des formatierten Strings
        return result;
    }
    
Hinweis: Die anfängliche Prüfung, ob das Vector()-Objekt null ist, ist unbedingt erforderlich, da bei einer Datenbankabfrage mit leerer Ergebnismenge null zurückgegeben wird.

Bei der Generierung von Auswahlboxen müssen der Methode formatSelect(Vector list, String[] param, String selected, int mode) ebenfalls ein Vector()-Objekt list mit den darzustellenden Inhalten sowie ein String-Feld param mit eventuellen Formatierungsparametern (z.B. Name der SELECT-Box, Zuweisung von JavaScript-Ereignisroutinen, ...) als Parameter übergeben werden. Desweiteren ist es möglich, durch Übergabe eines bestimmten Wertes im Parameter selected den übereinstimmenden Eintrag in der Auswahlbox als vorselektiert darzustellen. Der Übergabeparameter mode bestimmt schließlich das Verhalten der Methode bei Übergabe eines leeren Vector()-Objektes. Wird in einem solchen Fall für mode der Wert "0" angegeben, so wird ein Leer-String zurückgegeben, ansonsten eine SELECT-Box ohne Inhalt.


    // Generierung von SELECT-Boxen im HTML-Format
    public String formatSelect(Vector list, String[] param, String selected, int mode) {
        String result = "";
        int anz = 0;
        boolean empty = true;
        // Prüfung, ob Vector()-Objekt ungleich null ist
        if (list != null) {
            // Ermittlung, ob Vector()-Objekt leer ist
            empty = (list.size() <= 0);
            // Ermittlung der Anzahl von Elementen im Vector()-Objekt
            anz = list.size();
        }
        // einleitenden SELECT-Tags mit seinen Parametern generieren
        result = "<SELECT";
        for (int i=0; i<param.length; i++) result += " " + param[i];
        result += ">\n";
        // Einträge der Auswahlbox formatieren, falls vorhanden
        if (!empty) {
            // Standard-Eintrag
            result += "<OPTION value=''>Bitte wählen</OPTION>\n";
            // Optionen generieren
            for(int i=0; i<anz; i+=2) {
                // event. Vorselektierung berücksichtigen
                if (((String)list.elementAt(i)).equals(selected))
                    result += "<OPTION selected value='";
                else
                    result += "<OPTION value='";
                // Fortsetzung der OPTION-Zeichenfolge
                result += (String)list.elementAt(i) + "'>"+ (String)list.elementAt(i+1) + "</OPTION>\n";
            }
        }
        // SELECT-Tag schließen
        result += "</SELECT><BR>\n";
        // Leer-String erzeugen, falls keine Einträge vorhanden sind und kein leeres SELECT-Objekt zurückgegeben werden soll
        if ((mode == 0) && empty) result = "";
        // formatierten String zurückgeben
        return result;
    }
    

zurück weiter