1. Обзор
В этой быстрой статье мы обсудим интеграцию Spring с Vert-x и используем лучшее из обоих миров: мощную и хорошо известную функцию Spring и реактивный цикл с одним событием из Vert.x.
Чтобы узнать больше о Vert.x, пожалуйста, обратитесь к нашей ссылке на вступительную статью:/vertx[здесь].
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 s _ , поскольку мы собираемся развернуть наши сервисы с использованием вершин.
Вы можете найти последние зависимости here .
3. Приложение Spring Vert.x
Теперь мы создадим пример приложения с двумя развернутыми вершинами.
Первый Vertical направляет запросы обработчику, который отправляет их в виде сообщений на заданный адрес. Другая Вертикаль слушает по заданному адресу.
Давайте посмотрим на них в действии.
3.1. Отправитель Вертикаль
-
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));
}
В обработчике запросов сервера мы передали объект router , который перенаправляет любой входящий запрос обработчику 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. Получатель Вертикаль
-
ArticleRecipientVerticle прослушивает входящие сообщения и внедряет Spring bean ** . Он действует как место встречи для 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;
Эта статья будет продолжать прослушивать шину событий по адресу 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 и обратный вызов result , как мы видели в предыдущем разделе.
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);
}
}
Обратите внимание, что мы внедряем экземпляры вертикулов в класс приложения Spring. Итак, нам придется аннотировать классы Verticle,
Таким образом, нам придется аннотировать вертикальные классы ServerVerticle и ArticleRecipientVerticle с помощью @Component.
Давайте протестируем приложение:
@Test
public void givenUrl__whenReceivedArticles__thenSuccess() {
ResponseEntity<String> responseEntity = restTemplate
.getForEntity("http://localhost:8080/api/baeldung/articles", String.class);
assertEquals(200, responseEntity.getStatusCodeValue());
}
6. Заключение
В этой статье мы узнали о том, как создать RESTful WebService с использованием Spring и Vert.x.
Как обычно, пример доступен over on GitHub.