Vert.x Spring Integration – Vert.x Spring集成

最后修改: 2017年 6月 21日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick article, we’ll discuss the integration of Spring with Vert-x and leverage the best of both worlds: the powerful and well-known Spring feature, and the reactive single-event loop from Vert.x.

在这篇快速的文章中,我们将讨论Spring与Vert-x的集成,并利用两个世界的优点:强大而著名的Spring功能,以及Vert.x的反应性单事件循环。

To understand more about Vert.x, please refer to our introductory article here.

要进一步了解Vert.x,请参考我们的介绍性文章这里

2. Setup

2.设置

First, let’s get our dependencies in place:

首先,让我们把我们的依赖关系安排好。

<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>

Notice that we’ve excluded the embedded Tomcat dependency from spring-boot-starter-web since we are going to deploy our services using verticles.

注意,我们已经从spring-boot-starter-web s中排除了嵌入式Tomcat的依赖,因为我们将使用verticles部署我们的服务。

You may find the latest dependencies here.

你可以在这里找到最新的依赖项

3. Spring Vert.x Application

3.Spring Vert.x应用程序

Now, we’ll build a sample application with two verticles deployed.

现在,我们将建立一个部署有两个顶点的示例应用程序。

The first Verticle routes requests to the handler that sends them as messages to the given address. The other Verticle listens at a given address.

第一个Verticle将请求路由到处理程序,处理程序将请求作为消息发送到给定地址。另一个Verticle在给定的地址处监听。

Let’s look at these in action.

让我们来看看这些行动。

3.1. Sender Verticle

3.1.发射器垂直面

ServerVerticle accepts HTTP requests and sends them as messages to a designated address. Let’s create a ServerVerticle class extending the AbstractVerticle, and override the start() method to create our HTTP Server:

ServerVerticle接受HTTP请求并将其作为消息发送到指定的地址。让我们创建一个ServerVerticle类来扩展AbstractVerticle,并重写start()方法来创建我们的HTTP服务器。

@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));
}

In the server request handler, we passed a router object, which redirects any incoming request to the getAllArticlesHandler handler:

在服务器请求处理程序中,我们传递了一个router对象,它将任何进入的请求重定向到getAllArticleHandler处理程序。

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 the handler method, we’re passing an event to the Vert.x Event bus, with an event id as GET_ALL_ARTICLES. Then we process the callback accordingly for success and error scenarios.

在处理方法中,我们将一个事件传递给Vert.x事件总线,事件ID为GET_ALL_ARTICLES。然后我们针对成功和错误的情况对回调进行相应的处理。

The message from the event bus will be consumed by the ArticleRecipientVerticle, discussed in the following section.

来自事件总线的消息将被ArticleRecipientVerticle消费,在下一节讨论。

3.2. Recipient Verticle

3.2.收件人垂直线

ArticleRecipientVerticle listens for incoming messages and injects a Spring bean. It acts as the rendezvous point for Spring and Vert.x.

ArticleRecipientVerticle监听传入的消息并注入一个Spring Bean。它充当了Spring和Vert.x.的汇合点。

We’ll inject Spring service bean into a Verticle and invoke respective methods:

我们将把Spring服务Bean注入到Verticle中并调用各自的方法。

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

Here, articleService is an injected Spring bean:

这里,articleService是一个注入的Spring Bean。

@Autowired
private ArticleService articleService;

This Verticle will keep listening to the event bus on an address GET_ALL_ARTICLES. Once it receives a message, it delegates it to the getAllArticleService handler method:

这个Verticle将在一个地址GET_ALL_ARTICLES上持续监听事件总线。一旦它收到一个消息,它就把它委托给getAllArticleServicehandler方法。

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());
        }
    });
}

This performs the required service operation and replies to the message with the status. The message reply is being referenced at the ServerVerticle and the callback result as we saw in the earlier section.

这就执行了所需的服务操作,并将状态回复给消息。消息回复在ServerVerticle和回调result被引用,正如我们在前面的章节中看到的那样。

4. Service Class

4.服务等级

The service class is a simple implementation, providing methods to interact with the repository layer:

服务类是一个简单的实现,提供与资源库层交互的方法。

@Service
public class ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

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

The ArticleRepository extends, org.springframework.data.repository.CrudRepository and provides basic CRUD functionalities.

ArticleRepository扩展了org.springframework.data.repository.CrudRepository并提供基本的CRUD功能。

5. Deploying Verticles

5.部署轮子

We will be deploying the application, just the way we would do for a regular Spring Boot application. We have to create a Vert.X instance, and deploy verticles in it, after the Spring context initialization in completed:

我们将部署应用程序,就像部署普通的Spring Boot应用程序那样。我们必须创建一个Vert.X实例,并在Spring上下文初始化完成后,在其中部署verticles。

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);
    }
}

Notice that, we are injecting verticle instances into the Spring application class. So, we will have to annotate the Verticle classes,

请注意,我们是在将Verticle实例注入Spring应用类中。因此,我们必须对Verticle类进行注解。

So, we will have to annotate the Verticle classes, ServerVerticle and ArticleRecipientVerticle with @Component.

因此,我们必须用@Component.来注释Verticle类,ServerVerticleArticleRecipientVerticle

Let’s test the application:

让我们测试一下这个应用程序。

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

6. Conclusion

6.结论

In this article, we learned about how to build a RESTful WebService using Spring and Vert.x.

在这篇文章中,我们了解了如何使用Spring和Vert.x构建一个RESTful WebService。

As usual, the example is available over on GitHub.

像往常一样,这个例子可以在GitHub上找到