Inhaltsverzeichnis

  • Webprogrammierung mit vert.x

    • Maven

    • Maven in Netbeans

    • Einfacher Web-Server in vert.x

    • Einfacher Web-Server mit vert.x-Web

    • Mehrere Routen

    • Statischer Router

    • AJAX-Requests

    • Material


Webprogrammierung mit vert.x

Es ist durchaus möglich, Webprogrammierung mit Hilfe eines selbst geschriebenen Http-Servers zu gestalten. Allerdings ist damit ein relativ großer Aufwand verbunden, da sich die HTTP-Standards immer wieder ändern bzw. erweitert werden und somit auch der eigene Server immer wieder angepasst werden müsste.

Somit soll im Folgenden gezeigt werden, wie man mit Hilfe einer externen Bibliothek eine entsprechende Webanwendung umsetzen kann. Dazu soll das Framework vert.x verwendet werden, das neben der Programmierung in Java auch andere Sprachen wie Javascript, Kotlin, Groovy, etc. unterstützt.

Dieses Framework zeichnet sich durch eine rührige Community und eine hervorragende Dokumentation aus und soll hier nur einführend mit einigen Teilfunktionen vorgestellt werden. Ein Studium der Dokumentation ist empfehlenswert.

== Webprogrammierung mit vert.x Es ist durchaus möglich, Webprogrammierung mit Hilfe eines selbst geschriebenen Http-Servers zu gestalten. Allerdings ist damit ein relativ großer Aufwand verbunden, da sich die HTTP-Standards immer wieder ändern bzw. erweitert werden und somit auch der eigene Server immer wieder angepasst werden müsste. Somit soll im Folgenden gezeigt werden, wie man mit Hilfe einer externen Bibliothek eine entsprechende Webanwendung umsetzen kann. Dazu soll das Framework http://vertx.io/[icon:external-link[] vert.x] verwendet werden, das neben der Programmierung in Java auch andere Sprachen wie Javascript, Kotlin, Groovy, etc. unterstützt. Dieses Framework zeichnet sich durch eine rührige Community und eine hervorragende Dokumentation aus und soll hier nur einführend mit einigen Teilfunktionen vorgestellt werden. Ein Studium der Dokumentation ist empfehlenswert.

Maven

=== Maven

Um die vert.x-Bibliothek einzubinden gibt es mehrere Möglichkeiten, z. B. kann man das ganze Paket herunterladen und dann in ein Projekt einbinden.

Allerdings existiert eine noch elegantere Möglichkeit durch den Einsatz von Maven. Dabei handelt es sich unter anderem um eine Art App-Store für Programmierbibliotheken. Man muss nur angeben, welche Library (wird auch im Deutschen im Zusammenhang mit Programmieren als Anglizismus verwendet) man in welcher Version benötigt und Maven kümmert sich darum, dass die zugehörigen Dateien heruntergeladen und an der richtigen Stelle eingebunden werden.

Wir werden im Folgenden nur die notwendigen Schritte zur Einbindung von Libraries behandeln, die Funktionalität von Maven geht aber weit darüber hinaus.

Um die vert.x-Bibliothek einzubinden gibt es mehrere Möglichkeiten, z. B. kann man das ganze Paket herunterladen und dann in ein Projekt einbinden. Allerdings existiert eine noch elegantere Möglichkeit durch den Einsatz von http://maven.apache.org/[icon:external-link[] Maven]. Dabei handelt es sich unter anderem um eine Art App-Store für Programmierbibliotheken. Man muss nur angeben, welche Library (wird auch im Deutschen im Zusammenhang mit Programmieren als Anglizismus verwendet) man in welcher Version benötigt und _Maven_ kümmert sich darum, dass die zugehörigen Dateien heruntergeladen und an der richtigen Stelle eingebunden werden. Wir werden im Folgenden nur die notwendigen Schritte zur Einbindung von Libraries behandeln, die Funktionalität von Maven geht aber weit darüber hinaus.

Maven in Netbeans

=== Maven in Netbeans

Netbeans unterstützt den Einsatz von Maven. So muss man hierzu ein neues Projekt öffnen, diesmal aber nicht Java → Java-Application als Projektart auswählen, sondern Maven → Java-Application.

Im darauf folgenden Dialog muss man neben dem Projekt-Titel auch eine Versionsnummer und eine Group-ID eingeben. Letztere entspricht beispielsweise der Firma, die dieses Projekt verwaltet. Häufig wählt man bei Besitz einer eigenen Domain selbige in umgekehrter Reihenfolge: Hat man eine Homepage unter der Adresse qreator.de wäre eine denkbare Group-ID de.qreator. Diese ID-Festlegung über die Domain gewährleistet, dass sie weltweit einmalig ist.

In der von Netbeans angelegten Struktur befindet sich unter Project Files die Datei pom.xml (Project Object Model). In dieser Datei wird das aktuelle Projekt definiert.

Nach dem Anlegen eines neuen Projekts sieht diese Datei beispielsweise so aus:

Netbeans unterstützt den Einsatz von Maven. So muss man hierzu ein neues Projekt öffnen, diesmal aber *nicht Java -> Java-Application* als Projektart auswählen, sondern *Maven -> Java-Application*. Im darauf folgenden Dialog muss man neben dem Projekt-Titel auch eine Versionsnummer und eine _Group-ID_ eingeben. Letztere entspricht beispielsweise der Firma, die dieses Projekt verwaltet. Häufig wählt man bei Besitz einer eigenen Domain selbige in umgekehrter Reihenfolge: Hat man eine Homepage unter der Adresse qreator.de wäre eine denkbare Group-ID de.qreator. Diese ID-Festlegung über die Domain gewährleistet, dass sie weltweit einmalig ist. In der von Netbeans angelegten Struktur befindet sich unter *Project Files* die Datei *pom.xml* (Project Object Model). In dieser Datei wird das aktuelle Projekt definiert. Nach dem Anlegen eines neuen Projekts sieht diese Datei beispielsweise so aus:

Inhalt der pom.xml:

Inhalt der *pom.xml*:
<?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>de.qreator</groupId>
    <artifactId>Vertx</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
</project>
XML
[source,xml,indent=0] ---- <?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>de.qreator</groupId> <artifactId>Vertx</artifactId> <version>1.0</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> </project> ----

Um vert.x hinzuzufügen muss der folgende Abschnitt vor </project> in die pom.xml eingefügt werden:

Um _vert.x_ hinzuzufügen muss der folgende Abschnitt vor `</project>` in die pom.xml eingefügt werden:
<dependencies>
    <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-core</artifactId>
        <version>3.5.0</version>
    </dependency>
    <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-web</artifactId>
        <version>3.5.0</version>
    </dependency>
</dependencies>
XML
[source,xml, indent=0] ---- <dependencies> <dependency> <groupId>io.vertx</groupId> <artifactId>vertx-core</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>io.vertx</groupId> <artifactId>vertx-web</artifactId> <version>3.5.0</version> </dependency> </dependencies> ----

Damit erhält man insgesamt die Datei

Damit erhält man insgesamt die Datei
<?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>de.qreator</groupId>
    <artifactId>Vertx</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>3.5.0</version>
        </dependency>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-web</artifactId>
            <version>3.5.0</version>
        </dependency>
    </dependencies>
</project>
XML
[source,xml,indent=0] ---- <?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>de.qreator</groupId> <artifactId>Vertx</artifactId> <version>1.0</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>io.vertx</groupId> <artifactId>vertx-core</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>io.vertx</groupId> <artifactId>vertx-web</artifactId> <version>3.5.0</version> </dependency> </dependencies> </project> ----

groupId, artifactId und version sind die Maven-Koordinaten. Damit kann man eine Bibliothek in einem Maven-Repository eindeutig verorten. Ein solches Repository findet man beispielsweise unter http://mvnrepository.com/. Gibt man im Suchfeld vertx ein, so erscheinen vertx-core und vertx-web, die wir für unser Programm benötigen. Nach einem Klick auf die entsprechenden Links kann man die Koordinaten für die gewünschten Versionen der Bibliotheken kopieren und, wie soeben beschrieben, in die pom.xml-Datei einfügen.

_groupId_, _artifactId_ und _version_ sind die *Maven-Koordinaten*. Damit kann man eine Bibliothek in einem *Maven-Repository* eindeutig verorten. Ein solches _Repository_ findet man beispielsweise unter http://mvnrepository.com/. Gibt man im Suchfeld _vertx_ ein, so erscheinen _vertx-core_ und _vertx-web_, die wir für unser Programm benötigen. Nach einem Klick auf die entsprechenden Links kann man die Koordinaten für die gewünschten Versionen der Bibliotheken kopieren und, wie soeben beschrieben, in die pom.xml-Datei einfügen.

Sobald man neue Maven-Koordinaten in die pom.xml aufgenommen hat, sollte ein Projekt aktualisiert werden, so dass die notwendigen Dateien heruntergeladen werden. Dies gelingt in Netbeans über einen Klick mit der rechten Maustaste im Navigator auf den Projektnamen und dann Clean and Build.

Danach sollten alle Bibliotheken von Maven heruntergeladen und im lokalen Repository gespeichert werden.

[WARNING] ==== Sobald man neue Maven-Koordinaten in die pom.xml aufgenommen hat, sollte ein Projekt aktualisiert werden, so dass die notwendigen Dateien heruntergeladen werden. Dies gelingt in Netbeans über einen *Klick mit der rechten Maustaste im Navigator auf den Projektnamen* und dann *Clean and Build*. Danach sollten alle Bibliotheken von Maven heruntergeladen und im lokalen Repository gespeichert werden. ====

Einfacher Web-Server in vert.x

=== Einfacher Web-Server in vert.x

Nun soll in mehreren Schritten gezeigt werden, wie ein einfacher Webserver mit Hilfe von vert.x erstellt werden kann.

Zunächst die Minimalausführung eines Servers:

Nun soll in mehreren Schritten gezeigt werden, wie ein einfacher Webserver mit Hilfe von vert.x erstellt werden kann. Zunächst die Minimalausführung eines Servers:
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;

public class VertxSimple {

    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx(); (1)
        HttpServer server = vertx.createHttpServer(); (2)
        server.requestHandler(request -> { (3)
            HttpServerResponse response = request.response(); (4)
            response.putHeader("content-type", "text/plain"); (5)
            response.end("Hello World!"); (6)
        });
        server.listen(8080); (7)
    }
}
Java
[source,java,indent=0] ---- import io.vertx.core.Vertx; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerResponse; public class VertxSimple { public static void main(String[] args) { Vertx vertx = Vertx.vertx(); // <1> HttpServer server = vertx.createHttpServer(); //<2> server.requestHandler(request -> { //<3> HttpServerResponse response = request.response(); //<4> response.putHeader("content-type", "text/plain"); //<5> response.end("Hello World!"); //<6> }); server.listen(8080); //<7> } } ----
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;

public class VertxSimple {

    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx(); (1)
        HttpServer server = vertx.createHttpServer(); (2)
        server.requestHandler(request -> { (3)
            HttpServerResponse response = request.response(); (4)
            response.putHeader("content-type", "text/plain"); (5)
            response.end("Hello World!"); (6)
        });
        server.listen(8080); (7)
    }
}
1 Erstelle eine neue vert.x-Instanz. Das muss am Anfang des Einsatzes von vert.x immer geschehen.
2 Erstelle einen Http-Server namens server.
3 Der requestHandler ist das Objekt, das Anfragen (requests) entgegennimmt. Ab hier ist die aktuelle Anfrage im Objekt namens request gespeichert.
4 Ein neues Antwort-Objekt (repsonse) wird aus der Anfrage erstellt. Somit ist es die zur Anfrage zugehörige Antwort.
5 Der content-type wird auf normalen Text festgelegt.
6 Hier wird der Text "Hello World!" zurückgeschickt und die Verbindung beendet.
7 Nachdem nun alles festgelegt wurde, kann der Server starten und an Port 8080 auf Anfragen warten.
---- import io.vertx.core.Vertx; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerResponse; public class VertxSimple { public static void main(String[] args) { Vertx vertx = Vertx.vertx(); // <1> HttpServer server = vertx.createHttpServer(); //<2> server.requestHandler(request -> { //<3> HttpServerResponse response = request.response(); //<4> response.putHeader("content-type", "text/plain"); //<5> response.end("Hello World!"); //<6> }); server.listen(8080); //<7> } } ---- <1> Erstelle eine neue vert.x-Instanz. Das muss am Anfang des Einsatzes von vert.x immer geschehen. <2> Erstelle einen Http-Server namens `server`. <3> Der `requestHandler` ist das Objekt, das Anfragen (_requests_) entgegennimmt. Ab hier ist die aktuelle Anfrage im Objekt namens `request` gespeichert. <4> Ein neues Antwort-Objekt (_repsonse_) wird aus der Anfrage erstellt. Somit ist es die zur Anfrage zugehörige Antwort. <5> Der `content-type` wird auf normalen Text festgelegt. <6> Hier wird der Text "Hello World!" zurückgeschickt und die Verbindung beendet. <7> Nachdem nun alles festgelegt wurde, kann der Server starten und an Port 8080 auf Anfragen warten.

Um das Programm zu starten, muss das Projekt erst "zusammengebaut" werden (englisch: build). Also wieder Klick mit der rechten Maustaste im Navigator auf den Projektnamen und dann Clean and Build oder nur Build.

In unserem Fall danach auf die entsprechende Javadatei mit der rechten Maustaste klicken und dann Run File.

Nun sollte das Programm laufen, was man im Browser unter der Adresse http://localhost:8080 oder http://127.0.0.1:8080 überprüfen können sollte.

Um das Programm zu starten, muss das Projekt erst "zusammengebaut" werden (englisch: _build_). Also wieder *Klick mit der rechten Maustaste im Navigator auf den Projektnamen* und dann *Clean and Build* oder nur *Build*. In unserem Fall danach auf die entsprechende Javadatei mit *der rechten Maustaste klicken* und dann *Run File*. Nun sollte das Programm laufen, was man im Browser unter der Adresse http://localhost:8080 oder http://127.0.0.1:8080 überprüfen können sollte.

Einfacher Web-Server mit vert.x-Web

=== Einfacher Web-Server mit vert.x-Web

Speziell zur Programmierung von Webseiten gibt es das Modul vertx-web, das wir durch Maven bereits zur Verfügung haben. Dieses Modul erleichtert die Programmierung von Webanwendungen gewaltig, auch wenn es auf den ersten Blick nicht so aussieht.

Das Programm von gerade eben, nur mit dem vertx-web-Modul:

Speziell zur Programmierung von Webseiten gibt es das Modul `vertx-web`, das wir durch Maven bereits zur Verfügung haben. Dieses Modul erleichtert die Programmierung von Webanwendungen gewaltig, auch wenn es auf den ersten Blick nicht so aussieht. Das Programm von gerade eben, nur mit dem vertx-web-Modul:
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Router;

public class VertxWeb {

    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();
        HttpServer server = vertx.createHttpServer();
        Router router = Router.router(vertx); (1)
        router.route().handler(routingContext -> { (2)
            HttpServerResponse response = routingContext.response();
            response.putHeader("content-type", "text/plain");
            response.end("Hello World from Vert.x-Web!");
        });
        server.requestHandler(router::accept).listen(8080); (3)
    }
}
Java
[source,java,indent=0] ---- import io.vertx.core.Vertx; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.Router; public class VertxWeb { public static void main(String[] args) { Vertx vertx = Vertx.vertx(); HttpServer server = vertx.createHttpServer(); Router router = Router.router(vertx); //<1> router.route().handler(routingContext -> { //<2> HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "text/plain"); response.end("Hello World from Vert.x-Web!"); }); server.requestHandler(router::accept).listen(8080); //<3> } } ----
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Router;

public class VertxWeb {

    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();
        HttpServer server = vertx.createHttpServer();
        Router router = Router.router(vertx); (1)
        router.route().handler(routingContext -> { (2)
            HttpServerResponse response = routingContext.response();
            response.putHeader("content-type", "text/plain");
            response.end("Hello World from Vert.x-Web!");
        });
        server.requestHandler(router::accept).listen(8080); (3)
    }
}
1 Ein neuer Router wird erstellt.
2 Eine neue Route wird hinzugefügt. Da keine weitere Einschränkung angegeben ist, akzeptiert diese Route alle eingehenden Anfragen.
3 Der requestHandler, den wir eben noch selbst geschrieben haben, wird nun durch den Router gestellt: router::accept übergibt eine Anfrage an router.accept(HttpServerRequest request), der diese an den Router weiterleitet, der alles weitere übernimmt.
---- import io.vertx.core.Vertx; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.Router; public class VertxWeb { public static void main(String[] args) { Vertx vertx = Vertx.vertx(); HttpServer server = vertx.createHttpServer(); Router router = Router.router(vertx); //<1> router.route().handler(routingContext -> { //<2> HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "text/plain"); response.end("Hello World from Vert.x-Web!"); }); server.requestHandler(router::accept).listen(8080); //<3> } } ---- <1> Ein neuer *Router* wird erstellt. <2> Eine neue *Route* wird hinzugefügt. Da keine weitere Einschränkung angegeben ist, akzeptiert diese Route alle eingehenden Anfragen. <3> Der _requestHandler_, den wir eben noch selbst geschrieben haben, wird nun durch den Router gestellt: `router::accept` übergibt eine Anfrage an `router.accept(HttpServerRequest request)`, der diese an den Router weiterleitet, der alles weitere übernimmt.

Mehrere Routen

Die Vorteile des Einsatzes eines Routers werden deutlicher, wenn man verschiedene Endpunkte erstellt.

=== Mehrere Routen Die Vorteile des Einsatzes eines Routers werden deutlicher, wenn man verschiedene Endpunkte erstellt.

Möchte man nur Anfragen im Basisverzeichnis an einen Router weiterleiten, so schränkt man den Router so ein, dass er nur Anfragen an das Basisverzeichnis (mit / bezeichnet) akzeptiert.

Heißt die Webadresse www.qreator.de, so werden Anfragen, die unter der Eingabe von www.qreator.de an unser Programm gehen, von diesem Router akzeptiert:

Möchte man nur Anfragen im Basisverzeichnis an einen Router weiterleiten, so schränkt man den Router so ein, dass er nur Anfragen an das Basisverzeichnis (mit / bezeichnet) akzeptiert. Heißt die Webadresse www.qreator.de, so werden Anfragen, die unter der Eingabe von www.qreator.de an unser Programm gehen, von diesem Router akzeptiert:
router.route("/").handler(routingContext -> {
    HttpServerResponse response = routingContext.response();
    response.putHeader("content-type", "text/plain");
    response.end("Gib in der Adresszeile den Pfad \"daten\" oder \"produkte/Werkzeuge/Hammer\" ein.");
});
Java
[source,java,indent=0] ---- router.route("/").handler(routingContext -> { HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "text/plain"); response.end("Gib in der Adresszeile den Pfad \"daten\" oder \"produkte/Werkzeuge/Hammer\" ein."); }); ----

Beispiel: www.qreator.de

*Beispiel:* www.qreator.de

Möchte man nur Anfragen, die an www.qreator.de/daten gehen, akzeptieren, so ist das folgendermaßen möglich:

Möchte man nur Anfragen, die an www.qreator.de/daten gehen, akzeptieren, so ist das folgendermaßen möglich:
router.route("/daten").handler(routingContext -> {
    HttpServerResponse response = routingContext.response();
    response.putHeader("content-type", "text/plain");
    response.end("Hier eine Nachricht vom Unterpfad \"/daten\"!");
});
Java
[source,java,indent=0] ---- router.route("/daten").handler(routingContext -> { HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "text/plain"); response.end("Hier eine Nachricht vom Unterpfad \"/daten\"!"); }); ----

Beispiel: www.qreator.de/daten

*Beispiel:* www.qreator.de/daten

Werte aus der Adresszeile können als Parameter einfach übernommen werden. So wird die Eingabe www.qreator.de/produkte/Werkzeug/Hammer in produktTyp den Wert Werkzeug und in produktID den Wert Hammer speichern:

Werte aus der Adresszeile können als Parameter einfach übernommen werden. So wird die Eingabe www.qreator.de/produkte/Werkzeug/Hammer in `produktTyp` den Wert _Werkzeug_ und in `produktID` den Wert _Hammer_ speichern:
router.route("/produkte/:produktTyp/:produktID").handler(routingContext -> {
    String produktTyp=routingContext.request().getParam("produktTyp");
    String produktID=routingContext.request().getParam("produktID");
    HttpServerResponse response = routingContext.response();
    response.putHeader("content-type", "text/plain");
    response.end("Die ProduktID ist "+produktID+" und der Produkttyp ist "+produktTyp);
});
Java
[source,java,indent=0] ---- router.route("/produkte/:produktTyp/:produktID").handler(routingContext -> { String produktTyp=routingContext.request().getParam("produktTyp"); String produktID=routingContext.request().getParam("produktID"); HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "text/plain"); response.end("Die ProduktID ist "+produktID+" und der Produkttyp ist "+produktTyp); }); ----

Beispiel: www.qreator.de/produkte/Werkzeug/Hammer

*Beispiel:* www.qreator.de/produkte/Werkzeug/Hammer

Insgesamt sieht unser Programm bisher also so aus:

Insgesamt sieht unser Programm bisher also so aus:
Router router = Router.router(vertx);

router.route("/").handler(routingContext -> {
    HttpServerResponse response = routingContext.response();
    response.putHeader("content-type", "text/plain");
    response.end("Gib in der Adresszeile den Pfad \"daten\" oder \"produkte/Werkzeuge/Hammer\" ein.");
});

router.route("/daten").handler(routingContext -> {
    HttpServerResponse response = routingContext.response();
    response.putHeader("content-type", "text/plain");
    response.end("Hier eine Nachricht vom Unterpfad \"/daten\"!");
});

router.route("/produkte/:produktTyp/:produktID").handler(routingContext -> {
    String produktTyp=routingContext.request().getParam("produktTyp");
    String produktID=routingContext.request().getParam("produktID");
    HttpServerResponse response = routingContext.response();
    response.putHeader("content-type", "text/plain");
    response.end("Die ProduktID ist "+produktID+" und der Produkttyp ist "+produktTyp);
});

server.requestHandler(router::accept).listen(8080);
Java
[source,java,indent=0] ---- Router router = Router.router(vertx); router.route("/").handler(routingContext -> { HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "text/plain"); response.end("Gib in der Adresszeile den Pfad \"daten\" oder \"produkte/Werkzeuge/Hammer\" ein."); }); router.route("/daten").handler(routingContext -> { HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "text/plain"); response.end("Hier eine Nachricht vom Unterpfad \"/daten\"!"); }); router.route("/produkte/:produktTyp/:produktID").handler(routingContext -> { String produktTyp=routingContext.request().getParam("produktTyp"); String produktID=routingContext.request().getParam("produktID"); HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "text/plain"); response.end("Die ProduktID ist "+produktID+" und der Produkttyp ist "+produktTyp); }); server.requestHandler(router::accept).listen(8080); ----

Statischer Router

=== Statischer Router

Es ist auch möglich, ganz normale HTML-Dateien inklusive CSS und Javascript an den Browser zurückzuliefern. Dafür gibt es einen besonderen Router, der statische Inhalte zurückliefert, also auf dem Server hinterlegte Dateien.

Diese Route wird folgendermaßen festgelegt:

Es ist auch möglich, ganz normale HTML-Dateien inklusive CSS und Javascript an den Browser zurückzuliefern. Dafür gibt es einen besonderen Router, der _statische Inhalte_ zurückliefert, also auf dem Server hinterlegte Dateien. Diese Route wird folgendermaßen festgelegt:
router.route("/static/*").handler(StaticHandler.create().setDefaultContentEncoding("UTF-8"));
Java
[source,java,indent=0] ---- router.route("/static/*").handler(StaticHandler.create().setDefaultContentEncoding("UTF-8")); ----

Beispiel: www.qreator.de/static/index.html

*Beispiel:* www.qreator.de/static/index.html

Die Einstellung für das Encoding stellt sicher, dass die Kodierung der HTML-Dateien richtig erkannt wird. Dadurch werden Schriftzeichen aus der ganzen Welt im Browser korrekt dargestellt, insofern die zugehörige HTML-Datei in UTF-8 kodiert wurde, was üblicherweise der Fall ist.

Die Einstellung für das _Encoding_ stellt sicher, dass die Kodierung der HTML-Dateien richtig erkannt wird. Dadurch werden Schriftzeichen aus der ganzen Welt im Browser korrekt dargestellt, insofern die zugehörige HTML-Datei in UTF-8 kodiert wurde, was üblicherweise der Fall ist.

Stellt man in vert.x nichts anderes ein, so werden die entsprechenden statischen Dateien im Verzeichnis webroot des Projekts gesucht. Dieser Ordner sollte sich in unserem Projekt unter src/main/resources befinden.

Für die Anfrage www.qreator.de/static/daten/meineDatei.html sollte sich im Projekt die Datei meineDatei.html also unter unter src/main/resources/webroot/daten/meineDatei.html befinden.

[NOTE] ==== Stellt man in vert.x nichts anderes ein, so werden die entsprechenden statischen Dateien im Verzeichnis _webroot_ des Projekts gesucht. Dieser Ordner sollte sich in unserem Projekt unter _src/main/resources_ befinden. Für die Anfrage www.qreator.de/static/daten/meineDatei.html sollte sich im Projekt die Datei _meineDatei.html_ also unter unter _src/main/resources/webroot/daten/meineDatei.html_ befinden. ====

AJAX-Requests

=== AJAX-Requests

In modernen Webseiten ist es üblich, dass, zumeist nach einer Aktion des Benutzers, weitere Daten vom Server angefragt und auf der Webseite dargestellt werden, ohne dies komplett neu laden zu müssen.

Eine Möglichkeit, dies umzusetzen, besteht in der Verwendung von AJAX - Requests.

Dabei schickt die Webseite per Javascript eine Anfrage an den Server, der diese bearbeitet und eine entsprechende Antwort zurücksendet.

Mit Hilfe von jquery könnte eine solche Anfrage mit Javascript folgendermaßen aussehen:

In modernen Webseiten ist es üblich, dass, zumeist nach einer Aktion des Benutzers, weitere Daten vom Server angefragt und auf der Webseite dargestellt werden, ohne dies komplett neu laden zu müssen. Eine Möglichkeit, dies umzusetzen, besteht in der Verwendung von https://de.wikipedia.org/wiki/Ajax_(Programmierung)[icon:external-link[] AJAX] - Requests. Dabei schickt die Webseite per Javascript eine Anfrage an den Server, der diese bearbeitet und eine entsprechende Antwort zurücksendet. Mit Hilfe von jquery könnte eine solche Anfrage mit Javascript folgendermaßen aussehen:

Anfrage durch den Client per Javascript

=== Anfrage durch den Client per Javascript
$("#eingabeKnopf").click(function () { (1)
    $.ajax({url:"../anfrage", data: (2)
            {
                typ: "namenKnopf",
                name: $("#eingabeName").val() (3)
            },
            success: function (data) { (4)
                $("body").append("<div>Daten: " + data.text+"<div>");
            }
        });
});
JavaScript
[source, javascript,indent=0] ---- $("#eingabeKnopf").click(function () { // <1> $.ajax({url:"../anfrage", data: // <2> { typ: "namenKnopf", name: $("#eingabeName").val() //<3> }, success: function (data) { //<4> $("body").append("<div>Daten: " + data.text+"<div>"); } }); }); ----
    $("#eingabeKnopf").click(function () { (1)
        $.ajax({url:"../anfrage", data: (2)
                {
                    typ: "namenKnopf",
                    name: $("#eingabeName").val() (3)
                },
                success: function (data) { (4)
                    $("body").append("<div>Daten: " + data.text+"<div>");
                }
            });
    });
1 Dieser Bereich wird nach dem Klicken eines Knopfes ausgeführt.
2 Die Anfrage geht an den Endpunkt "../anfrage" auf dem Server, also eine Verzeichnisebene höher an den Endpunkt anfrage.
3 Die übertragenen Daten werden in Form eines JSON-Objekts übertragen.
4 Dieser Bereich wird ausgeführt, wenn die Bearbeitung durch den Server erfolgreich war. In der Variablen data befinden sich die vom Server übermittelten Daten.
---- $("#eingabeKnopf").click(function () { // <1> $.ajax({url:"../anfrage", data: // <2> { typ: "namenKnopf", name: $("#eingabeName").val() //<3> }, success: function (data) { //<4> $("body").append("<div>Daten: " + data.text+"<div>"); } }); }); ---- <1> Dieser Bereich wird nach dem Klicken eines Knopfes ausgeführt. <2> Die Anfrage geht an den Endpunkt "../anfrage" auf dem Server, also eine Verzeichnisebene höher an den Endpunkt _anfrage_. <3> Die übertragenen Daten werden in Form eines JSON-Objekts übertragen. <4> Dieser Bereich wird ausgeführt, wenn die Bearbeitung durch den Server erfolgreich war. In der Variablen `data` befinden sich die vom Server übermittelten Daten.

Auf der Serverseite muss diese Anfrage durch den Endpunkt anfrage bearbeitet werden. Dies könnte beispielsweise so aussehen:

Auf der Serverseite muss diese Anfrage durch den Endpunkt _anfrage_ bearbeitet werden. Dies könnte beispielsweise so aussehen:

Bearbeitung der Anfrage auf Server-Seite

=== Bearbeitung der Anfrage auf Server-Seite
router.route("/anfrage").handler(routingContext -> {
    String typ = routingContext.request().getParam("typ");
    String name = routingContext.request().getParam("name");
    HttpServerResponse response = routingContext.response();
    response.putHeader("content-type", "application/json");
    JsonObject jo = new JsonObject();

    if (typ.equals("namenKnopf")) {
        jo.put("typ", "antwort");
        jo.put("text", "Der Text war " + name);
    }
    response.end(Json.encodePrettily(jo));
});
Java
[source,java,indent=0] ---- router.route("/anfrage").handler(routingContext -> { String typ = routingContext.request().getParam("typ"); String name = routingContext.request().getParam("name"); HttpServerResponse response = routingContext.response(); response.putHeader("content-type", "application/json"); JsonObject jo = new JsonObject(); if (typ.equals("namenKnopf")) { jo.put("typ", "antwort"); jo.put("text", "Der Text war " + name); } response.end(Json.encodePrettily(jo)); }); ----

Anfrage: http://127.0.0.1:8080/anfrage?typ=namenKnopf&name=Test

*Anfrage:* http://127.0.0.1:8080/anfrage?typ=namenKnopf&name=Test

Antwort: {typ: "antwort", text: "Der Text war Test"}

*Antwort:* {typ: "antwort", text: "Der Text war Test"}

Das mag an dieser Stelle verwundern: das sieht genauso aus, wie eine normale Parameterauswertung! Tatsächlich sendet das Javascript-Programm eine Anfrage an http://127.0.0.1:8080/anfrage?typ=namenKnopf&name=Test. Die Parameter typ und name erscheinen also tatsächlich in der - nur für den User nicht direkt sichtbaren - Adresszeile.

Da wir hier eine normale HTTP-Verbindung verwenden, können die übermittelten Daten von jedem mitgelesen werden, der die Datenpakete auf dem Weg zum Server weiterleitet.

Deshalb sollten Passwörter niemals über eine unverschlüsselte Verbindung übermittelt werden!

Das mag an dieser Stelle verwundern: das sieht genauso aus, wie eine normale Parameterauswertung! Tatsächlich sendet das Javascript-Programm eine Anfrage an `http://127.0.0.1:8080/anfrage?typ=namenKnopf&name=Test`. Die Parameter `typ` und `name` erscheinen also tatsächlich in der - nur für den User nicht direkt sichtbaren - Adresszeile. [WARNING] ==== Da wir hier eine normale HTTP-Verbindung verwenden, können die übermittelten Daten von jedem mitgelesen werden, der die Datenpakete auf dem Weg zum Server weiterleitet. Deshalb sollten Passwörter niemals über eine unverschlüsselte Verbindung übermittelt werden! ====

Als content-type wird hier nicht, wie bisher text/plain, sondern ´application/json` verwendet. json steht für Javascipt Object Notation .

Um ein solches Objekt zu erstellen, verwenden wir die put-Methoden des JsonObject-Objekts von vert.x. Das encodePrettily erstellt einen JSON-konformen Antwort-String, wie z. B.

Als `content-type` wird hier nicht, wie bisher `text/plain`, sondern ´application/json` verwendet. _json_ steht für https://de.wikipedia.org/wiki/JavaScript_Object_Notation[_Javascipt Object Notation_] . Um ein solches Objekt zu erstellen, verwenden wir die `put`-Methoden des `JsonObject`-Objekts von vert.x. Das `encodePrettily` erstellt einen JSON-konformen Antwort-String, wie z. B.

Wieder beim Client

=== Wieder beim Client
{typ: "antwort", text: "Der Text war Test"}
JavaScript
[source, javascript] ---- {typ: "antwort", text: "Der Text war Test"} ----

Auf den Text kann auf der Client-Seite per data.test zugegriffen werden. Im Erfolgsfall steht dort ja:

Auf den Text kann auf der Client-Seite per `data.test` zugegriffen werden. Im Erfolgsfall steht dort ja:
success: function (data) {
    $("body").append("<div>Daten: " + data.text+"<div>");
}
JavaScript
[source,javascript,indent=0] ---- success: function (data) { $("body").append("<div>Daten: " + data.text+"<div>"); } ----

Material

Die Unterlagen zum Projekt können entweder direkt hier heruntergeladen werden:

=== Material Die Unterlagen zum Projekt können entweder direkt hier heruntergeladen werden:

Dateiname

Vertx.zip

Größe in Bytes

363203

Einfügezeitpunkt

10.12.2017, 23:09:39

  • VertxSimple ist der Webserver ohne Routen.

  • VertxWeb ist der gleiche Webserver, nur mit Routen mit Hilfe des Moduls vertx-web.

  • VertxWebRouter ist ein Beispiel mit mehreren Routen.

  • VertxWebStatic zeigt den Einsatz einer Route für statische Dateien. Die zugehörigen Dateien befinden sich unter webroot im Ressourcenverzeichnis.

  • VertxWebFormular demonstriert den Einsatz von AJAX-Abfragen.

  • vertx.VertxDatabase zeigt die Verwendung einer Datenbank aus vertx heraus.

* _VertxSimple_ ist der Webserver ohne Routen. * _VertxWeb_ ist der gleiche Webserver, nur mit Routen mit Hilfe des Moduls vertx-web. * _VertxWebRouter_ ist ein Beispiel mit mehreren Routen. * _VertxWebStatic_ zeigt den Einsatz einer Route für statische Dateien. Die zugehörigen Dateien befinden sich unter _webroot_ im Ressourcenverzeichnis. * _VertxWebFormular_ demonstriert den Einsatz von AJAX-Abfragen. * _vertx.VertxDatabase_ zeigt die Verwendung einer Datenbank aus vertx heraus.

Wahlweise befinden sich alle notwendigen Dateien auch auf Github unter https://github.com/menzelths/VertxWeb.git.

Wahlweise befinden sich alle notwendigen Dateien auch auf Github unter https://github.com/menzelths/VertxWeb.git.