Перейти к основному содержимому

Интеграция Vert.x Spring

· 4 мин. чтения

1. Обзор

В этой быстрой статье мы обсудим интеграцию Spring с Vert-x и воспользуемся лучшим из обоих миров: мощной и хорошо известной функцией Spring и реактивным циклом одного события из Vert.x.

Чтобы узнать больше о Vert.x, обратитесь к нашей вводной статье здесь .

2. Настройка

Во-первых, давайте установим наши зависимости:

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

Обратите внимание, что мы исключили встроенную зависимость Tomcat из spring-boot-starter-web , так как мы собираемся развертывать наши службы с использованием вертикул.

Вы можете найти последние зависимости здесь .

3. Приложение Spring Vert.x

Теперь мы создадим пример приложения с развернутыми двумя вершинами.

Первая Verticle направляет запросы обработчику, который отправляет их в виде сообщений на указанный адрес. Другая Verticle слушает по заданному адресу.

Давайте посмотрим на них в действии.

3.1. Вертикаль отправителя

ServerVerticle принимает HTTP-запросы и отправляет их в виде сообщений на указанный адрес. Давайте создадим класс ServerVerticle , расширяющий AbstractVerticle, и переопределим метод start() для создания нашего HTTP-сервера:

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

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

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

В обработчик запросов к серверу мы передали объект маршрутизатора , который перенаправляет любой входящий запрос в обработчик getAllArticlesHandler :

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

В методе обработчика мы передаем событие на шину событий Vert.x с идентификатором события GET_ALL_ARTICLES. Затем мы обрабатываем обратный вызов соответственно для сценариев успеха и ошибок.

Сообщение из шины событий будет использовано ArticleRecipientVerticle , что обсуждается в следующем разделе.

3.2. Получатель Verticle

ArticleRecipientVerticle прослушивает входящие сообщения и внедряет bean-компонент Spring . Он действует как точка встречи для Spring и Vert.x.

Мы внедрим сервисный компонент Spring в Verticle и вызовем соответствующие методы:

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

Здесь articleService — это внедренный компонент Spring:

@Autowired
private ArticleService articleService;

Эта Verticle будет продолжать прослушивать шину событий по адресу GET_ALL_ARTICLES. Получив сообщение, он делегирует его методу-обработчику getAllArticleService :

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

Это выполняет требуемую операцию службы и отвечает на сообщение со статусом. Ответ на сообщение ссылается на ServerVerticle и на результат обратного вызова , как мы видели в предыдущем разделе.

4. Класс обслуживания

Сервисный класс представляет собой простую реализацию, предоставляющую методы для взаимодействия со слоем репозитория:

@Service
public class ArticleService {

@Autowired
private ArticleRepository articleRepository;

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

ArticleRepository расширяется, org.springframework.data.repository.CrudRepository и предоставляет базовые функции CRUD.

5. Развертывание вершин

Мы будем развертывать приложение так же, как и для обычного приложения Spring Boot. Мы должны создать экземпляр Vert.X и развернуть в нем вершины после завершения инициализации контекста Spring:

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

Обратите внимание, что мы внедряем экземпляры verticle в класс приложения Spring. Итак, нам придется аннотировать классы Verticle,

Итак, нам придется аннотировать классы Verticle, ServerVerticle и ArticleRecipientVerticle с помощью @Component.

Протестируем приложение:

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

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

6. Заключение

В этой статье мы узнали о том, как создать RESTful WebService с использованием Spring и Vert.x.

Как обычно, пример доступен на GitHub.