Servlets , HTML-Befehle, CGI-Methoden , Hash-Tabellen und RandomAccess-Dateien
Ein Protokoll von Peter Buhr

Servlets:

Servlets sind Java-Programme, die auf Servern laufen und für einen standardisierten Informationsaustausch zwischen Server und Clients sorgen. Dies geschieht über das  CGI-Interface (Common Gateway Interface) ---> auf deutsch Allgemeine Vermittlungsrechner-Schnittstelle.
Weil das Programm im Gegesatz zu Java-Applets zentral auf dem Server bearbeitet wird, und nicht autark auf jedem einzelnen Client, können zum Beispiel Online-Gästebücher mit Hilfe von Servlets realisiert werden. Servlets schicken Informationen an die Clients meist in Form von HTML-Dateien zurück. Deswegen soll hier ein kurzer Überblick über HTML gegeben werden.

HTML (Hypertext Markup Language):

HTML besteht aus Informationen für den Benutzer + Informationen für den Browser. Das sind die sogenannten   <...> Tags.

Rahmen-Tags:

<html>   // HTML-Grundgerüst
    <head>  // "HTML-Kopf"
    <title>Titeltext</title>  // Das was oben in der Browserleiste als Name angezeigt wird
        <script language="Javascript">   // eventuell werden hier Scripts reingeschrieben
        ......
        </script>  // Scriptende
    </head>   // Ende "HTML-Kopfe"
    <body>   // "HTML-Körper"
    ....Inhalt   // Hier kommen die eigentlichen Texte, Formulare, etc. in HTML-Syntax rein
    </body>   // Ende "HTML-Körper"
</html>   // Ende der HTML-Datei

Ein paar wichtige HTML-Tags:
 
Hintergrundfarbe setzen <body bgcolor="ffffaa">
Überschriften <h1>.....</h1>
Zentrieren <center>...</center>
Zeilenumbruch <br>
mit Lehrzeile <p>
horizontale Linie <hr>
Schrägschrift <i> </i>
Fettschrift <b>.....</b>
unterstrichen <u>.....</u>
Leerzeichen &nbsp;
Bilder einfügen <img src="dateiname">   ///z.B. Bilder in .gif (Strich) oder .jpg (Foto)
Zeichen HTML ASCII - Hexadezimalzahl
ä &auml; E4
Ä &Auml; C4
ö &ouml; F6
Ö &Ouml; D6
ü &uuml; FC
Ü &Uuml; DC
ß &szlig; DF

 

Aufbau von Tabellen:

<table border=1>
<tr><td>Inhalt</td><td>...</td></tr>
<tr><td>...
</table>

Aufbau von Formularen:

Kopftag:
<form name="form1" method={"Post" oder "Get"(gibt den "Transportbehälter" für die Formulare an)}action={Pfad des Perl-Scripts oder Servlets cgi-bin/gp.pl"oder z.B."servlet/gb.class"}>

Textbefehle:    <input type="Text" name="Nachname" [value="xxxxx" (vorbelegter Inhalt)] [size="20" (Länge des Textfeldes in Zeichen)]>

Buttons:        <input type="Button" value="Aufschrift">   // Allgemeine Befehle zur Erstellung eines Buttons
                      <input type="submit" value="Abschicken">   // Der Inhalt des Formulars wird zum Server geschickt und das Action-Programm wird gestartet
                     <input type="Reset" value="loeschen">   // Alle Textfelder werden gelöscht

</form>

Servlets

Servlets sind Java-Programme, die für die Kommunikation zwischen Client und Server eine entsprechende API bereitstellen. Die wesentliche Funktionalität bietet die Klasse javax.servlet.http.HttpServlet. Eigene Servlets können von dieser Klasse Methoden erben und durch Überschreiben an spezifische Anforderungen anpassen. Das gilt insbesondere für die Methoden zum Informationsaustasch zwischen Client und Server. Bei der Übertrgung von Infomationen vom Client zum Server unterscheidet man zwischen der GET- und der POST-Methode. Verwendet der Client die GET-Methode, so findet der Server die Informationen  in einem Speicherbereich, der als Umgebungsvariable bezeichnet wird. Der zu übertragende Inhalt wird an die in der Methode "Action" angegebene Adresse gehängt, wobei ein einziges Fragezeichen als Trennzeichen dient. Diese Zeichenkette wird dann in der bereits erwähnten Umgebungsvariablen abgelegt und zwar im Bereich "QUERY_STRING". Wenn von einem Servlet Daten mit der Get-Methode empfangen werden sollen, muss die Methode doGet überschrieben werden. Dabei werden Objekte der Klassen HttpServletRequest und HttpServletResponse erzeugt, mit deren Methoden die gesamte Kommunikation abgewickelt wird. Das sieht dann so aus:

public void doGet (HttpServletRequest requ, HttpServletResponse resp) throws ServletException, IOException{

String eingabe=requ.getQueryString();   //Einlesen der Nachricht vom Client

String eingabe=requ.getParameter("T1");   //Einlesen der Nachricht vom Client. Hier vom Objekt mit dem Namen T1, welches im HTML-Formular angegeben wurde. "getParameter" hat den großen Vorteil gegenüber "getQueryString", dass alle Zeichen aus "QUERY_STRING" im Klartext vorliegen und deshalb direkt ausgegeben werden können.

String addr=requ.getRemoteAddr().toString();   //Einlesen der IP-Adresse des Clients

resp.setContentType ("text/html");   //Inhaltstype der Datei, die zum Client geschickt wird

PrintWriter out=resp.getWriter   //Ausgangskanal zum Client erzeugen:

Die URL-Codierung

Der Inhalt eines Formulars, der vom Client zum Sever geschickt wird, ist nach folgenden Regeln codiert:
Für die Formularfelder werden Namen-Inhalts Paare geschickt. Dabei sind Name und Inhalt des Feldes durch ein = getrennt. Namen-Inhalts Paare unterschiedlicher Felder sind ihrerseits durch &-Zeichen getrennt:

Name1=Inhalt1&Name2=Inhalt2&Name3=Inhalt3

Die Zeichen in Namen und Inhalt sind ihrerseits codiert:

1.    0-9, A-Z, a-z werden uncodiert übertragen

2.    Leerzeichen werden durch + ersetzt.

3.    Alle anderen Zeichen werden durch ihren ASCII-Code ersetzt, der durch eine 2-stellige Hexadezimalzahl angegeben wird, und vor dem ein %-Zeichen steht.

Mit der Methode getQueryString() erhält das Servlet die Client-Informationen codiert. Das heisst, dass der Programmierer selbst für die Dekodierung sorgen muss. Dagegen liefert die Methode getParameter("Name") den Inhalt des Feldes, dessen Name im Argument der Methode steht, bereits decodiert.

Das Vorbereiten der Entwicklungsumgebung auf das Arbeiten mit Servlets

Da selbst das  JDK1.3.1_02 noch nicht die erforderlichen Bibliotheken für Servlets von Haus aus beinhaltet, muss man sich die Bibliothek "servlet.jar" selbst aus dem Internet besorgen und nachträglich in das Verzeichnis <jdk-Verzeichnis>/lib/ kopieren. Danach sind noch Pfadhinweise in der "Autoexec.bat" und ein Neustart des Rechners nötig. Man fügt einfach folgende Zeilen hinzu:

path=<jdk-Verzeichnis>\jre\bin;c:\jdk1.3.1_02\jre\lib\classic;.......
set classpath=<jdk-Verzeichnis>\lib\servlet.jar;.........

Danach sollte der Java-Compiler in der Lage sein, unseren Servlet-Quelltext zu kompilieren.

Die Installation von "jsdk2.1" zum Ausführen der Servlets auf dem eigenen PC

Wenn man die selbstprogrammierten Servlets auf dem eigenen Rechner testen will, muss der Rechner zusätzlich zu der Rolle des Clients auch die Rolle des Servers übernehmen. Man kann zu diesem Zweck hierfür das Paket "jsdk2.1.zip" von der Java-Hompage herunterladen. Dieses Programmpaket enthält einen Web-Server mit einer Servlet-Engine. Um ihn zu installieren, entpackt das zip-Archiv in ein neues Verzeichnis. Die HTML-Datei (als index.html benannt!) legt man in <JSDK-Verzeichnis>/webpages/  ab. Servlets kommen in den Ordner <JSDK-Verzeichnis>/webpages/Web-inf/servlets/ .

In der Datei  "<JSDK-Verzeichnis>/default.cfg" kann noch der Standard-HTTP Port 80 eingestellt werden:

                                            server.port=80
                                            server.hostname=localhost

Um den Server zu starten muss man in einem DOS-Fenster die Datei <JSDK-Verzeichnis>/startserver.bat ausführen. (Das funtioniert nur, wenn in den Eigenschaften des DOS-Fensters der Umgebungsspeicher auf 2816 gesetzt ist.) Jetzt wird ein Browser gestartet und "http://localhost/" eingegeben. Die dadurch aufgerufene HTML-Seite enthält Verweise auf DOC-Files für die Servlet-API. Insbesondere kann er aber Servlets ausführen, deren Class-Dateien sich im Verzeichnis webpages/web-inf/servlets befinden.
 
 

Beispiel für ein einfaches Servlet

Als erstes Beispiel soll ein Servlet geschrieben werden, dem man schon anmerkt, dass es Zugriff auf einen Server hat. Es soll zunächst von einer HTML-Seite mittels der GET-Methode den Inhalt eines Textfeldes erhalten und dann folgende Aktionen durchführen:

1.    einen (einzeiligen) Text aus einer Datei "msg.txt"   in eine String-Variable "alt" einlesen.
2.    den übermittelten Text in einen String "neu" zwischenspeicheren.
3.    dann den Inhalt von "neu" in die Datei msg.txt schreiben (der alte Inhalt wird dabei überschrieben)
4.    und schließlich den alten Inhalt "alt" an den Client schicken.

Das läuft darauf hinaus, dass man eine Nachricht hinterlegt und im Gegenzug die vom vorherigen Benutzer hinterlegte Nachricht erhält.

1. Bestandteil - Die HTML-Datei "index.html"

<html>
<head>
<title>Testservlet</title>
</head>
<body>
<h3 align="center">Testservlet</h3>
<hr>
<form method="GET" action="/servlet/testserv">  //Hier wird der Pfad für das Servlet gelegt. Achtung:der Pfad gilt ab der //Ebene wo die HTML-Datei selber liegt Im Pfad steht servlet, obwohl das Verzeichnis servlets heißt UND beim Servlet fehlt die Endung ".class"
<table align="center" border="1">
<tr><td><input type="text" name="T1" size="20"></td></tr>   //Das Textobjekt wird erstellt --> mit dem name "T1"
<tr><td><input type="submit" value="Abschicken" name="B1"></tr></td>
<tr><td><input type="reset" value="Zurücksetzen" name="B2"></tr></td>
</table>
</form>
</body>
</html>

2. Bestandteil - Das Servlet "testserv.class"

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.net.*;

public class testserv extends HttpServlet implements SingleThreadModel{
  public void doGet(HttpServletRequest requ,HttpServletResponse resp)
    throws ServletException, IOException, IOException {
    String pfad ="c:/jsdk2.1/webpages/Web-inf/servlets/msg.txt";   //Hier wird der Pfad von "msg.txt" angegeben
    FileReader fileread =new FileReader(pfad);
    BufferedReader fileread2=new BufferedReader(fileread);
    String alt = fileread2.readLine();   //"alt" erhält den Inhalt der Textdatei (über den Umweg der Lese-Objekte)
    fileread2.close();
    String neu=requ.getParameter("T1");  //der String aus dem Textobjekt des Formulars "T1" kann ausgelesen werden und wird in "neu" gespeichert
    FileWriter filewrite=new FileWriter(pfad);
    PrintWriter filewrite2=new PrintWriter(filewrite);
    filewrite2.println(neu);  //"neu" wird in "msg.txt" abgespeichert
    filewrite2.flush();
    filewrite2.close();
    resp.setContentType("text/html");
    PrintWriter out=resp.getWriter();
    out.println("<html><head>servlettest</head><body>");   //das HTML-Grundgerüst der Datei, die das Servlet zurückschickt, wird gemacht
    out.println(alt);  //"alt" wird ausgegeben
    out.println("</body></html>");  //das Ende der HTML-Datei
    out.flush();
    out.close();
  }
}


Das Programm zum herunterladen.


Hash-Tabellen:

Um die ASCII-Codes für Umlaute und ß in einen, für die Ausgabe brauchbaren, HTML-Code zu verwandeln, benötigt man eine Zuordnungstabelle. Dafür eignet sich eine Hash-Tabelle.
Mit Hash-Tabellen (Hashtables) kann man arbeiten wie mit Arrays. Während aber die Elemente von Arrays durch Zahlen gekennzeichnet sind, kennzeichnet man die Elemente von Hashtables durch Schlüssel für die man unter anderem auch Strings verwenden kann:

Veranschaulichung einer Hash-Tabelle:

Erzeugung einer Hash-Tabelle:
        Hashtable htmlcode=new Hashtable();  // die erzeugte Hash-Tabelle ist zunächst noch leer.

Hinzufügen von Elementen:
        htmlcode.put("E4"[Schlüssel (Key)],"&auml;"[Wert(Value)]);

Nachschauen von Schlüsselwerten:
        htmlcode.containsKey(Schlüsselwert)  // ----> ergibt entweder "true" oder "false"

Inhalt von einem bestimmten Schlüssel herausholen:
        htmlcode.get(Schlüssel)  // liefert ein Objekt, das gegebenfalls mit Typecasting in die spezielle Inhaltsklasse verwandelt werden muss.