![]() |
|
|||||
Wir wollen die Schemas im Folgenden auch Protokoll nennen. Das Protokoll bestimmt die Zugriffsart und das am meisten verwendete Protokoll ist mittlerweile HTTP (Hypertext Transfer Protocol) mit dem auf Inhalte des Webs zugegriffen wird. Die URL für die Dienste im Web beginnt mit »http«. Sun unterstützt im JDK folgende Protokolle: »doc«, »file«, »ftp«, »gopher«, »http«, »jar«, »mailto«, »system«, »verbatim«. Unterschiedliche Implementierungen haben mehr oder weniger unterstützte Protokolle. Während die Syntax für oben nicht genannte Adressierungen schwanken, so lässt sich für die IPbasierten Protokolle (IP für »Internet Protocol«) eine Syntax für den schemenspezifischen Teil ausmachen. Dieser beginnt nach einem Doppel-Slash. Somit ist deutlich, dass diese Angabe dem Internet-Schema folgt: //user:password@host:port/url-path Einige oder alle Teile können bei einer URL ausgelassen werden. So sind »user:password@«, »:password«, »:port« und »/url-path« optional. Sind Benutzername und dass Passwort angegeben, so folgt ein At-Zeichen »@«. Natürlich dürfen im Passwort und Benutzernamen Doppelpunkt, At-Zeichen oder Slash nicht vorkommen. Die einzelnen Komponenten haben folgende Bedeutung:
17.2.1 URL-Objekte erzeugen
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Beispiel Um eine Verbindung zum Host der Universität Paderborn zu bekommen, nehmen wir die bekannte URL und erzeugen damit das Objekt:
URL uniURL = new URL( "http://uni-paderborn.de/index.html" ); |
Die URL-Klasse besitzt noch zusätzliche Konstruktoren; diese sind dann nützlich, wenn Komponenten der Adresse, also Zugriffsart (beispielsweise das HTTP), Hostname und Dateireferenz getrennt gegeben sind.
Beispiel Eine Alternative zur oberen Form
URL uniURL = new URL( "http", "uni-paderborn.de", "index.html" ); |
Das zweite Argument ist die Basisadresse der URL. Was dem String im dritten Parameter übergeben wird, ist der Ressource-Namen relativ zur Basisadresse. Ist diese Basisadresse null, was möglich ist, dann ist die zweite Angabe absolut zu nehmen. Und ist der zweite Parameter in absoluter Notation formuliert, wird alles im ersten Parameter ignoriert.
Da eine URL auch einen entfernten Rechner an einem anderen Port ansprechen kann, existiert auch dafür ein Konstruktor:
URL url = new URL( "http", "uni-paderborn.de", 80, "index.html" );
Die URL des Objekts wurde durch eine absolute Adresse erzeugt. Diese enthält dann alle Informationen, die für den Aufbau zum Host nötig sind. Es können jedoch auch URL-Objekte erzeugt werden, wo nur eine relative Angabe bekannt ist. Relative Angaben werden häufig bei HTML-Seiten verwendet, da somit die Seite besser vor Verschiebungen geschützt ist. Damit die Erzeugung eines URL-Objekts mit relativer Adressierung gelingt, muss eine Basisadresse bekannt sein. Ein Konstruktor für relative Adressen erwartet diese Basisadresse als Parameter.
Beispiel Für die Uni-Seite nutzen wir ein URL-Objekt, welches auf die Datei index.html zeigt:
URL uniURL = new URL( "http://uni-paderborn.de" ); |
Diese Art und Weise der URL-Objekt-Erzeugung ist besonders praktisch für Referenzen innerhalb von Web-Seiten (Named Anchors).
Beispiel Besteht für eine Seite ein Unterteilung in TOP und BOTTOM, so kann der URL-Konstruktor für relative URLs verwendet werden.
URL virtuellURL = new URL( "http://bum.bum.org" ); |
Jeder der Konstruktoren wirft eine MalformedURLException, wenn der Parameter im Konstruktor entweder null ist oder er ein unbekanntes Protokoll (wie in telepatic:\\ulli\brain\java) beschreibt. Somit ist der Code in der Regel von einem Block der folgenden Art umgeben:
try {
URL myURL = new URL( . . . )
}
catch ( MalformedURLException e ) {
// Fehlerbehandlung
}
class java.net.URL |
| URL( String protocol, String host, int port, String file ) throws MalformedURLException Erzeugt ein URL-Objekt mit dem gegebenen Protokoll, Hostnamen, Portnummer und Datei. Ist die Portnummer -1, so wird der Standard-Port verwendet, zum Beispiel für das WWW der Port 80. |
| URL( String protocol, String host, String file ) throws MalformedURLException Das Gleiche wie URL(protocol, host, -1, file). |
| URL( String ) throws MalformedURLException Erzeugt ein Objekt aus der URL-Zeichenkette. |
| URL( URL, String ) throws MalformedURLException Erzeugt relativ zur URL ein neues URL-Objekt. |
|
Ist das URL-Objekt einmal angelegt, so lassen sich die Attribute des Objekts nicht mehr ändern. Es gibt zwar Setter-Methoden, aber diese sind protected und den Unterklassen vorbehalten. Uns normalen Klassenbenutzern bietet die URL-Klasse nur Methoden zum Zugriff. So lassen sich Protokoll, Hostname, Port Nummer und Dateinamen mit Zugriffsmethoden erfragen. Es lassen sich jedoch nicht alle URL-Adressen so detailliert aufschlüsseln und außerdem sind manche der Zugriffsmethoden nur für HTTP sinnvoll.
| String getProtocol() Liefert das Protokoll der URL. |
| String getHost() Liefert den Hostnamen der URL, falls dies möglich ist. Für das Protokoll »file« ist dies ein leerer String. |
| int getPort() Lierfert die Portnummer. Ist sie nicht gesetzt, liefert getPort() eine -1. |
| String getFile() Gibt den Dateinamen der URL zurück. |
| String getRef() Gibt die relative Adresse der URL zurück. |
final class java.net.URL |
Das kleine nachfolgende Programm erzeugt ein URL-Objekt zu http://java.sun.com. Alle Möglichkeiten zur Angabe von URL-Informationen werden ausgenutzt. Anschließend erfolgt ein Auslesen aller Attribute.
Listing 17.1 ParseURL.javaimport java.net.*;
import java.io.*;
class ParseURL
{
public static void main( String args[] )
{
try {
URL aURL = new URL(
"http://java.sun.com:80/tutorial/intro.html#DOWNLOADING");
System.out.println( "protocol = " + aURL.getProtocol() );
System.out.println( "host = " + aURL.getHost() );
System.out.println( "filename = " + aURL.getFile() );
System.out.println( "port = " + aURL.getPort() );
System.out.println( "ref = " + aURL.getRef() );
} catch ( MalformedURLException e ) {
System.out.println( "MalformedURLException: " + e );
}
}
}
protocol = http
host = java.sun.com
filename = /tutorial/intro.html
port = 80
ref = DOWNLOADING
Die Methode equals() aus der Klasse Object ist uns bekannt. Sie soll von jeder Klasse so implementiert werden, dass gleiche Objekte true zurückliefern. Jede Klasse soll aber selbst ihre Inhalte vergleichen und nicht nur ihre Objektreferenzen. So muss also die URL-Klasse untersuchen, ob alle Komponenten der einen URL mit der anderen URL übereinstimmen. equals() untersucht dafür zuerst, ob es sich bei der vergleichenden Klasse um ein Exemplar von URL handelt. Wenn ja, wird untersucht, ob die Komponenten Referenzen besitzen oder nicht. Dies wird erreicht, indem Protokoll, Host, Port und Datei untersucht werden. Hierfür bietet sich auch die öffentliche Methode sameFile()an. Ein Anker ist für den Vergleich nicht bestimmend.
public boolean sameFile(URL other) {
// AVH: should we not user getPort to compare ports?
return protocol.equals(other.protocol) &&
hostsEqual(host, other.host) &&
(port == other.port) &&
file.equals(other.file);
}
Die Implementierung verrät uns, dass sich die Entwickler nicht einig sind, ob die Ports nicht besser mit getPort() zu vergleichen sind.
final class java.net.URL |
| boolean sameFile( URL ) Vergleicht zwei URL-Objekte. Die Methode liefert true, falls beide Objekte auf die gleiche Ressource zeigen. Der Anker der HTML-Dateien ist unwichtig. |
Beispiel equals() für URL-Objekte Listing 17.2 URLContentsTheSame.java
import java.net.*; |
Um auf die auf dem Web-Server gespeicherten Daten zuzugreifen, gibt es drei Möglichkeiten. Zwei davon nutzen Streams, und zwar einmal über die Klasse URL und einmal über eine URLConnection. Bei der dritten Möglichkeit ist Handarbeit angesagt und fällt deshalb in das Kapitel über Sockets.
Jedes URL-Objekt besitzt die Methode openStream(), die einen InputStream zum Weiterverarbeiten liefert, sodass wir dort die Daten auslesen können:
InputStream in = uniURL.openStream();
final class java.net.URL |
| final InputStream openStream() throws IOException Öffnet eine Verbindung zur Server und liefert einen InputStream zurück. Diese Methode ist eine Abkürzung für openConnection().getInputStream(). |
| URLConnection openConnection() throws IOException Liefert ein URLConnection Objekt, welches die Verbindung zum entfernten Objekt vertritt. openConnection() wird vom Protokoll-Handler immer dann aufgerufen, wenn eine neue Verbindung geöffnet wird. |
Verweist die URL auf eine Textdatei, dann erweitern wir oft den InputStream zu einem BufferedReader, da dieser eine readLine()-Methode besitzt. Folgender Programmcode liest solange Zeilen, bis das Ende der Eingabe signalisiert wird. Glücklicherweise ist uns die Vorgehensweise schon bekannt, da sich ja das Lesen von einer Datei nicht vom Lesen eines entfernten URL-Objekts unterscheidet:
BufferedReader in = new BufferedReader(
new InputStreamReader( url.openStream() ) );
String line = "";
while ( (line = in.readLine()) != null )
System.out.println( line );
Sind die Daten gelesen, schließt close() den Datenstrom – close() bezieht sich allerdings nicht auf das URL-Objekt, sondern auf den Datenstrom. Es sei anschließend noch einmal ein vollständiges, lauffähiges Programm aufgeführt.
Listing 17.3 OpenURLStream.javaimport java.net.*;
import java.io.*;
class OpenURLStream
{
public static void main( String args[] )
{
try
{
URL spiegelURL = new URL( "http://www.spiegel.de" );
BufferedReader in = new BufferedReader(
new InputStreamReader( spiegelURL.openStream() ) );
String s;
while ( ( s = in.readLine() ) != null )
System.out.println( s );
in.close();
} catch ( MalformedURLException e ) {
System.out.println( "MalformedURLException: " + e );
} catch ( IOException e ) {
System.out.println( "IOException: " + e );
}
}
}
Wir erzeugen ein URL-Objekt und rufen darauf die openStream()-Methode auf. Diese liefert einen InputStream auf den Dateiinhalt. In der API-Beschreibung wurde aber schon kurz erwähnt, dass diese Funktion eigentlich nur eine Abkürzung für openConnection().getInputStream() ist. openConnection() erzeugt ein URLConnection-Objekt und sendet diesem die Nachricht getInputStream().
Wir wollen uns im nächsten Abschnitt mit dem URLConnection-Objekt beschäftigen, denn damit wird die Verbindung über das Netzwerk zum Inhalt aufgebaut. Die URL-Klasse besitzt nur deshalb die Abkürzung über openStream(), da zum einen nicht jeder wissen muss, dass URLConnection dahinter steckt, und zweitens, weil es Tipperei erspart.
Das Beispiel zeigt auch, dass bei openConnection() ein try/catch-Block notwendig ist. Denn geht etwas daneben, zum Beispiel, wenn der Dienst nicht verfügbar ist, so wird eine IOException ausgelöst:
try {
URL ohoURL = new URL( "http://www.oho.com/" );
ohoURL.openConnection();
} catch ( MalformedURLException e ) { // new URL() ging daneben
...
} catch ( IOException e ) { // openConnection() schlug fehl
...
}
Die Objekte der Klasse URLConnection sind für den Empfang der Inhalte der URL-Objekte verantwortlich. Die Klasse ist abstrakt und die Unterklassen implementieren die Protokolle, mit denen die Verbindung zum Inhalt aufgebaut wird. Die Unterklassen bedienen sich dabei Objekten der Klasse URLStreamHandler, mit denen der eigentliche Inhalt ausgelesen wird. (Siehe hierzu Abbildung 17.2 auf der folgenden Seite.)
|
Die Klasse URLConnection ist ein wenig HTTP-lastig, denn viele Methoden haben nur für URLs auf Web-Seiten eine Bedeutung. So stellt die Klasse Methoden bereit, um die Verbindung aufzubauen, den HTTP-Header zu lesen und den Inhalt eines Dokuments zu holen. Da eine Datei, die vom Web-Server kommt, den Inhalt (engl. Content) immer ankündigt (wenn wir später mit direkten Socket-Verbindungen arbeiten, lässt sich dies am zurückgeschickten Inhalt erkennen), so erkennt die Klasse URLConnection mit einem Content-Handler den Inhalt und bietet uns Benutzern Methoden an, um mit dem Header und den Inhalten zurechtzukommen.
Handelt es sich bei der Verbindung um das Protokoll HTTP, so schreibt die HTTP 1.1 Spezifikation im RFC 2616 einige Header vor, die durch spezielle Methoden der Klasse URLConnection abgefragt werden können.
Beispiel Um zu erfahren, wann die Datei auf dem Server gelandet ist, kann getDate() bzw. getLastModified() verwendet werden. Werfen wir dazu einen Blick auf die Methode printHeader().
void printHeader() |
Die meisten der Attribute werden durch eine der Funktionen getHeaderField(), getHeaderFieldInt() oder getHeaderFieldDate() verarbeitet. getHeaderFieldInt() ist eine Hilfsfunktion und bedient sich getHeaderField() wie folgt: Integer.parseInt(getHeaderField(name)). Ebenso wandelt getHeaderFieldDate() mittels getHeaderField() den String in ein long um: return Date.parse(getHeaderField(name)). Schauen wir uns zwei der Methoden an:
public String getContentType() {
return getHeaderField("content-type");
}
public long getLastModified() {
return getHeaderFieldDate("last-modified", 0);
}
Wie nun getHeaderField() wirklich implementiert ist, können wir nicht sehen, da es sich dabei um Funktionen handelt, die von den Unterklassen überschrieben werden. Prinzipiell ist die URLConnection-Klasse zwar für alle Protokolle gleichwertig, doch an anderer Stelle wurde erwähnt, dass sie mehr zugunsten von HTTP entscheidet. Deshalb muss ein Rückgabewert von getLastModified() von einer FTP-Verbindung mit Vorsicht genossen werden.
Der Inhalt eines URL-Objekts lässt sich mit getContent() vom Server holen, falls ein passender Content-Handler eingetragen ist. Für Bilder ist etwa so ein Handler eingetragen, der als Rückgabewert ein URLImageSource liefert. Mit wenigen Zeilen können wir dann ein Bild in Form eines Image-Objekts erzeugen, das auf dem Server weilt:
public static Image fetchimage( String url )
throws MalformedURLException, IOException
{
URL u = new URL( url );
Toolkit tk = Toolkit.getDefaultToolkit();
return tk.createImage((ImageProducer)u.getContent());
}
Wenn wir konkret ein Bild über eine URL laden wollen, dann bietet sich sicherlich die Methode getImage(URL) an.
Mit getContent() an Daten zu gelangen, funktioniert für alle Objekte – natürlich muss ein passendes Protokoll installiert sein. Bei Content-Handlern gilt das Gleiche wie für Protokoll-Handler: Unterschiedliche Umgebungen implementieren unterschiedliche Handler. Für HTML-Dateien liefert getContent() ein Objekt vom Typ sun.net.www.MeteredStream zurück und für normale Textdateien ein sun.net.www.content.text.PlainTextInputStream Objekt; also nur Datenströme. Für Texte und HTML-Seiten können wir dann mit Hilfe des InputStreams (MeteredStream und PlainTextInputStream sind Unterklassen) die Datei zeilenweise auslesen. Leider gibt es keine Methode in der Bibliothek, die sofort die Daten in einem String bereitstellt.
Mit einer kleinen Zeile können wir erfragen, was für ein Handler-Objekt eine URL-Klasse für den Datenstrom einsetzt:
Object o = u.getContent();
System.out.println( "Schnapp: Ich habe einen " + o.getClass().getName() );
getContent() erkennt nun an Hand der Endung beziehungsweise der ersten Bytes den Typ der Datei. Dann konvertiert ein Content-Handler die Bytes seines Datenstroms in ein Java-Objekt. Der Protokoll-Handler überwacht die Verbindung zum Server und stellt dann die Verbindung zu einem konkreten Content-Handler her, der die Konvertierung in ein Objekt übernimmt.
Stellen wir zusammenfassend noch einmal den Content- und Protokoll-Handler gegenüber:
| Content-Handler: Durch einen Content-Handler wird die Funktionalität der URL-Klasse erweitert. Es können Quellen verschiedener MIME-Typen durch die Methode getContent() als Objekte zurückgegeben werden. Leider beschreibt die Java Spezifikation nicht, welche Content-Handler bereitgestellt werden müssen. Für GIFs und JPGs gibt es Handler, die gleich ImageProducer anlegen. |
| Protokoll-Handler: Auch ein Protokoll-Handler erweitern die Möglichkeiten der URL-Klassen. Das Protokoll ist der erste Teil einer URL und gibt bei Übertragungen wie »http« die Kommunikationsmethode an. Auch hier gibt es keine verbindliche Verpflichtung, diese bei einer JVM auszuliefern. So unterstützt das JDK Protokolle wie »file«, »ftp«, »jar«, »mailto«, doch schon Netscape benutzt andere Implementierungen der Klasse URLConnection. Noch anders sieht es beim Microsoft Explorer aus. Also hilft nur das Selberprogrammieren2 . |
final class java.net.URLConnection |
| Object getContent() throws IOException, UnknownServiceException Liefert den Inhalt, auf den die URL verweist. UnknownServiceException ist eine Unterklasse von IOException, es reicht also ein catch auf IOException aus. |
final class java.net.URL |
| final Object getContent() throws IOException Liefert den Inhalt, auf den die URL verweist. Die Methode ist eine Abkürzung für openConnection().getContent().Wegen der Umleitung auf das URLConnection-Objekt kann auch hier eine UnknownServiceException auftauchen. |
Die Klasse URLConnection ist abstrakt. Wird openStream() von einem URL-Objekt aufgerufen, so weiß diese Methode, wie die Verbindung zum Dienst aufzubauen ist. Denn für Web-Seiten mit dem HTTP-Protokoll sieht dies anders aus als eine Dateiübertragung mit dem FTP-Protokoll. openConnection() von URL macht nichts weiteres als vom jeweiligen Handler wiederum openConnection() aufzurufen. Die Handler wissen für ihr Protokoll, wie die Verbindung aufzubauen ist. Der Handler von URLConnection ist vom Typ URLStreamHandler, eine abstrakte Superklasse, die von allen Stream-Protokoll-Handlern implementiert wird. Leider können wir diese Implementierung nicht im Quelltext sehen. Im Konstruktor des URL-Objekts werden die Protokoll-Handler initialisiert. Denn an dieser Stelle ist klar, um was für einen Dienst es sich handelt. Ein URL-Parser zerpflückt dann die URL und ruft in dem Protokoll die getURLStreamHandler()-Methode auf. Sie würde null zurückliefern, falls sie mit dem Protokoll nichts anzufangen weiß – dies bekämen wir zu spüren, denn eine null heißt: MalformedURLException().
getURLStreamHandler() – static synchronized gekennzeichnet – ist die eigentliche Arbeitsstelle. Hier wird zum Präfix sun.net.www.protocol. der Name des Handler gehängt (zum Beispiel ftp, http) und anschließend ein .Handler drangesetzt. Nun wird über Class.forName(clsName) nachgeschaut, ob die Klasse schon im System geladen wurde. Wenn nicht, dann versucht der Klassenlader über loadClass(clsName) an die Klasse zu kommen. Falls die Klasse geladen werden konnte, wird sie mit newInstance() initialisiert und als URLStreamHandler dem aufrufenden Konstruktor übergeben.
Soweit der Weg vom Konstruieren über ein URL-Objekt zum Laden des Handlers. Anschließend liegt der Handler URLStreamHandler vor und wird in der privaten Variablen handler abgelegt. Kommen wir nun noch einmal zur Methode openConnection(). Wir haben gesagt, dass diese Methode wissen muss, welches URLConnection-Objekt es zurückgibt, da das Protokoll bekannt ist. Und da das Protokoll vom Typ URLStreamHandler in der Variablen handler liegt, ist es ein einfaches, sich die openConnection()-Methode vorzustellen:
public URLConnection openConnection() throws java.io.IOException
{
return handler.openConnection(this);
}
Der Handler übernimmt selbst das Öffnen. Nun gibt es eine URLConnection und wir können damit auf die Referenz lesend (wir holen uns also Informationen beispielsweise von der Web-Seite) und schreibend (zum Beispiel für eine CGI-Abfrage) reagieren. Es muss betont werden, dass bei der Erzeugung eines URLConnection-Objekts noch keine Verbindung aufgebaut wird. Dies folgt mit den Methoden getOutputStream() oder getInputStream().
final class java.net.URLConnection |
| URLConnection openConnection() throws IOException Liefert ein URLConnection-Objekt, das die Verbindung zum entfernten Objekt vertritt. openConnection() wird vom Protokoll-Handler immer dann aufgerufen, wenn eine neue Verbindung geöffnet wird. |
CGI (Common Gateway Interface) ist eine Beschreibung einer Schnittstelle http://cgi-spec.golux.com., mit der externe Programme mit Informations-Servern, meistens Web-Servern, Daten austauschen. Die aktuelle Version ist CGI/1.1. Diese ausgeführten Programme werden kurz »CGI-Programme« genannt und können in allen erdenklichen Programmiersprachen verfasst sein. Häufig sind es Shell- oder Perl-Skripte (oft wird dann die Bezeichnung CGI-Skripte verwendet). Die Unterscheidung zwischen Skript und Programm ist bei CGI schwammig. Traditionell ist eine compilierte Quelldatei ein Programm und Programme, die mit einem Interpreter arbeiten, ein Skript. Wir werden im Folgenden allerdings »Programm« und »Skript« austauschbar verwenden. Für uns ist es erst einmal egal, ob ein Programm oder Skript ausgeführt wird. Denn wir wollen diese Programme aus Java nutzen und nicht selber schreiben. Auf der Server-Seite ergänzen Servlets immer mehr CGI-Programme.
Die CGI-Programme werden von einem Browser durch eine ganz normale URL angesprochen. Der Browser baut eine Verbindung zum Server auf und dieser erkennt anhand des Pfads in der URL, ob es sich um eine ganz normale Web-Seite handelt oder um ein Skript. Wenn es ein Skript ist, dann führt der Server das Skript aus, welches eine HTML-Datei erzeugt. Diese wird übertragen und im Browser dargestellt. Der Aufrufer einer URL merkt keinen Unterschied zwischen erstellten, also dynamischen, und statischen Seiten. Die CGI-Programme sind also immer eine Angelegenheit des Servers, der uns mit aktuellen Daten versorgt.
Beim Aufruf eines CGI-Programms können Parameter übergeben werden, bei einer Suchmaschine etwa der Suchbegriff. Es gibt nun zwei Möglichkeiten, wie diese Parameter zum Skript kommen und somit vom Web-Server verarbeitet werden.
| Die Parameter (genannt auch Query-String) werden an die URL angehängt (GET-Methode). Das Skript liest die Daten aus der Umgebungsvariablen QUERY_STRING aus. |
| Die Daten werden zur Standardeingabe des Web-Servers gesendet (POST-Methode). Das Skript muss dann aus dieser Eingabe lesen. |
GET und POST unterscheiden sich auch in der Länge der übertragenen Daten. Bei vielen Systemen ist die Länge einer GET-Anfrage beschränkt auf 1024 Byte. Der Content-Type (application/x-www-form-urlencoded) ist für GET- und POST-Anfragen identisch.
Die Daten sind mit dem CGI-Programmnamen verbunden und gehen beide zusammen auf die Reise. Der Anfragestring (Query-String) wird hinter ein Fragezeichen gesetzt, das et-Zeichen »&« trennt mehrere Anfragezeichenketten. Unter Java setzen wir einfach einen Befehl ab, indem wir ein neues URL-Objekt erzeugen und anschließend den Inhalt auslesen:
meineURL = new URL( "http", "...", "cgi-bin/trallala?tri" );
Das CGI-Skript holt sich seinerseits die Daten aus der Umgebungsvariable QUERY_STRING. Das folgende Kapitel zeigt, wie diese Abfrage-Zeichenketten komfortabel durch die Klasse URLEncoder zusammengebaut werden. Werfen wir jedoch erst einen Blick auf die Variablen.
Die Klasse URLConnection bietet die schon bekannte Methode getOutputStream() an, die eine Verbindung zur Eingabe des CGI-Scripts möglich macht (POST-Methode):
// CGI-Script schickt die Daten zurück
urlout PrintStream = new PrintStream(
cgiConnection.getOutputStream());
urlout.println( data );
urlout.close();
Wenn aus einer HTML-Datei mit Formularen über Submit Daten an das CGI-Programm übermittelt werden, dann werden diese Daten kodiert. Dies liegt daran, dass viele Zeichen in URL nicht erlaubt sind. Betrachten wir daher folgenden Ausschnitt aus einer Web-Seite:
<FORM METHOD="GET" ACTION="/cgi-bin/caller.cgi">
<P>Name:
<INPUT TYPE = "text" NAME = "name" VALUE = "">
<P>E-Mail:
<INPUT TYPE="text" NAME="email" VALUE = "">
<P>
<INPUT TYPE="submit" name="submit" >
</FORM>
Die Seite besitzt zwei Felder mit den Namen name und email. Dazu kommt noch ein Submit-Button, der, falls aktiviert, die Daten an das CGI-Programm caller.cgi weitergibt. Wenn wir die Felder mit irgendeinem Inhalt füllen und Submit drücken, sehen wir URL häufig in der Adressleiste des Browsers. Dort erscheint, ohne Zeilenumbruch, zum Beispiel:
http://oho.de/cgi-bin/caller.cgi?
name=Ulli+Ullenboom&email=ulliull@ulli.com&submit=Submit
Da in einer URL keine Leerzeichen erlaubt sind, werden sie durch Plus-Zeichen kodiert. Es gibt noch weitere Zeichen, die kodiert werden, so das Plus- oder das Gleichheitszeichen o