Skip to content

2. Grundlagen der Webprogrammierung

Das Hauptziel dieses Kapitels ist es, die wichtigsten Prinzipien der Webprogrammierung vorzustellen, die unabhängig von der jeweils zur Umsetzung verwendeten Technologie sind. Es enthält zahlreiche Beispiele, die Sie am besten selbst ausprobieren sollten, um sich nach und nach mit der Philosophie der Webentwicklung vertraut zu machen. Leser, die diese Kenntnisse bereits besitzen, können direkt zu Kapitel 3 übergehen.

Eine Webanwendung besteht aus folgenden Komponenten:

Image

Nummer
Rolle
Gängige Beispiele
1
OS Server
Unix, Linux, Windows
2
Webserver
Apache (Unix, Linux, Windows)
IIS (Windows + Plattform .NET)
Node.js (Unix, Linux, Windows)
3
Serverseitig ausgeführte Codes. Sie können von Servermodulen oder von Programmen außerhalb des Servers ausgeführt werden (CGI).
JAVASCRIPT (Node.js)
PHP (Apache, IIS)
JAVA (Tomcat, WebSphere, JBoss, WebLogic, ...)
C#, VB.NET (IIS)
4
Datenbank – Diese kann sich auf demselben Rechner wie das Programm befinden, das sie nutzt, oder über das Internet auf einem anderen Rechner.
Oracle (Linux, Windows)
MySQL (Linux, Windows)
Postgres (Linux, Windows)
SQL Server (Windows)
5
OS Client
Unix, Linux, Windows
6
Webbrowser
Chrome, Internet Explorer, Firefox, Opera, Safari, ...
7
Clientseitig im Browser ausgeführte Skripte. Diese Skripte haben keinen Zugriff auf die Festplatten des Client-Rechners.
JavaScript (alle Browser)

2.1. Datenaustausch in einer Webanwendung mit Formularen

Image

Nummer
Rolle
1
Der Browser fordert zum ersten Mal eine URL für (http://machine/url) an. Es werden keine Parameter übergeben.
2
Der Webserver sendet ihm die Webseite mit der Kennung URL. Diese kann statisch sein oder dynamisch durch ein Serverskript (SA) generiert werden, das möglicherweise Inhalte aus Datenbanken (SB, SC) verwendet hat. In diesem Fall erkennt das Skript, dass die Datei „URL“ ohne Übergabe von Parametern angefordert wurde, und generiert die Startseite.
Der Browser empfängt die Seite und zeigt sie an (CA). Browserseitige Skripte (CB) konnten die vom Server gesendete Startseite verändern. Anschließend wird die Webseite durch Interaktionen zwischen dem Benutzer (CD) und den Skripten (CB) verändert. Insbesondere werden die Formulare ausgefüllt.
3
Der Benutzer bestätigt die Formulardaten, die daraufhin an den Webserver gesendet werden müssen. Der Browser fordert je nach Fall die ursprüngliche Seite URL oder eine andere erneut an und übermittelt gleichzeitig die Formularwerte an den Server. Dazu kann er zwei Methoden namens GET und POST verwenden. Nach Erhalt der Anfrage des Clients löst der Server das Skript (SA) aus, das mit dem angeforderten URL verknüpft ist; dieses Skript erkennt die Parameter und verarbeitet sie.
4
Der Server liefert die programmgesteuert erstellte Webseite (SA, SB, SC). Dieser Schritt entspricht dem vorherigen Schritt 2. Der Datenaustausch erfolgt nun gemäß den Schritten 2 und 3.

2.2. Statische Webseiten, dynamische Webseiten

Eine statische Seite wird durch eine Datei HTML dargestellt. Eine dynamische Seite ist eine Seite HTML, die vom Webserver „on the fly“ generiert wird.

2.2.1. Statische Seite HTML (HyperText Markup Language)

Erstellen wir ein erstes Spring-Projekt MVC [1-2]:

  • In [1-2] erstellen wir ein neues Projekt auf Basis von Spring Boot [http://projects.spring.io/spring-boot/];
  • Die Informationen [3-7] dienen der Maven-Konfiguration des Projekts;
  • in [3], der Name des Maven-Projekts;
  • in [4] die Maven-Gruppe, in der das Ergebnis der Projektkompilierung abgelegt wird;
  • in [5] der Name des Kompilierungsergebnisses;
  • in [6] eine Beschreibung des Projekts;
  • in [7] das Paket, in dem die ausführbare Klasse des Projekts abgelegt wird;
  • in [8] die Art des Projekts. Es handelt sich um ein Webprojekt mit Thymeleaf-Views. Hier sind alle gebrauchsfertigen Maven-Abhängigkeiten zu sehen, die das Spring-Boot-Projekt bereitstellt;
  • in [9] wird angegeben, dass das Ergebnis des Maven-Builds in ein JAR-Archiv und nicht in ein WAR-Archiv gepackt wird. Das Projekt wird dann einen eingebetteten Tomcat-Server verwenden, der in seinen Abhängigkeiten enthalten ist;
  • in [10] fahren wir mit dem Assistenten fort;
  • In [11] wird der Projektordner angegeben;
  • In [12] schließen wir den Assistenten ab;
  • in [13] das generierte Projekt.

Sehen wir uns die generierte Datei [pom.xml] an:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>istia.st.springmvc</groupId>
    <artifactId>intro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springmvc-intro</name>
    <description>Les bases de la programmation web</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
        <relativePath /> <!-- Übergeordnetes Element aus dem Repository abrufen -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>istia.st.springmvc.Application</start-class>
        <java.version>1.7</java.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Sie enthält alle im Assistenten angegebenen Informationen. In den Zeilen 26–30 finden wir eine Abhängigkeit, die uns bisher nicht bekannt war. Sie ermöglicht die Integration der Unit-Tests JUnit mit Spring.

Beginnen wir damit, eine statische Seite HTML in diesem Projekt zu erstellen. Sie muss standardmäßig im Ordner [src / main / resources / static] abgelegt werden:

  • In [1-4] erstellen wir eine Datei HTML im Ordner [static];
  • in [6], der Seite einen Namen geben;
  • in [7] wurde die Seite hinzugefügt.

Der Inhalt der erstellten Seite lautet wie folgt:


<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

</body>
</html>
  • Zeilen 2–10: Der Code wird durch das Stamm-Tag <html> begrenzt;
  • Zeilen 3–6: Das Tag <head> begrenzt den sogenannten Kopfbereich der Seite;
  • Zeilen 7–9: Das Tag <body> begrenzt den sogenannten Hauptteil der Seite.

Ändern wir diesen Code wie folgt:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>essai 1 : une page statique</title>
</head>
<body>
  <h1>Une page statique...</h1>
</body>
</html>
  • Zeile 5: definiert den Titel der Seite – wird als Titel des Browserfensters angezeigt, in dem die Seite angezeigt wird;
  • Zeile 8: ein Text in großer Schrift (<h1>).

Führen wir die Anwendung [1-3] aus:

und rufen wir anschließend mit einem Browser die Seiten URL und [http://localhost:8080/exemple-01.html] auf:

  • in [1], das URL der angezeigten Seite;
  • in [2], der Titel des Fensters – wurde durch das Tag <title> der Seite bereitgestellt;
  • in [3], der Hauptteil der Seite – wurde durch das Tag <h1> bereitgestellt.

Sehen wir uns den Code [4-5] an, den der Browser unter HTML empfangen hat:

  • In [5] hat der Browser die von uns erstellte Seite HTML empfangen. Er hat sie interpretiert und grafisch dargestellt.

2.2.2. Eine dynamische Thymeleaf-Seite

Erstellen wir nun eine Thymeleaf-Seite. Es handelt sich um eine klassische HTML-Seite mit Tags, die durch Attribute [Thymeleaf] und [http://www.thymeleaf.org/] erweitert wurden. Wir gehen ähnlich vor wie bei der Erstellung der Seite HTML, doch diesmal muss die neue Seite HTML im Ordner [templates] abgelegt werden:

 

Die Seite [exemple-02.html] wird wie folgt aussehen:


<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>spring mvc intro</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p th:text="'Il est ' + ${heure}">Voici l'heure</p>
</body>
</html>
  • Zeile 8: Das Tag <p> ist ein HTML-Tag, das einen Absatz in die angezeigte Seite einfügt. [th:text] ist ein Attribut von [Thymeleaf], das zwei unterschiedliche Funktionen hat, je nachdem, ob [Thymeleaf] aktiv ist oder nicht:
    • Wenn [Thymeleaf] die Seite HTML nicht interpretiert, wird das Attribut [th:text] ignoriert, da es in HTML unbekannt ist. Der angezeigte Text lautet dann [Voici l'heure],
    • wenn [Thymeleaf] die Seite HTML interpretiert, wird das Attribut [th:text] ausgewertet und sein Wert ersetzt den Text [Voici l'heure]. Sein Wert sieht in etwa so aus: [Il est 17:11:06];

Schauen wir uns das einmal in der Praxis an. Wir duplizieren die Seite [templates / exemple-02.html] im Ordner [static]. Die in diesem Ordner abgelegten Seiten HTML werden von [Thymeleaf] nicht interpretiert:

Wir führen die Anwendung wie bereits mehrfach zuvor aus und rufen dann mit einem Browser die Dateien URL und [http://localhost:8080/exemple-02.html] auf:

Wir sehen in [1], dass das Attribut [th:text] nicht interpretiert wurde und auch keinen Fehler verursacht hat. Der Quellcode der in [2] empfangenen Seite zeigt, dass der Browser die Seite vollständig empfangen hat.

Kehren wir zur Seite [exemple-02.html] aus dem Ordner [templates] zurück:

  

Die Seiten HTML, die sich im Ordner [templates] befinden, werden von [Thymeleaf] interpretiert. Kehren wir zum Code der Seite zurück:


<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>spring mvc intro</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p th:text="'Il est ' + ${heure}">Voici l'heure</p>
</body>
</html>
  • Zeile 7: [Thymeleaf] interpretiert das Attribut [th:text] und ersetzt [Voici l'heure] durch den Wert des Ausdrucks:
"'Il est ' + ${heure}"

Dieser Ausdruck verwendet die Variable [${heure}], wobei [heure] zum Modell der Ansicht [exemple-02.html] gehört. Wir müssen dieses Modell also erstellen. Dazu folgen wir dem in Abschnitt 1.6 behandelten Beispiel. Wir erweitern das Projekt wie folgt:

In [1] fügen wir den folgenden Controller hinzu:


package istia.st.springmvc;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyController {

    @RequestMapping("/")
    public String heure(Model model) {
        // Zeitformat
        SimpleDateFormat formater = new SimpleDateFormat("HH:MM:ss");
        // aktuelle Uhrzeit
        String heure = formater.format(new Date());
        // Die Uhrzeit wird in die Ansichtvorlage eingefügt
        model.addAttribute("heure", heure);
        // die Ansicht wird angezeigt [exemple-02.html]
        return "exemple-02";
    }
}
  • Zeilen 13–14: Die Methode [heure] verarbeitet URL und [/];
  • Zeile 14: [Model model] ist eine leere Vorlage. Die Aktion [heure] muss dort die Attribute einfügen, die sie in der Vorlage sehen möchte. Es ist bekannt, dass die Ansicht [exemple-02.html] ein Attribut mit dem Namen [heure] erwartet;
  • Zeilen 19–22: setzen das soeben Erläuterte um. Die Ansicht [exemple-02.html] wird angezeigt (Zeile 22), wobei ihr Modell ein Attribut namens [heure] enthält (Zeile 20);
  • Zeile 16: Es wird ein Datumsformatierer erstellt. Das verwendete Format [HH:MM:ss] ist ein Format [heures:minutes:secondes], bei dem die Uhrzeiten im Intervall [0-24] liegen;
  • Zeile 18: Mit diesem Formatierer wird das aktuelle Datum formatiert;
  • Zeile 20: Die ermittelte Uhrzeit wird einem Attribut mit dem Namen [heure] zugewiesen;

Wir starten die Anwendung und fragen nach URL [/]:

  • in [1] die angezeigte Seite und in [2] deren Inhalt HTML. Man kann feststellen, dass der ursprüngliche Text [Voici l'heure] vollständig verschwunden ist;

Wenn man nun die Seite [1] (F5) aktualisiert, erhält man eine andere Anzeige (neue Uhrzeit), während sich URL nicht ändert. Das ist der dynamische Aspekt der Seite: Ihr Inhalt kann sich im Laufe der Zeit ändern.

Aus dem Vorstehenden lässt sich der grundlegende Unterschied zwischen dynamischen und statischen Seiten ableiten.

2.2.3. Konfiguration der Spring-Boot-Anwendung

Kehren wir zur Architektur des Eclipse-Projekts zurück:

Mit der Datei [application.properties] lässt sich die Spring-Boot-Anwendung konfigurieren. Derzeit ist diese Datei leer. Sie kann verwendet werden, um die Anwendung auf vielfältige Weise zu konfigurieren, wie in den Dateien URL und [http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html] beschrieben. Wir werden die Datei [application.properties] gemäß [2] verwenden:

  • Zeile 1: Legt den Dienstport der Webanwendung fest;
  • Zeile 2: Legt den Kontext der Webanwendung fest;

Mit dieser Konfiguration wird die statische Seite [exemple-01.html] mit den Dateien URL und [http://localhost:9000/intro/exemple-01.html] erstellt:

 

2.3. Browser-seitige Skripte

Eine Seite HTML kann Skripte enthalten, die vom Browser ausgeführt werden. Die wichtigste browserbasierte Skriptsprache ist derzeit (Januar 2015) JavaScript. Hunderte von Bibliotheken wurden in dieser Sprache erstellt, um Entwicklern die Arbeit zu erleichtern.

Erstellen wir eine neue Seite [exemple-03.html] im Ordner [static] des bestehenden Projekts:

  

Bearbeiten wir die Datei „[exemple-03.html]“ mit folgendem Inhalt:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>exemple Javascript</title>
  <script type="text/javascript">
    function réagir() {
      alert("Vous avez cliqué sur le bouton !");
    }
  </script>
</head>
<body>
  <input type="button" value="Cliquez-moi" onclick="réagir()" />
</body>
</html>
  • Zeile 13: Definiert eine Schaltfläche (Attribut „type“) mit dem Text „Klick mich“ (Attribut „value“). Wenn man darauf klickt, wird die JavaScript-Funktion [réagir] ausgeführt (Attribut „onclick“);
  • Zeilen 6–10: ein JavaScript-Skript;
  • Zeilen 7–9: die Funktion [réagir];
  • Zeile 8: Zeigt ein Dialogfeld mit der Meldung [Vous avez cliqué sur le bouton] an.

Sehen wir uns die Seite in einem Browser an:

  • in [1] die angezeigte Seite;
  • in [2] das Dialogfeld, das beim Klicken auf die Schaltfläche angezeigt wird.

Beim Klicken auf die Schaltfläche findet kein Datenaustausch mit dem Server statt. Der JavaScript-Code wird vom Browser ausgeführt.

Dank der Vielzahl verfügbarer JavaScript-Bibliotheken lassen sich mittlerweile echte Anwendungen direkt im Browser ausführen. Dabei tendiert man zu folgenden Architekturen:

  • 1-2: Der Server HTML ist ein Server für statische Seiten HTML5 / CSS / JavaScript;
  • 3-4: Die ausgelieferten Seiten HTML5 / CSS / Javascript interagieren direkt mit dem Datenserver. Dieser liefert ausschließlich Daten ohne Layout (HTML). Das JavaScript fügt diese Daten in die bereits im Browser vorhandenen Seiten HTML ein.

In dieser Architektur kann der JavaScript-Code sehr umfangreich werden. Man versucht daher, ihn in Schichten zu strukturieren, wie man es auch beim serverseitigen Code tut:

  • Die Ebene [UI] ist für die Interaktion mit dem Benutzer zuständig;
  • die Schicht [DAO] interagiert mit dem Datenserver;
  • die Schicht [métier] umfasst die Geschäftsprozesse, die weder mit dem Benutzer noch mit dem Datenserver interagieren. Diese Schicht muss nicht unbedingt vorhanden sein.

2.4. Der Austausch zwischen Client und Server

Kehren wir zu unserem Ausgangsdiagramm zurück, das die Akteure einer Webanwendung veranschaulichte:

Image

Wir konzentrieren uns hier auf den Datenaustausch zwischen dem Client-Rechner und dem Server-Rechner. Dieser erfolgt über ein Netzwerk, und es ist sinnvoll, die allgemeine Struktur des Datenaustauschs zwischen zwei entfernten Rechnern noch einmal in Erinnerung zu rufen.

2.4.1. Das Modell OSI

Das von der ISO (International Standards Organisation) definierte Modell für offene Netzwerke mit der Bezeichnung OSI (Open Systems Interconnection Reference Model) beschreibt ein ideales Netzwerk, in dem die Kommunikation zwischen Rechnern durch ein siebenstufiges Modell dargestellt werden kann:

Jede Schicht erhält Dienste von der darunterliegenden Schicht und stellt ihre eigenen Dienste der darüberliegenden Schicht zur Verfügung. Nehmen wir an, zwei Anwendungen auf unterschiedlichen Rechnern A und B möchten miteinander kommunizieren: Dies geschieht auf der Ebene der Schicht Application. Sie müssen nicht alle Details der Funktionsweise des Netzwerks kennen: Jede Anwendung übergibt die Informationen, die sie übertragen möchte, an die darunterliegende Schicht, nämlich die Schicht Présentation. Die Anwendung muss daher nur die Schnittstellenregeln zur Schicht Présentation kennen. Sobald sich die Informationen in der Schicht Présentation befinden, werden sie nach anderen Regeln an die Schicht Session weitergeleitet und so weiter, bis die Informationen auf dem physikalischen Medium ankommen und physikalisch an den Zielrechner übertragen werden. Dort durchläuft sie den umgekehrten Prozess, den sie auf dem Absenderrechner durchlaufen hat.

Auf jeder Schicht sendet der für den Versand der Informationen zuständige Senderprozess diese an einen Empfängerprozess auf dem anderen Rechner, der derselben Schicht angehört wie er selbst. Dies geschieht nach bestimmten Regeln, die als Protokoll der jeweiligen Schicht bezeichnet werden. Daraus ergibt sich folgendes endgültiges Kommunikationsschema:

Die verschiedenen Schichten haben folgende Funktionen:

Physikalische Schicht
Gewährleistet die Übertragung von Bits über ein physikalisches Medium. In dieser Schicht finden sich Endgeräte zur Datenverarbeitung (E.T.T.D.), wie beispielsweise Terminals oder Computer, sowie Geräte zum Abschluss von Datenleitungen (E.T.C.D.), wie Modulatoren/Demodulatoren, Multiplexer und Konzentratoren. Die wichtigsten Aspekte auf dieser Ebene sind:
  • die Wahl der Informationskodierung (analog oder digital)
  • die Wahl des Übertragungsmodus (synchron oder asynchron).
Datenverbindung
Versteckt die physikalischen Besonderheiten der physikalischen Schicht. Erkennt und korrigiert Übertragungsfehler.
Netzwerk
Verwaltet den Weg, den die im Netzwerk gesendeten Informationen zurücklegen müssen. Dies wird als routage bezeichnet: die Bestimmung der Route, die eine Information nehmen muss, damit sie ihren Empfänger erreicht.
Transport
Ermöglicht die Kommunikation zwischen zwei Anwendungen, während die vorherigen Schichten nur die Kommunikation zwischen Rechnern ermöglichten. Ein von dieser Schicht bereitgestellter Dienst kann beispielsweise das Multiplexing sein: Die Transportschicht kann dieselbe Netzwerkverbindung (von Rechner zu Rechner) nutzen, um Informationen mehrerer Anwendungen zu übertragen.
Sitzung
In dieser Schicht finden sich Dienste, die es einer Anwendung ermöglichen, eine Arbeitssitzung auf einem Remote-Rechner zu eröffnen und aufrechtzuerhalten.
Präsentation
Sie zielt darauf ab, die Darstellung von Daten auf den verschiedenen Rechnern zu vereinheitlichen. So werden Daten, die von Rechner A stammen, von der Schicht Présentation des Rechners A gemäß einem Standardformat „aufbereitet“, bevor sie über das Netzwerk gesendet werden. Wenn sie die Schicht Présentation des Zielrechners B erreichen, der sie anhand ihres Standardformats erkennt, werden sie auf andere Weise aufbereitet, damit die Anwendung auf Rechner B sie erkennen kann.
Anwendung
Auf dieser Ebene befinden sich die Anwendungen, die in der Regel nah am Benutzer angesiedelt sind, wie beispielsweise E-Mail oder Dateiübertragung.

2.4.2. Das Modell TCP/IP

Das Modell OSI ist ein ideales Modell. Die Protokollsuite TCP/IP kommt diesem in folgender Form nahe:

  • Die Netzwerkschnittstelle (die Netzwerkkarte des Computers) übernimmt die Funktionen der Schichten 1 und 2 des Modells OSI
  • Die Schicht IP (Internet Protocol) übernimmt die Funktionen der Schicht 3 (Netzwerk)
  • Die Schicht TCP (Transfer Control Protocol) oder UDP (User Datagram Protocol) übernimmt die Funktionen der Schicht 4 (Transport). Das Protokoll TCP stellt sicher, dass die zwischen den Rechnern ausgetauschten Datenpakete ihr Ziel erreichen. Ist dies nicht der Fall, sendet es die fehlgeleiteten Pakete zurück. Das Protokoll UDP übernimmt diese Aufgabe nicht, sodass es dem Anwendungsentwickler obliegt, dies zu tun. Aus diesem Grund wird im Internet, das kein zu 100 % zuverlässiges Netzwerk ist, vor allem das Protokoll TCP verwendet. Man spricht dann von einem TCP-IP-Netzwerk.
  • Die Anwendungsschicht deckt die Funktionen der Schichten 5 bis 7 des OSI-Modells ab.

Webanwendungen befinden sich in der Schicht Application und stützen sich somit auf die Protokolle TCP-IP. Die Schichten Application der Client- und Server-Rechner tauschen Nachrichten aus, die den Schichten 1 bis 4 des Modells zur Weiterleitung an den Bestimmungsort übergeben werden. Um sich zu verstehen, müssen die Anwendungsschichten beider Rechner dieselbe Sprache bzw. dasselbe Protokoll „sprechen“. Das Protokoll für Webanwendungen heißt HTTP (HyperText Transfer Protocol). Es handelt sich um ein textbasiertes Protokoll, d. h., die Rechner tauschen Textzeilen über das Netzwerk aus, um sich zu verständigen. Dieser Austausch ist standardisiert, d. h., der Client verfügt über eine bestimmte Anzahl von Nachrichten, um dem Server genau mitzuteilen, was er möchte, und der Server verfügt ebenfalls über eine bestimmte Anzahl von Nachrichten, um dem Client seine Antwort zu übermitteln. Dieser Nachrichtenaustausch hat folgende Form:

Image

Client --> Server

Wenn der Client seine Anfrage an den Webserver sendet, übermittelt er

  1. Textzeilen im Format HTTP, um anzugeben, was er möchte;
  2. eine Leerzeile;
  3. optional ein Dokument.

Server --> Client

Wenn der Server dem Client antwortet, sendet er

  1. Textzeilen im Format HTTP, um anzugeben, was er sendet;
  2. eine leere Zeile;
  3. optional ein Dokument.

Der Datenaustausch erfolgt somit in beide Richtungen in derselben Form. In beiden Fällen kann ein Dokument gesendet werden, auch wenn es selten vorkommt, dass ein Client ein Dokument an den Server sendet. Das Protokoll HTTP sieht dies jedoch vor. Dadurch können beispielsweise Kunden eines Internetanbieters verschiedene Dokumente auf ihre bei diesem Anbieter gehostete persönliche Website hochladen. Die ausgetauschten Dokumente können beliebiger Art sein. Nehmen wir einen Browser, der eine Webseite mit Bildern anfordert:

  1. Der Browser stellt eine Verbindung zum Webserver her und fordert die gewünschte Seite an. Die angeforderten Ressourcen werden eindeutig durch URL (Uniform Resource Locator) bezeichnet. Der Browser sendet lediglich HTTP-Header und kein Dokument.
  2. Der Server antwortet ihm. Er sendet zunächst HTTP-Header, die angeben, welche Art von Antwort er sendet. Dies kann ein Fehler sein, wenn die angeforderte Seite nicht existiert. Wenn die Seite existiert, gibt der Server in den HTTP-Header seiner Antwort an, dass er im Anschluss daran ein Dokument im Format HTML (HyperText Markup Language) senden wird. Dieses Dokument besteht aus einer Folge von Textzeilen im Format HTML. Ein HTML-Text enthält Tags (Markierungen), die dem Browser Anweisungen zur Darstellung des Textes geben.
  3. Der Client erkennt anhand der HTTP-Header des Servers, dass er ein HTML-Dokument erhalten wird. Er analysiert dieses Dokument und stellt möglicherweise fest, dass es Bildverweise enthält. Diese sind im Dokument HTML nicht enthalten. Daher sendet er eine neue Anfrage an denselben Webserver, um das erste benötigte Bild anzufordern. Diese Anfrage ist identisch mit der in Schritt 1, nur dass die angeforderte Ressource eine andere ist. Der Server bearbeitet diese Anfrage, indem er dem Client das angeforderte Bild sendet. Diesmal geben die Header HTTP in seiner Antwort an, dass es sich bei dem gesendeten Dokument um ein Bild und nicht um ein Dokument HTML handelt.
  4. Der Client empfängt das gesendete Bild. Die Schritte 3 und 4 werden so lange wiederholt, bis der Client (in der Regel ein Browser) über alle Dokumente verfügt, die er zur Anzeige der gesamten Seite benötigt.

2.4.3. Das Protokoll HTTP

Lassen Sie uns das Protokoll HTTP anhand von Beispielen näher betrachten. Was tauschen ein Browser und ein Webserver aus?

Der Webdienst oder HTTP-Dienst ist ein TCP-IP-Dienst, der normalerweise auf Port 80 läuft. Er könnte auch auf einem anderen Port laufen. In diesem Fall müsste der Client-Browser diesen Port in der von ihm angeforderten URL-Anfrage angeben. Eine URL hat im Allgemeinen folgende Form:

Protokoll://[:port]-Rechner/Pfad/Infos

wobei

Protokoll
http für den Webdienst. Ein Browser kann auch als Client für FTP-, News-, Telnet-Dienste usw. dienen.
Rechner
Name des Rechners, auf dem der Webdienst läuft
Port
Port des Webdienstes. Bei Port 80 kann die Portnummer weggelassen werden. Dies ist der häufigste Fall
Pfad
Pfad, der auf die angeforderte Ressource verweist
Infos
zusätzliche Informationen, die dem Server übermittelt werden, um die Anfrage des Clients zu präzisieren

Was macht ein Browser, wenn ein Benutzer das Laden einer URL anfordert?

  1. Er baut eine Verbindung TCP-IP mit dem Rechner und dem Port auf, die im Abschnitt „machine[:port]“ des URL angegeben sind. Eine TCP-IP-Verbindung zu öffnen bedeutet, eine „Kommunikationsverbindung“ zwischen zwei Rechnern herzustellen. Sobald diese Verbindung hergestellt ist, werden alle zwischen den beiden Rechnern ausgetauschten Informationen über sie übertragen. Die Erstellung dieser Verbindung TCP-IP beinhaltet noch nicht das Webprotokoll HTTP.
  2. Sobald die Verbindung TCP-IP hergestellt ist, sendet der Client seine Anfrage an den Webserver, indem er Textzeilen (Befehle) im Format HTTP an ihn übermittelt. Er sendet dem Server den Pfad-/Informationsteil von URL
  3. Der Server antwortet auf die gleiche Weise und über dieselbe Verbindung
  4. Einer der beiden Partner trifft die Entscheidung, die Verbindung zu schließen. Dies hängt vom verwendeten Protokoll HTTP ab. Beim Protokoll HTTP 1.0 schließt der Server die Verbindung nach jeder seiner Antworten. Dies zwingt einen Client, der mehrere Anfragen stellen muss, um die verschiedenen Dokumente zu erhalten, aus denen eine Webseite besteht, bei jeder Anfrage eine neue Verbindung zu öffnen, was mit Kosten verbunden ist. Beim Protokoll HTTP/1.1 kann der Client den Server anweisen, die Verbindung offen zu halten, bis er ihn auffordert, sie zu schließen. Er kann somit alle Dokumente einer Webseite über eine einzige Verbindung abrufen und die Verbindung selbst schließen, sobald das letzte Dokument empfangen wurde. Der Server erkennt diese Schließung und schließt die Verbindung ebenfalls.

Um den Datenaustausch zwischen einem Client und einem Webserver zu untersuchen, verwenden wir die Chrome-Erweiterung [Advanced Rest Client], die wir in Abschnitt 9.6 installiert haben. Wir befinden uns in folgender Situation:

Image

Der Webserver kann beliebig sein. Wir wollen hier herausfinden, welcher Datenaustausch zwischen dem Browser und dem Webserver stattfindet. Zuvor haben wir die folgende statische Seite „HTML“ erstellt:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>essai 1 : une page statique</title>
</head>
<body>
  <h1>Une page statique...</h1>
</body>
</html>

die wir in einem Browser anzeigen:

 

Man sieht, dass die angeforderte Seite URL lautet: [http://localhost:9000/intro/exemple-01.html]. Der Webserver ist also localhost (=lokaler Rechner) und der Port 9000. Verwenden wir die Anwendung [Advanced Rest Client], um denselben URL abzufragen:

  • bei [1] starten wir die Anwendung (im Tab [Applications] eines neuen Chrome-Tabs);
  • unter [2] wählt man die Option [Request] aus;
  • unter [3] gibt man den abgefragten Server an: http://localhost:9000;
  • in [4] wird die angeforderte URL angegeben: /intro/exemple-01.html;
  • In [5] werden eventuelle Parameter zur URL URL hinzugefügt. Hier keine;
  • In [6] wird der für die Anfrage verwendete Befehl HTTP angegeben, hier GET.

Daraus ergibt sich folgende Abfrage:

Die so vorbereitete Abfrage [7] wird von [8] an den Server gesendet. Die erhaltene Antwort lautet dann wie folgt:

Wir haben oben erwähnt, dass der Austausch zwischen Client und Server folgende Form hat:

Image

  • In [1] sind die vom Browser in seiner Anfrage gesendeten Header HTTP zu sehen. Es gab kein Dokument zum Senden;
  • In [2] sieht man die vom Server als Antwort gesendeten Header HTTP. In [3] sieht man das Dokument, das er gesendet hat.

In [3] erkennt man die statische Seite HTML, die wir auf dem Webserver abgelegt haben.

Sehen wir uns die Anfrage HTTP des Browsers an:

GET /intro/exemple-01.html HTTP/1.1
Host: localhost:9000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Content-Type: text/plain; charset=utf-8
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
  • Zeile 1 wurde von der Anwendung nicht angezeigt;
  • Zeile 6: Der Browser identifiziert sich mit dem Header [User-Agent];
  • Zeile 7: Der Browser gibt an, dass er ein Textdokument (text/plain) im Format UTF-8 an den Server sendet. Tatsächlich hat der Browser hier jedoch kein Dokument gesendet;
  • Zeile 8: Der Browser gibt an, dass er als Antwort jeden Dokumenttyp akzeptiert;
  • Zeile 9: Der Browser gibt die akzeptierten Dokumentformate an;
  • Zeile 10: Der Browser gibt die gewünschten Sprachen in der Reihenfolge ihrer Präferenz an.

Der Server hat ihm geantwortet, indem er die folgenden Header HTTP gesendet hat:

1
2
3
4
5
6
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Last-Modified: Sat, 29 Nov 2014 07:31:43 GMT
Content-Type: text/html
Content-Length: 255
Date: Sat, 29 Nov 2014 08:20:52 GMT
  • Zeile 1: wurde von der Anwendung nicht angezeigt;
  • Zeile 2: Der Server identifiziert sich, in diesem Fall handelt es sich um einen Apache-Coyote-Server;
  • Zeile 3: Datum der letzten Änderung des gesendeten Dokuments;
  • Zeile 4: Art des vom Server gesendeten Dokuments. Hier ein HTML-Dokument;
  • Zeile 5: Die Größe des gesendeten Dokuments HTML in Byte.
  • Zeile 6: Datum und Uhrzeit der Antwort;

2.4.4. Fazit

Anhand einiger Beispiele haben wir die Struktur der Anfrage eines Web-Clients und die der Antwort des Web-Servers darauf kennengelernt. Der Dialog erfolgt über das Protokoll HTTP, eine Reihe von Befehlen im Textformat, die zwischen den beiden Partnern ausgetauscht werden. Die Anfrage des Clients und die Antwort des Servers weisen beide die folgende Struktur auf:

Image

Die beiden üblichen Befehle zum Abrufen einer Ressource lauten GET und POST. Der Befehl GET wird nicht von einem Dokument begleitet. Der Befehl POST hingegen wird von einem Dokument begleitet, bei dem es sich meist um eine Zeichenkette handelt, die alle in einem Formular eingegebenen Werte zusammenfasst. Der Befehl HEAD dient dazu, ausschließlich die Kopfzeilen HTTP abzufragen, und enthält kein Dokument.

Auf Anfrage eines Clients sendet der Server eine Antwort mit derselben Struktur. Die angeforderte Ressource wird im Abschnitt [Document] übermittelt, es sei denn, der Befehl des Clients lautete HEAD; in diesem Fall werden nur die Header HTTP gesendet.

2.5. Grundlagen der Sprache HTML

Ein Webbrowser kann verschiedene Dokumente anzeigen, wobei das häufigste das Dokument HTML (HyperText Markup Language) ist. Dabei handelt es sich um einen Text, der mit Tags der Form <balise>texte</balise> formatiert ist. So wird der Text „<B>important</B>“ den wichtigen Text in Fettdruck anzeigen. Es gibt auch einzelne Tags wie das Tag „<hr/>“, das eine horizontale Linie anzeigt. Wir werden hier nicht auf alle Tags eingehen, die in einem HTML-Text vorkommen können. Es gibt zahlreiche Programme, mit denen man eine Webseite erstellen kann, ohne eine einzige Zeile Code zu schreiben. Diese Tools generieren automatisch den Code eines Layouts, das mit der Maus und vordefinierten Steuerelementen erstellt wurde. So kann man (mit der Maus) eine Tabelle in die Seite einfügen und anschließend den von der Software generierten HTML-Code einsehen, um herauszufinden, welche Tags zur Definition einer Tabelle auf einer Webseite verwendet werden müssen. Einfacher geht es nicht. Außerdem sind Kenntnisse der Sprache HTML unerlässlich, da dynamische Webanwendungen den an die Web-Clients zu sendenden Code HTML selbst generieren müssen. Dieser Code wird programmgesteuert generiert, und man muss natürlich wissen, was generiert werden muss, damit der Client die gewünschte Webseite erhält.

Zusammenfassend lässt sich sagen, dass man keineswegs die gesamte Sprache HTML beherrschen muss, um mit der Webprogrammierung zu beginnen. Diese Kenntnisse sind jedoch notwendig und können durch die Verwendung von WYSIWYG-Software zur Erstellung von Webseiten wie DreamWeaver und Dutzenden anderer Programme erworben werden. Eine weitere Möglichkeit, die Feinheiten der Sprache HTML zu entdecken, besteht darin, im Web zu stöbern und den Quellcode von Seiten anzuzeigen, die interessante und Ihnen noch unbekannte Merkmale aufweisen.

2.5.1. Ein Beispiel

Betrachten wir das folgende Beispiel, das einige Elemente enthält, die in einem Webdokument vorkommen können, wie zum Beispiel:

  • eine Tabelle;
  • ein Bild;
  • einen Link.

Ein HTML-Dokument hat im Allgemeinen folgende Form:

<html>
    <head>
        <title>Un titre</title>
        ...
    </head>
    <body attributs>
        ...
    </body>
</html>

Das gesamte Dokument wird von den Tags <html>...</html> umschlossen. Es besteht aus zwei Teilen:

  1. <head>...</head>: Dies ist der nicht sichtbare Teil des Dokuments. Er enthält Informationen für den Browser, der das Dokument anzeigen wird. Oft findet man hier das Tag <title>...</title>, das den Text festlegt, der in der Titelleiste des Browsers angezeigt wird. Außerdem können hier weitere Tags vorkommen, insbesondere solche, die die Schlüsselwörter des Dokuments definieren – Schlüsselwörter, die anschließend von Suchmaschinen verwendet werden. In diesem Teil können sich auch Skripte befinden, die meist in JavaScript oder VBScript geschrieben sind und vom Browser ausgeführt werden.
  1. <body-Attribute>...</body>: Dies ist der Teil, der vom Browser angezeigt wird. Die in diesem Teil enthaltenen Tags HTML geben dem Browser die „gewünschte“ visuelle Darstellung des Dokuments vor. Jeder Browser interpretiert diese Tags auf seine eigene Weise. Zwei Browser können daher ein und dasselbe Webdokument unterschiedlich darstellen. Dies ist in der Regel eine der Herausforderungen für Webdesigner.

Der Code HTML unseres Beispieldokuments lautet wie folgt:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>balises</title>
</head>

<body style="height: 400px; width: 400px; background-image: url(images/standard.jpg)">
    <h1 style="text-align: center">Les balises HTML</h1>
    <hr />
    <table border="1">
        <thead>
            <tr>
                <th>Colonne 1</th>
                <th>Colonne 2</th>
                <th>Colonne 3</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>cellule(1,1)</td>
                <td style="width: 150px; text-align: center;">cellule(1,2)</td>
                <td>cellule(1,3)</td>
            </tr>
            <tr>
                <td>cellule(2,1)</td>
                <td>cellule(2,2)</td>
                <td>cellule(2,3</td>
            </tr>
        </tbody>
    </table>

    <table>
        <tr>
            <td>Une image</td>
            <td><img border="0" src="images/cerisier.jpg" /></td>
        </tr>
        <tr>
            <td>le site de l'ISTIA</td>
            <td><a href="http://istia.univ-angers.fr">ici</a></td>
        </tr>
    </table>
</body>
</html>
Element
Tags und Beispiele HTML
Dokumenttitel
<title>Tags</title> (Zeile 5)
Der Text balises erscheint in der Titelleiste des Browsers, der das Dokument anzeigt
horizontale Leiste
<hr/>: Zeigt einen horizontalen Strich an (Zeile 10)
Tabelle
<Tabellenattribute>....</table>: zum Definieren der Tabelle (Zeilen 11, 31)
<thead>...</thead>: zum Definieren der Spaltenüberschriften (Zeilen 12, 18)
<tbody>...</tbody>: zum Definieren des Tabelleninhalts (Zeile 19, 30)
<tr Attribute>...</tr>: zur Definition einer Zeile (Zeilen 20, 24)
<td Attribute>...</td>: zum Definieren einer Zelle (Zeile 21)
Beispiele:
<table border="1">...</table>: Das Attribut „border“ legt die Dicke des Tabellenrandes fest
<td style="width: 150px; text-align: center;">Zelle(1,2)</td>: definiert eine Zelle, deren Inhalt „Zelle(1,2)“ lautet. Dieser Inhalt wird horizontal zentriert (text-align: center). Die Zelle hat eine Breite von 150 Pixeln (width: 150px)
Bild
<img border="0" src="/images/cerisier.jpg"/> (Zeile 36): Definiert ein Bild ohne Rahmen (border=0"), dessen Quelldatei sich unter /images/cerisier.jpg auf dem Webserver befindet (src="images/cerisier.jpg"). Dieser Link befindet sich in einem Webdokument, das mit dem URL http://localhost:port/intro/exemple-04.html erstellt wurde. Daher fordert der Browser die Datei URL http://localhost:port/intro/images/cerisier.jpg an, um das hier referenzierte Bild zu erhalten.
Link
<a href="http://istia.univ-angers.fr">hier</a> (Zeile 40): bewirkt, dass der Text ici als Link zu http://istia.univ-angers.fr dient.
Seitenhintergrund
<body style="height:400px;width:400px;background-image:url(images/standard.jpg)"> (Zeile 8): Gibt an, dass sich das Bild, das als Seitenhintergrund dienen soll, unter der Adresse URL [images/standard.jpg] auf dem Webserver befindet. In unserem Beispiel ruft der Browser die URL http://localhost:port/intro/images/standard.jpg ab, um dieses Hintergrundbild zu laden. Der Hauptteil des Dokuments wird dabei in einem Rechteck mit einer Höhe von 400 Pixeln und einer Breite von 400 Pixeln angezeigt.

An diesem einfachen Beispiel wird deutlich, dass der Browser drei Anfragen an den Server stellen muss, um das gesamte Dokument aufzubauen:

  1. http://localhost:port/intro/exemple-04.html, um die Quelldatei HTML des Dokuments abzurufen
  2. http://localhost:port/intro/images/cerisier.jpg, um das Bild cerisier.jpg abzurufen
  3. http://localhost:port/intro/images/standard.jpg, um das Hintergrundbild standard.jpg abzurufen

2.5.2. Ein Formular HTML

Das folgende Beispiel zeigt ein Formular:

Der Code HTML, der diese Anzeige erzeugt, lautet wie folgt:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>formulaire</title>
  <script type="text/javascript">
    function effacer() {
      alert("Vous avez cliqué sur le bouton Effacer");
    }
  </script>
</head>

<body style="height: 400px; width: 400px; background-image: url(images/standard.jpg)">
  <h1 style="text-align: center">Formulaire HTML</h1>
  <form method="post" action="postFormulaire">
    <table>
      <tr>
        <td>Etes-vous marié(e)</td>
        <td>
          <input type="radio" value="Oui" name="R1" />Oui
          <input type="radio" name="R1" value="non" checked="checked" />Non
        </td>
      </tr>
      <tr>
        <td>Cases à cocher</td>
        <td>
          <input type="checkbox" name="C1" value="un" />1
          <input type="checkbox" name="C2" value="deux" checked="checked" />2
          <input type="checkbox" name="C3" value="trois" />3
        </td>
      </tr>
      <tr>
        <td>Champ de saisie</td>
        <td>
          <input type="text" name="txtSaisie" size="20" value="qqs mots" />
        </td>
      </tr>
      <tr>
        <td>Mot de passe</td>
        <td>
          <input type="password" name="txtMdp" size="20" value="unMotDePasse" />
        </td>
      </tr>
      <tr>
        <td>Boîte de saisie</td>
        <td>
          <textarea rows="2" name="areaSaisie" cols="20">
ligne1
ligne2
ligne3
</textarea>
        </td>
      </tr>
      <tr>
        <td>combo</td>
        <td>
          <select size="1" name="cmbValeurs">
            <option value="1">choix1</option>
            <option selected="selected" value="2">choix2</option>
            <option value="3">choix3</option>
          </select>
        </td>
      </tr>
      <tr>
        <td>liste à choix simple</td>
        <td>
          <select size="3" name="lst1">
            <option selected="selected" value="1">liste1</option>
            <option value="2">liste2</option>
            <option value="3">liste3</option>
            <option value="4">liste4</option>
            <option value="5">liste5</option>
          </select>
        </td>
      </tr>
      <tr>
        <td>liste à choix multiple</td>
        <td>
          <select size="3" name="lst2" multiple="multiple">
            <option value="1" selected="selected">liste1</option>
            <option value="2">liste2</option>
            <option selected="selected" value="3">liste3</option>
            <option value="4">liste4</option>
            <option value="5">liste5</option>
          </select>
        </td>
      </tr>
      <tr>
        <td>bouton</td>
        <td>
          <input type="button" value="Effacer" name="cmdEffacer" onclick="effacer()" />
        </td>
      </tr>
      <tr>
        <td>envoyer</td>
        <td>
          <input type="submit" value="Envoyer" name="cmdRenvoyer" />
        </td>
      </tr>
      <tr>
        <td>rétablir</td>
        <td>
          <input type="reset" value="Rétablir" name="cmdRétablir" />
        </td>
      </tr>
    </table>
    <input type="hidden" name="secret" value="uneValeur" />
  </form>
</body>
</html>

Die Zuordnung zwischen der visuellen Darstellung und dem Tag HTML lautet wie folgt:

Prüfung
Tag HTML
Formular
<form method="post" action="...">
Eingabefeld
<input type="text" name="txtSaisie" size="20" value="ein paar Wörter" />
verdecktes Eingabefeld
<input type="password" name="txtMdp" size="20" value="unMotDePasse" />
mehrzeiliges Eingabefeld
<textarea rows="2" name="areaSaisie" cols="20">
Zeile 1
Zeile 2
Zeile 3
</textarea>
Optionsfelder
<input type="radio" value="Ja" name="R1" />Ja
<input type="radio" name="R1" value="nein" checked="checked" />Nein
Kontrollkästchen
<input type="checkbox" name="C1" value="eins" />1
<input type="checkbox" name="C2" value="zwei" checked="checked" />2
<input type="checkbox" name="C3" value="drei" />3
Kombinationsfeld
<select size="1" name="cmbValeurs">
<option value="1">Auswahl 1</option>
<option selected="selected" value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
Auswahlliste mit einer Auswahlmöglichkeit
<select size="3" name="lst1">
<option selected="selected" value="1">Liste 1</option>
<option value="2">Liste 2</option>
<option value="3">Liste 3</option>
<option value="4">Liste 4</option>
<option value="5">Liste 5</option>
</select>
Liste mit Mehrfachauswahl
<select size="3" name="lst2" multiple="multiple">
<option value="1">Liste1</option>
<option value="2">Liste 2</option>
<option selected="selected" value="3">Liste 3</option>
<option value="4">Liste 4</option>
<option value="5">Liste 5</option>
</select>
Submit-Schaltfläche
<input type="submit" value="Senden" name="cmdRenvoyer" />
Reset-Schaltfläche
<input type="reset" value="Zurücksetzen" name="cmdRétablir" />
Schaltfläche vom Typ „button“
<input type="button" value="Löschen" name="cmdEffacer" onclick="effacer()" />

Sehen wir uns diese verschiedenen Tags einmal genauer an:

2.5.2.1. Das Formular-

Formular

<form method="post" action="postFormulaire">
Tag HTML
<form name="..." method="..." action="...">...</form>
Attribute
name="frmexemple": Name des Formulars
method="...": Methode, die vom Browser verwendet wird, um die im Formular erfassten Werte an den Webserver zu senden
action="...": URL, an die die im Formular erfassten Werte gesendet werden.
Ein Webformular wird von den Tags <form>...</form> umschlossen. Das Formular kann einen Namen haben (name="xx"). Dies gilt für alle Steuerelemente, die in einem Formular vorkommen können. Der Zweck eines Formulars besteht darin, die vom Benutzer über Tastatur und Maus eingegebenen Informationen zu sammeln und diese an eine URL des Webservers zu senden. An welche? An diejenige, die im Attribut action="URL" angegeben ist. Fehlt dieses Attribut, werden die Informationen an den Webserver des Dokuments gesendet, in dem sich das Formular befindet. Ein Webclient kann zwei verschiedene Methoden namens POST und GET verwenden, um Daten an einen Webserver zu senden. Das Attribut method="méthode", wobei method gleich GET oder POST ist, des Tags <form> gibt dem Browser vor, welche Methode zum Senden der im Formular erfassten Informationen an die durch das Attribut action="URL" angegebene Adresse URL verwendet werden soll. Wenn das Attribut method nicht angegeben ist, wird standardmäßig die Methode GET verwendet.

2.5.2.2. Die Texteingabefelder

Eingabefeld
<input type="text" name="txtSaisie" size="20" value="ein paar Wörter" />
<input type="password" name="txtMdp" size="20" value="unMotDePasse" />
 
Tag HTML
<input type="..." name="..." size=".." value=".."/>
Das input-Tag gibt es für verschiedene Steuerelemente. Das Attribut type ermöglicht es, diese verschiedenen Steuerelemente voneinander zu unterscheiden.
Attribute
type="text": Gibt an, dass es sich um ein Eingabefeld handelt
type="password": Die Zeichen im Eingabefeld werden durch *-Zeichen ersetzt. Dies ist der einzige Unterschied zum normalen Eingabefeld. Diese Art von Steuerelement eignet sich für die Eingabe von Passwörtern.
size="20": Anzahl der im Feld sichtbaren Zeichen – verhindert nicht die Eingabe weiterer Zeichen
name="txtSaisie": Name des Steuerelements
value="ein paar Wörter": Text, der im Eingabefeld angezeigt wird.

2.5.2.3. Mehrzeilige Eingabefelder

Mehrzeiliges Eingabefeld
<textarea rows="2" name="areaSaisie" cols="20">
Zeile 1
Zeile 2
Zeile 3
</textarea>
 
Tag HTML
<textarea ...>Text</textarea>
zeigt ein mehrzeiliges Eingabefeld an, das zunächst bereits Text enthält
Attribute
rows="2": Anzahl der Zeilen
cols="'20" : Anzahl der Spalten
name="areaSaisie": Name des Steuerelements

2.5.2.4. Die Optionsfelder

Optionsfelder
<input type="radio" value="Ja" name="R1" />Ja
<input type="radio" name="R1" value="nein" checked="checked" />Nein
 
Tag HTML
<input type="radio" attribut2="Wert2" ..../>Text
zeigt ein Optionsfeld mit Text daneben an.
Attribute
name="radio": Name des Steuerelements. Radiobuttons mit demselben Namen bilden eine Gruppe von sich gegenseitig ausschließenden Schaltflächen: Es kann immer nur einer davon ausgewählt werden.
value="Wert": dem Optionsfeld zugewiesener Wert. Dieser Wert ist nicht mit dem Text zu verwechseln, der neben dem Optionsfeld angezeigt wird. Letzterer dient lediglich der Anzeige.
checked="checked": Ist dieses Schlüsselwort vorhanden, ist das Optionsfeld markiert, andernfalls nicht.

2.5.2.5. Die Kontrollkästchen

Kontrollkästchen
<input type="checkbox" name="C1" value="eins" />1
<input type="checkbox" name="C2" value="zwei" checked="checked" />2
<input type="checkbox" name="C3" value="drei" />3
 
Tag HTML
<input type="checkbox" attribut2="Wert2" ....>Text
zeigt ein Kontrollkästchen mit Text daneben an.
Attribute
name="C1": Name des Steuerelements. Kontrollkästchen können denselben Namen haben oder auch nicht. Kontrollkästchen mit demselben Namen bilden eine Gruppe zugehöriger Kontrollkästchen.
value="Wert": dem Kontrollkästchen zugewiesener Wert. Dieser Wert ist nicht mit dem Text zu verwechseln, der neben dem Kontrollkästchen angezeigt wird. Letzterer dient lediglich der Anzeige.
checked= „checked“: Ist dieses Schlüsselwort vorhanden, ist das Kontrollkästchen aktiviert, andernfalls nicht.

2.5.2.6. Die Dropdown-Liste (Combo)

Kombinationsfeld
<select size="1" name="cmbValeurs">
<option value="1">Auswahl 1</option>
<option selected="selected" value="2">Auswahl 2</option>
<option value="3">Option 3</option>
</select>
 
Tag HTML
<select size=".." name="..">
<option [selected="selected"] value=”v”>...</option>
...
</select>
zeigt die Texte zwischen den Tags <option>...</option>
Attribute
name="cmbValeurs": Name des Steuerelements.
size="1": Anzahl der sichtbaren Listenelemente. size="1" macht die Liste zu einer Combobox.
selected="selected": Wenn dieses Schlüsselwort für ein Listenelement vorhanden ist, wird dieses in der Liste als ausgewählt angezeigt. In unserem obigen Beispiel erscheint das Listenelement choix2 als ausgewähltes Element der Combobox, wenn diese zum ersten Mal angezeigt wird.
value=”v”: Wenn das Element vom Benutzer ausgewählt wird, wird dieser Wert [v] an den Server gesendet. Fehlt dieses Attribut, wird der angezeigte und ausgewählte Text an den Server gesendet.

2.5.2.7. Einfachauswahlliste

Liste mit einer Auswahlmöglichkeit
<select size="3" name="lst1">
<option selected="selected" value="1">Liste1</option>
<option value="2">Liste 2</option>
<option value="3">Liste 3</option>
<option value="4">Liste 4</option>
<option value="5">Liste 5</option>
</select>
 
Tag HTML
<select size=".." name="..">
<option [selected="selected"]>...</option>
...
</select>
zeigt die Texte zwischen den Tags <option>...</option>
Attribute
sind dieselben wie bei der Dropdown-Liste, die nur ein Element anzeigt. Dieses Steuerelement unterscheidet sich von der vorherigen Dropdown-Liste lediglich durch das Attribut „size>1“.

2.5.2.8. Liste mit Mehrfachauswahl

Einzelauswahlliste
<select size="3" name="lst2" multiple="multiple">
<option value="1" selected="selected">Liste1</option>
<option value="2">Liste2</option>
<option selected="selected" value="3">Liste 3</option>
<option value="4">Liste 4</option>
<option value="5">Liste 5</option>
</select>
 
Tag HTML
<select size=".." name=".." multiple="multiple">
<option [selected="selected"]>...</option>
...
</select>
zeigt die Texte zwischen den Tags <option>...</option>
Attribute
multiple: Ermöglicht die Auswahl mehrerer Elemente in der Liste. Im obigen Beispiel sind die Elemente liste1 und liste3 beide ausgewählt.

2.5.2.9. Schaltfläche vom Typ „button“

Schaltfläche vom Typ „button“
<input type="button" value="Löschen" name="cmdEffacer" onclick="effacer()" />
 
Tag HTML
<input type="button" value="..." name="..." onclick="effacer()" ..../>
Attribute
type="button": Definiert ein Schaltfeld. Es gibt zwei weitere Schaltfeldtypen: submit und reset.
value="Löschen": Der auf der Schaltfläche angezeigte Text
onclick="Funktion()": Ermöglicht die Definition einer Funktion, die ausgeführt werden soll, wenn der Benutzer auf die Schaltfläche klickt. Diese Funktion ist Teil der im angezeigten Webdokument definierten Skripte. Die oben angegebene Syntax entspricht der javascript-Syntax. Wenn die Skripte in VBScript geschrieben sind, müsste man onclick="Funktion" ohne Klammern schreiben. Die Syntax bleibt identisch, wenn Parameter an die Funktion übergeben werden sollen: onclick="Funktion(val1, val2,...)"
In unserem Beispiel ruft ein Klick auf die Schaltfläche Effacer die folgende JavaScript-Funktion effacer auf:
<script type="text/javascript">
function effacer() {
alert("Sie haben auf die Schaltfläche ‚Löschen‘ geklickt");
}
</script>
Die Funktion effacer zeigt folgende Meldung an:

2.5.2.10. Submit-Schaltfläche

Submit-Schaltfläche
<input type="submit" value="Senden" name="cmdRenvoyer" />
 
Tag HTML
<input type="submit" value="Senden" name="cmdRenvoyer" />
Attribute
type="submit": Definiert die Schaltfläche als Schaltfläche zum Senden der Formulardaten an den Webserver. Wenn der Benutzer auf diese Schaltfläche klickt, sendet der Browser die Formulardaten an die im Attribut „action“ des Tags <form> angegebene Adresse gemäß der im Attribut „method“ desselben Tags definierten Methode.
value="Senden": Der auf der Schaltfläche angezeigte Text

2.5.2.11. Reset-Schaltfläche

Reset-Schaltfläche
<input type="reset" value="Zurücksetzen" name="cmdRétablir" />
 
Tag HTML
<input type="reset" value="Zurücksetzen" name="cmdRétablir"/>
Attribute
type="reset": Definiert die Schaltfläche als Schaltfläche zum Zurücksetzen des Formulars. Wenn der Benutzer auf diese Schaltfläche klickt, versetzt der Browser das Formular in den Zustand zurück, in dem es empfangen wurde.
value="Zurücksetzen": Der auf der Schaltfläche angezeigte Text

2.5.2.12. Verstecktes Feld

verstecktes Feld
<input type="hidden" name="secret" value="uneValeur" />
Tag HTML
<input type="hidden" name="..." value="..."/>
Attribute
type="hidden": Gibt an, dass es sich um ein verstecktes Feld handelt. Ein verstecktes Feld ist Teil des Formulars, wird dem Benutzer jedoch nicht angezeigt. Würde der Benutzer jedoch in seinem Browser den Quellcode anzeigen lassen, würde er das Tag <input type="hidden" value="..."> und somit den Wert des versteckten Feldes sehen.
value="einWert": Wert des versteckten Feldes.
Wozu dient das versteckte Feld? Es ermöglicht dem Webserver, Informationen über mehrere Anfragen eines Kunden hinweg zu speichern. Betrachten wir eine Online-Shopping-Anwendung. Der Kunde kauft auf einer ersten Seite eines Katalogs einen ersten Artikel art1 in der Menge q1 und wechselt dann zu einer neuen Seite des Katalogs. Um zu speichern, dass der Kunde q1 Artikel in der Menge art1 gekauft hat, kann der Server diese beiden Informationen in ein verstecktes Feld des Webformulars auf der neuen Seite einfügen. Auf dieser neuen Seite kauft der Kunde die Artikel q2 und art2. Wenn die Daten dieses zweiten Formulars an den Server gesendet werden (Submit), erhält dieser nicht nur die Information (q2, art2), sondern auch (q1, art1), die ebenfalls als verstecktes Feld Teil des Formulars sind. Der Webserver fügt dann die Informationen (q1,art1) und (q2,art2) in ein neues verstecktes Feld ein und sendet eine neue Katalogseite. Und so weiter.

2.5.3. Übermittlung der Werte eines Formulars von einem Web-Client an einen Webserver

In der vorherigen Lektion haben wir erwähnt, dass der Web-Client über zwei Methoden verfügt, um die Werte eines von ihm angezeigten Formulars an einen Webserver zu senden: die Methoden GET und POST. Sehen wir uns anhand eines Beispiels den Unterschied zwischen den beiden Methoden an.

2.5.3.1. Methode „ “ GET

Führen wir einen ersten Test durch, bei dem im Code HTML des Dokuments das Tag <form> wie folgt definiert ist:


<form method="get" action="doNothing">

Wenn der Benutzer auf die Schaltfläche [1] klickt, werden die im Formular eingegebenen Werte an den Spring-Controller [2] gesendet. Wir haben gesehen, dass die Werte des Formulars an den Controller URL und [doNothing] gesendet werden:


<form method="get" action="doNothing">

Die Aktion [doNothing] ist im Controller [MyController] [2] wie folgt definiert:


    // ----------------------- einen Feed leeren [Content-Length=0]
    @RequestMapping(value = "/doNothing")
    @ResponseBody
    public void doNothing() {
}
  • Zeile 1: Die Aktion verarbeitet die Aktion URL [/doNothing], also tatsächlich [/context/doNothing], wobei [context] der Kontext bzw. Name der Webanwendung ist, hier [/intro];
  • Zeile 3: Die Annotation [@ResponseBody] gibt an, dass das Ergebnis der annotierten Methode direkt an den Client gesendet werden soll;
  • Zeile 4: Die Methode gibt nichts zurück. Der Client erhält also eine leere Antwort vom Server.

Wir wollen lediglich wissen, wie der Browser die eingegebenen Werte an den Webserver übermittelt. Dazu verwenden wir ein in Chrome verfügbares Debugging-Tool. Wir aktivieren es durch Drücken von STRG-Umschalt-I (Großbuchstabe) [3]:

Da wir uns für den Netzwerkverkehr zwischen dem Browser und dem Webserver interessieren, öffnen wir oben die Registerkarte [Network] und klicken dann auf die Schaltfläche [Envoyer] im Formular. Dabei handelt es sich um eine Schaltfläche vom Typ [submit] innerhalb eines [form]-Tags. Der Browser reagiert auf den Klick, indem er die im Attribut [action] des Tags [form] angegebene URL [/intro/doNothing] abfragt, mit der im Attribut [method] angegebenen Methode GET. Wir erhalten dann folgende Informationen:

Der obige Screenshot zeigt uns das URL, das vom Browser nach dem Klicken auf die Schaltfläche [envoyer] angefordert wurde. Er fordert zwar die erwartete URL ([/intro/doNothing]) an, fügt aber dahinter Informationen hinzu, bei denen es sich um die im Formular eingegebenen Werte handelt. Um weitere Informationen zu erhalten, klicken wir auf den obigen Link:

Oberhalb von [1, 2] sehen wir die vom Browser gesendeten Header von HTTP. Sie wurden hier formatiert. Um den Klartext dieser Header anzuzeigen, folgen wir dem Link [view source] [3, 4]. Der vollständige Text lautet wie folgt:

GET /intro/doNothing?R1=non&C2=deux&txtSaisie=qqs+mots&txtMdp=unMotDePasse&areaSaisie=ligne1%0D%0Aligne2%0D%0Aligne3%0D%0A&cmbValeurs=2&lst1=1&lst2=1&lst2=3&cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
Host: localhost:9000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0,8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Referer: http://localhost:9000/intro/exemple-05.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

Wir finden Elemente wieder, die wir bereits zuvor gesehen haben. Andere tauchen zum ersten Mal auf:

Verbindung: Keep-Alive
Der Client fordert den Server auf, die Verbindung nach dessen Antwort nicht zu schließen. So kann er dieselbe Verbindung für eine spätere Anfrage nutzen. Die Verbindung bleibt jedoch nicht unbegrenzt offen. Der Server schließt sie nach einer zu langen Inaktivitätszeit.
Referer
die URL, die im Browser angezeigt wurde, als die neue Anfrage gestellt wurde.

Die Neuerung befindet sich in Zeile 1 der Informationen, die auf den URL folgen. Es ist festzustellen, dass die im Formular getroffenen Auswahlen in der URL wiederzufinden sind. Die vom Benutzer im Formular eingegebenen Werte wurden in den Befehl GET URL?param1=Wert1&param2=Wert2&... übergeben. HTTP/1.1, wobei die parami die Namen (Attribut name) der Steuerelemente des Webformulars und die valeuri die ihnen zugeordneten Werte sind. Nachfolgend finden Sie eine Tabelle mit drei Spalten:

  • Spalte 1: enthält die Definition eines Steuerelements HTML aus dem Beispiel;
  • Spalte 2: zeigt die Darstellung dieses Steuerelements in einem Browser;
  • Spalte 3: zeigt den Wert an, den der Browser für das Steuerelement aus Spalte 1 an den Server sendet, und zwar in der Form, wie er in der Abfrage GET aus dem Beispiel vorliegt.

Steuerelement HTML


Anzeige


zurückgegebene(r) Wert(e)

<input type="radio" value="Ja" name="R1"/>Ja
<input type="radio" name="R1" value="Nein" checked="checked"/>Nein
R1=Ja
– der Wert des Attributs value des vom Benutzer markierten Optionsfelds.
<input type="checkbox" name="C1" value="eins"/>1
<input type="checkbox" name="C2" value="zwei" checked="checked"/>2
<input type="checkbox" name="C3" value="drei"/>3
C1=eins
C2=zwei
– Werte der Attribute value der vom Benutzer angekreuzten Kontrollkästchen
<input type="text" name="txtSaisie" size="20" value="ein paar Wörter"/>
txtEingabe=Web-Programmierung
- vom Benutzer in das Eingabefeld eingegebener Text. Leerzeichen wurden durch das Pluszeichen ersetzt
<input type="password" name="txtMdp" size="20" value="unMotDePasse"/>
txtMdp=diesistgeheim
– vom Benutzer in das Eingabefeld eingegebener Text
<textarea rows="2" name="areaSaisie" cols="20">
Zeile 1
Zeile 2
Zeile 3
</textarea>
Eingabebereich=Grundlagen+der%0D%0A
Webprogrammierung+
– vom Benutzer in das Eingabefeld eingegebener Text. %OD%OA ist das Zeichen für das Zeilenende. Leerzeichen wurden durch das Pluszeichen ersetzt
<select size="1" name="cmbValeurs">
<option value='1'>Auswahl1</option>
<option selected="selected" value='2'>Auswahl 2</option>
<option value='3'>Auswahl 3</option>
</select>
cmbWerte=3
- Attribut [value] des vom Benutzer ausgewählten Elements
<select size="3" name="lst1">
<option selected="selected" value='1'>Liste1</option>
<option value='2'>Liste 2</option>
<option value='3'>Liste 3</option>
<option value='4'>Liste 4</option>
<option value='5'>Liste 5</option>
</select>
lst1=3
- Attribut [value] des vom Benutzer ausgewählten Elements
<select size="3" name="lst2" multiple="multiple">
<option selected="selected" value='1'>Liste1</option>
<option value='2'>Liste 2</option>
<option selected="selected" value='3'>Liste 3</option>
<option value='4'>Liste 4</option>
<option value='5'>Liste 5</option>
</select>
lst2=1
lst2=3
- Attribute [value] der vom Benutzer ausgewählten Elemente
<input type="submit" value="Senden" name="cmdRenvoyer"/>
 
cmdRenvoyer=Senden
- Name und Attribut value der Schaltfläche, über die die Formulardaten an den Server gesendet wurden
<input type="hidden" name="secret" value="uneValeur"/>
 
secret=einWert
- Attribut value des versteckten Feldes

2.5.3.2. Methode POST

Wir ändern das Dokument HTML so, dass der Browser nun die Methode POST verwendet, um die Formularwerte an den Webserver zu senden:


  <form method="post" action="doNothing">

Wir füllen das Formular wie bei der Methode GET aus und übermitteln die Parameter mit der Schaltfläche [Envoyer] an den Server. Wie bereits im vorigen Absatz auf Seite 63 beschrieben, haben wir in Chrome Zugriff auf die Header HTTP der vom Browser gesendeten Anfrage:

POST /intro/doNothing HTTP/1.1
Host: localhost:9000
Connection: keep-alive
Content-Length: 172
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0,8
Origin: http://localhost:9000
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:9000/intro/exemple-05.html
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

R1=non&C2=deux&txtSaisie=qqs+mots&txtMdp=unMotDePasse&areaSaisie=ligne1%0D%0Aligne2%0D%0Aligne3%0D%0A&cmbValeurs=2&lst1=1&lst2=1&lst2=3&cmdRenvoyer=Envoyer&secret=uneValeur

In der Anfrage HTTP des Clients tauchen neue Elemente auf:

POST URL HTTP/1.1
Die Abfrage GET wurde durch die Abfrage POST ersetzt. Die Parameter sind in dieser ersten Zeile der Anfrage nicht mehr vorhanden. Man kann feststellen, dass sie nun (Zeile 15) nach einer Leerzeile hinter der Anfrage HTTP stehen. Ihre Kodierung ist identisch mit derjenigen, die sie in der Anfrage GET hatten.
Content-Length
Anzahl der „gesendeten“ Zeichen, c.a.d. Die Anzahl der Zeichen, die der Webserver nach dem Empfang der Header HTTP lesen muss, um das vom Client gesendete Dokument abzurufen. Bei dem betreffenden Dokument handelt es sich hier um die Liste der Formularwerte.
Content-Type
Gibt den Typ des Dokuments an, das der Client nach den Headern HTTP sendet. Der Typ [application/x-www-form-urlencoded] gibt an, dass es sich um ein Dokument handelt, das Formularwerte enthält.

Es gibt zwei Methoden, um Daten an einen Webserver zu übermitteln: GET und POST. Gibt es eine Methode, die besser ist als die andere? Wir haben gesehen, dass, wenn die Werte eines Formulars vom Browser mit der Methode GET gesendet wurden, der Browser in seinem Feld Adresse die angeforderte URL in der Form URL?param1=val1&param2=val2&... anzeigt. Man kann dies als Vorteil oder als Nachteil betrachten:

  • ein Vorteil, wenn man dem Benutzer ermöglichen möchte, diese konfigurierte URL in seine Lesezeichen aufzunehmen;
  • ein Nachteil, wenn man nicht möchte, dass der Benutzer Zugriff auf bestimmte Informationen des Formulars hat, wie beispielsweise versteckte Felder.

Im weiteren Verlauf werden wir in unseren Formularen fast ausschließlich die Methode POST verwenden.

2.6. Conclusion

In diesem Kapitel wurden verschiedene Grundkonzepte der Webentwicklung vorgestellt:

  • den Client-Server-Austausch über das Protokoll HTTP;
  • die Gestaltung eines Dokuments mithilfe der Sprache HTML;
  • die Gestaltung von Eingabeformularen.

Anhand eines Beispiels konnten wir sehen, wie ein Client Informationen an den Webserver senden kann. Wir haben nicht erläutert, wie der Server

  • diese Informationen abrufen kann;
  • diese verarbeiten;
  • dem Kunden eine dynamische Antwort senden, die vom Ergebnis der Verarbeitung abhängt.

Dies ist der Bereich der Webprogrammierung, den wir im nächsten Kapitel mit der Vorstellung der Spring-Technologie MVC behandeln werden.