Einführung in Vert.x

1. Überblick

In diesem Artikel werden wir Vert.x diskutieren, seine Kernkonzepte behandeln und einen einfachen RESTfull-Webdienst damit erstellen.

Wir werden zunächst die Grundlagen des Toolkits erläutern, langsam zu einem HTTP-Server vorrücken und dann den RESTfull-Dienst erstellen.

2. Über Vert.x

  • Vert.x ist ein Open Source, reaktives und mehrsprachiges Softwareentwicklungs-Toolkit ** von den Entwicklern von Eclipse.

Reaktive Programmierung ist ein Programmierparadigma, das mit asynchronen Streams verknüpft ist, die auf Änderungen oder Ereignisse reagieren.

In ähnlicher Weise verwendet Vert.x einen Ereignisbus, um mit verschiedenen Teilen der Anwendung zu kommunizieren und Ereignisse asynchron an Handler zu übergeben, wenn diese verfügbar sind.

  • Wir nennen es Polyglot, da es mehrere JVM- und Nicht-JVM-Sprachen wie Java, Groovy, Ruby, Python und JavaScript unterstützt. **

3. Konfiguration

Um Vert.x verwenden zu können, müssen Sie die Maven-Abhängigkeit hinzufügen:

<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-core</artifactId>
    <version>3.4.1</version>
</dependency>

Die neueste Version der Abhängigkeit finden Sie unter here .

3. Verticles

Verticles sind Code-Teile, die von der Vert.x-Engine ausgeführt werden. Das Toolkit enthält viele abstrakte Verticle-Klassen, die beliebig erweitert und implementiert werden können.

Da sie mehrsprachig sind, können Verticles in jeder der unterstützten Sprachen geschrieben werden. Eine Anwendung würde sich normalerweise aus mehreren Knoten zusammensetzen, die in derselben Vert.x-Instanz laufen und über Ereignisse über den Ereignisbus miteinander kommunizieren.

Um einen Knoten in JAVA zu erstellen, muss die Klasse die Schnittstelle io.vertx.core.Verticle oder eine ihrer Unterklassen implementieren.

4. Event Bus

Es ist das Nervensystem einer Vert.x-Anwendung.

Da die Vertices reaktiv sind, bleiben sie still, bis sie eine Nachricht oder ein Ereignis erhalten. Verticles kommunizieren miteinander über den Event-Bus. Die Nachricht kann alles von einer Zeichenfolge bis zu einem komplexen Objekt sein.

Die Nachrichtenverarbeitung ist im Idealfall asynchron, Nachrichten werden in den Ereignisbus aufgenommen und die Steuerung wird an den Sender zurückgegeben. Später wird es an den Hörverteiler entfernt. Die Antwort wird mit den Methoden Future und callback gesendet.

5. Einfache Vert.x-Anwendung

  • Erstellen Sie eine einfache Anwendung mit einer Vertikalen und stellen Sie sie mithilfe einer Vertx-Instanz bereit. ** Um unser Verticle zu erstellen, erweitern wir das

Um unseren Knoten zu erstellen, erweitern wir die io.vertx.core.AbstractVerticle -Klasse und überschreiben die start () -Methode:

public class HelloVerticle extends AbstractVerticle {

    @Override
    public void start(Future<Void> future) {
        LOGGER.info("Welcome to Vertx");
    }
}

Die start () - Methode wird von der vertx -Instanz aufgerufen, wenn der Verticle bereitgestellt wird. Die Methode verwendet io.vertx.core.Future als Parameter, mit dem der Status einer asynchronen Bereitstellung des Vertikels ermittelt werden kann.

Lassen Sie uns nun den Verticle einsetzen:

public static void main(String[]args) {
    Vertx vertx = Vertx.vertx();
    vertx.deployVerticle(new HelloVerticle());
}

In ähnlicher Weise können wir die stop () - Methode von der AbstractVerticle -Klasse überschreiben, die beim Herunterfahren des Vertikels aufgerufen wird:

@Override
public void stop() {
    LOGGER.info("Shutting down application");
}

6. HTTP-Server

Lassen Sie uns nun einen HTTP-Server mit einem Verticle hochfahren:

@Override
public void start(Future<Void> future) {
    vertx.createHttpServer()
      .requestHandler(r -> r.response().end("Welcome to Vert.x Intro");
      })
      .listen(config().getInteger("http.port", 9090),
        result -> {
          if (result.succeeded()) {
              future.complete();
          } else {
              future.fail(result.cause());
          }
      });
}

Wir haben die Methode start () zum Erstellen eines HTTP-Servers überschrieben und einen Anforderungshandler daran angehängt. Die Methode requestHandler () wird jedes Mal aufgerufen, wenn der Server eine Anforderung erhält.

Schließlich wird der Server an einen Port gebunden, und ein AsyncResult <HttpServer> -Handler wird an die Methode listen () übergeben, unabhängig davon, ob die Verbindung oder der Serverstart mit future.complete () oder future.fail ( ) bei eventuellen Fehlern.

Beachten Sie, dass die config.getInteger () -Methode den Wert für die HTTP-Port-Konfiguration liest, die aus einer externen conf.json -Datei geladen wird.

Lassen Sie uns unseren Server testen:

@Test
public void whenReceivedResponse__thenSuccess(TestContext testContext) {
    Async async = testContext.async();

    vertx.createHttpClient()
      .getNow(port, "localhost", "/", response -> {
        response.handler(responseBody -> {
          testContext.assertTrue(responseBody.toString().contains("Hello"));
          async.complete();
        });
      });
}

Für den Test verwenden wir vertx-unit zusammen mit JUnit:

<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-unit</artifactId>
    <version>3.4.1</version>
    <scope>test</scope>
</dependency>

Wir können die neueste Version hier erhalten.

Der Verticle wird in einer vertx -Instanz in der setup () -Methode des Komponententests bereitgestellt:

@Before
public void setup(TestContext testContext) {
    vertx = Vertx.vertx();

    vertx.deployVerticle(SimpleServerVerticle.class.getName(),
      testContext.asyncAssertSuccess());
}

In ähnlicher Weise wird die vertx -Instanz in der @ AfterClass tearDown () -Methode geschlossen:

@After
public void tearDown(TestContext testContext) {
    vertx.close(testContext.asyncAssertSuccess());
}

Beachten Sie, dass die @ BeforeClass-Methode setup () ein TestContext -Argument benötigt. Dies hilft beim Steuern und Testen des asynchronen Verhaltens des Tests. Zum Beispiel ist die Verticle-Bereitstellung asynchron, sodass wir nichts testen können, es sei denn, es wurde ordnungsgemäß bereitgestellt.

Die deployVerticle () -Methode testContext.asyncAssertSuccess () verfügt über einen zweiten Parameter . _T . Dieser wird verwendet, um zu ermitteln, ob der Server ordnungsgemäß implementiert ist oder Fehler aufgetreten sind. Es wartet auf den Aufruf von future.complete () oder future.fail () _ in der Server-Ecke. Im Fehlerfall wird der Test nicht bestanden.

7. RESTful WebService

Wir haben einen HTTP-Server erstellt. Jetzt können Sie einen REST-vollständigen WebService hosten. Dazu benötigen wir ein weiteres Vert.x-Modul mit dem Namen vertx-web . Dies bietet viele zusätzliche Funktionen für die Webentwicklung zusätzlich zu vertx-core .

Fügen wir die Abhängigkeit zu unserer pom.xml hinzu:

<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-web</artifactId>
    <version>3.4.1</version>
</dependency>

Die neueste Version finden Sie unter hier .

7.1. Router und Routes

Erstellen wir einen router für unseren WebService. Dieser Router nimmt eine einfache Route der GET-Methode und der Handler-Methode getArtilces () :

Router router = Router.router(vertx);
router.get("/api/baeldung/articles/article/:id")
  .handler(this::getArticles);

Die Methode getArticle () ist eine einfache Methode, die ein neues Article -Objekt zurückgibt:

private void getArticles(RoutingContext routingContext) {
    String articleId = routingContext.request()
      .getParam("id");
    Article article = new Article(articleId,
      "This is an intro to vertx", "baeldung", "01-02-2017", 1578);

    routingContext.response()
      .putHeader("content-type", "application/json")
      .setStatusCode(200)
      .end(Json.encodePrettily(article));
}

Ein Router, wenn er eine Anfrage erhält, sucht nach der passenden Route und leitet die Anfrage weiter. Dem routes ist eine Handlermethode zugeordnet, mit der die Anforderung summiert wird.

In unserem Fall ruft der Handler die Methode getArticle () auf. Es empfängt das routingContext -Objekt als Argument. Liefert den Pfadparameter id, und erstellt damit ein Article -Objekt.

Im letzten Teil der Methode rufen wir die response () -Methode für das routingContext -Objekt auf und setzen die Header, setzen den HTTP-Antwortcode und beenden die Antwort mit dem JSON-codierten article -Objekt.

7.2. Router zum Server hinzufügen

Nun fügen wir den router, , der im vorherigen Abschnitt erstellt wurde, zum HTTP-Server hinzu:

vertx.createHttpServer()
  .requestHandler(router::accept)
  .listen(config().getInteger("http.port", 8080),
    result -> {
      if (result.succeeded()) {
          future.complete();
      } else {
          future.fail(result.cause());
      }
});
Beachten Sie, dass wir dem Server __requestHandler (router

accept) hinzugefügt haben. Dies weist den Server an, den accept () des router__-Objekts aufzurufen, wenn eine Anforderung empfangen wird.

Lassen Sie uns nun unseren WebService testen:

@Test
public void givenId__whenReceivedArticle__thenSuccess(TestContext testContext) {
    Async async = testContext.async();

    vertx.createHttpClient()
      .getNow(8080, "localhost", "/api/baeldung/articles/article/12345",
        response -> {
            response.handler(responseBody -> {
            testContext.assertTrue(
              responseBody.toString().contains("\"id\" : \"12345\""));
            async.complete();
        });
      });
}

8. Vert.x-Anwendung für Verpackungen

Um die Anwendung als ein implementierbares Java-Archiv (.jar) zu packen, verwenden Sie das Plugin Maven Shade und die Konfigurationen im execution -Tag

<configuration>
    <transformers>
        <transformer
          implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <manifestEntries>
                <Main-Class>io.vertx.core.Starter</Main-Class>
                <Main-Verticle>com.baeldung.SimpleServerVerticle</Main-Verticle>
            </manifestEntries>
        </transformer>
    </transformers>
    <artifactSet/>
    <outputFile>
        ${project.build.directory}/${project.artifactId}-${project.version}-app.jar
    </outputFile>
</configuration>

In manifestEntries gibt Main-Verticle den Startpunkt der Anwendung an und die Main-Class ist eine Vert.x-Klasse, die die vertx -Instanz erstellt und das Main-Verticle. bereitstellt.

9. Fazit

In diesem einleitenden Artikel haben wir das Vert.x-Toolkit und seine grundlegenden Konzepte erläutert. Ich habe gesehen, wie man einen HTTP-Server mit Vert.x und einem RESTFull-WebService erstellt und mit vertx-unit getestet

Schließlich verpackte die Anwendung als ausführbare Dose.

Die vollständige Implementierung der Codeausschnitte ist verfügbar unter https://github.com/eugenp/tutorials/tree/master/vertx