Vert.x Spring Integration

1. Überblick

In diesem kurzen Artikel werden wir die Integration von Spring in Vert-x diskutieren und das Beste aus beiden Welten nutzen: die leistungsstarke und bekannte Spring-Funktion und die reaktive Einzelereignisschleife von Vert.x.

Weitere Informationen zu Vert.x finden Sie in unserem Einführungsartikel-Link:/vertx

2. Konfiguration

Lassen Sie uns zunächst unsere Abhängigkeiten in Kraft setzen:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-web</artifactId>
    <version>3.4.1</version>
</dependency>

Beachten Sie, dass wir die eingebettete Tomcat-Abhängigkeit von ____spring-boot-starter-web ausgeschlossen haben.

3. Spring Vert.x Anwendung

Jetzt erstellen wir eine Beispielanwendung mit zwei verteilten Verticles.

Der erste Verticle leitet Anforderungen an den Handler weiter, der sie als Nachrichten an die angegebene Adresse sendet. Der andere Verticle hört an einer bestimmten Adresse.

Schauen wir uns diese in Aktion an.

3.1. Sender Verticle

  • ServerVerticle akzeptiert HTTP-Anforderungen und sendet sie als Nachrichten an eine angegebene Adresse. ** Erstellen Sie eine ServerVerticle -Klasse, die das AbstractVerticle erweitert, und überschreibt die start () - Methode, um unseren HTTP-Server zu erstellen:

@Override
public void start() throws Exception {
    super.start();

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

    vertx.createHttpServer()
      .requestHandler(router::accept)
      .listen(config().getInteger("http.port", 8080));
}

Im Server-Anforderungshandler haben wir ein router -Objekt übergeben, das alle eingehenden Anforderungen an den getAllArticlesHandler -Handler umleitet:

private void getAllArticlesHandler(RoutingContext routingContext) {
    vertx.eventBus().<String>send(ArticleRecipientVerticle.GET__ALL__ARTICLES, "",
      result -> {
        if (result.succeeded()) {
            routingContext.response()
              .putHeader("content-type", "application/json")
              .setStatusCode(200)
              .end(result.result()
              .body());
        } else {
            routingContext.response()
              .setStatusCode(500)
              .end();
        }
      });
}

In der Handler-Methode übergeben wir ein Ereignis an den Vert.x-Ereignisbus mit der Ereignis-ID GET ALL ARTICLES. Anschließend verarbeiten wir den Rückruf entsprechend für Erfolgs- und Fehlerszenarien.

Die Nachricht vom Ereignisbus wird vom ArticleRecipientVerticle konsumiert, der im folgenden Abschnitt behandelt wird.

3.2. Empfänger Verticle

  • ArticleRecipientVerticle wartet auf eingehende Nachrichten und injiziert eine Spring-Bean ** Es dient als Treffpunkt für Spring und Vert.x.

Wir injizieren Spring Service Bean in einen Verticle und rufen die entsprechenden Methoden auf:

@Override
public void start() throws Exception {
    super.start();
    vertx.eventBus().<String>consumer(GET__ALL__ARTICLES)
      .handler(getAllArticleService(articleService));
}

Hier ist articleService eine Spring Bean:

@Autowired
private ArticleService articleService;

Dieser Verticle überwacht den Event-Bus an einer Adresse GET ALL ARTICLES. Sobald er eine Nachricht empfängt, delegiert er diese an die getAllArticleService -Handler-Methode:

private Handler<Message<String>> getAllArticleService(ArticleService service) {
    return msg -> vertx.<String> executeBlocking(future -> {
        try {
            future.complete(
            mapper.writeValueAsString(service.getAllArticle()));
        } catch (JsonProcessingException e) {
            future.fail(e);
        }
    }, result -> {
        if (result.succeeded()) {
            msg.reply(result.result());
        } else {
            msg.reply(result.cause().toString());
        }
    });
}

Dadurch wird die erforderliche Dienstoperation ausgeführt und die Nachricht wird mit dem Status beantwortet. Die Nachrichtenantwort wird am ServerVerticle und dem Rückruf result referenziert, wie wir im vorherigen Abschnitt gesehen haben.

4. Serviceklasse

Die Serviceklasse ist eine einfache Implementierung, die Methoden für die Interaktion mit der Repository-Schicht bereitstellt:

@Service
public class ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    public List<Article> getAllArticle() {
        return articleRepository.findAll();
    }
}

ArticleRepository erweitert org.springframework.data.repository.CrudRepository und bietet grundlegende CRUD-Funktionen.

5. Verticles einsetzen

Wir werden die Anwendung bereitstellen, genau wie wir es für eine normale Spring Boot-Anwendung tun würden. Wir müssen eine Vert.X-Instanz erstellen und Verticles darin implementieren, nachdem die Spring-Kontextinitialisierung abgeschlossen ist:

public class VertxSpringApplication {

    @Autowired
    private ServerVerticle serverVerticle;

    @Autowired
    private ArticleRecipientVerticle articleRecipientVerticle;

    public static void main(String[]args) {
        SpringApplication.run(VertxSpringApplication.class, args);
    }

    @PostConstruct
    public void deployVerticle() {
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(serverVerticle);
        vertx.deployVerticle(articleRecipientVerticle);
    }
}

Beachten Sie, dass wir Verticle-Instanzen in die Spring-Anwendungsklasse einfügen. Also müssen wir die Verticle-Klassen kommentieren,

Daher müssen die Verticle-Klassen ServerVerticle und ArticleRecipientVerticle mit @Component. kommentiert werden.

Testen wir die Anwendung:

@Test
public void givenUrl__whenReceivedArticles__thenSuccess() {
    ResponseEntity<String> responseEntity = restTemplate
      .getForEntity("http://localhost:8080/api/baeldung/articles", String.class);

    assertEquals(200, responseEntity.getStatusCodeValue());
}

6. Fazit

In diesem Artikel haben wir erfahren, wie Sie einen RESTful-WebService mit Spring und Vert.x erstellen.

Wie üblich ist das Beispiel verfügbar https://github.com/eugenp/tutorials/tree/master/spring-vertx GitHub.]