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;
}