Зарегистрируйтесь, чтобы продолжить обучение

Многопоточность в Spring Java: Продвинутое использование

В этом уроке мы познакомимся с Spring WebFlux — фреймворком на платформе Spring, предназначенным для создания реактивных веб-приложений. Он позволяет обрабатывать запросы асинхронно и в неблокирующем режиме, что делает приложение более эффективным, так как оно может одновременно обрабатывать множество запросов, не дожидаясь завершения каждого из них.

Реактивный подход означает, что система может выполнять несколько задач одновременно, не ожидая завершения одной задачи перед началом другой. Например, в традиционном синхронном приложении, когда вы делаете запрос к базе данных, оно будет ждать ответа, прежде чем продолжить выполнение. В отличие от этого, реактивное приложение отправляет запрос и сразу же продолжает выполнение, обрабатывая ответ, когда он поступит, без блокировки основного потока.

В ходе урока мы разработаем простое реактивное приложение, которое продемонстрирует основные принципы работы с асинхронными операциями и реактивными потоками данных с использованием Spring WebFlux.

Классы для работы с реактивными потоками данных

В Spring WebFlux мы работаем с реактивными потоками данных, которые позволяют обрабатывать запросы и операции в асинхронном режиме, используя типы Mono и Flux для представления результатов

Mono - это класс, который представляет собой поток данных, который может содержать не более одного элемента. Он используется, когда нужно обработать один результат или ошибку.

Flux - это класс, который представляет собой поток данных, который может содержать любое количество элементов. Он используется, когда нужно обработать несколько результатов или ошибок.

Модель

В реактивных приложениях на основе Spring WebFlux модели не используют традиционные аннотации из пакета jakarta.persistence, так как они предназначены для синхронных ORM-фреймворков. Вместо этого для работы с асинхронными базами данных применяются другие подходы, такие как Spring Data R2DBC, которые лучше соответствуют неблокирующей природе реактивного программирования

import org.springframework.data.annotation.Id;
import org.springframework.data.relationgl.core.mapping.Table;

@Table
public class Car {

    // Идентификатор будет генерироваться автоматически
    @Id
    private long id;

    private String model;

    private String color;
}

Репозиторий

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

Чтобы реализовать асинхронное взаимодействие с базой данных, мы используем репозитории, которые наследуются от ReactiveCrudRepository. ReactiveCrudRepository — это интерфейс, который предоставляет асинхронные и неблокирующие операции для работы с базами данных в реактивных приложениях, что позволяет выполнять операции, такие как создание, чтение, обновление и удаление сущностей, без блокировки потоков.

@Repository
// Реализуем интерфейс ReactiveCrudRepository
public interface CarRepository extends ReactiveCrudRepository<Car, Integer> {
    // Все необходимые методы уже содержатся в интерфейсе ReactiveCrudRepository
}

Репозиторий ReactiveCrudRepository работает с реактивными типами Mono<T> и Flux<T>

Сервис

Сервис в данном примере представляет собой слой бизнес-логики, который использует репозиторий для взаимодействия с базой данных и возвращает реактивные типы Flux и Mono, что позволяет обрабатывать данные в асинхронном режиме

@Service
public class CarService {
    // Сервис использует репозиторий
    @Autowired
    CarRepository carRepository;

    // Из методов сервиса возвращаем типы Reactor Flux<T> или Mono<T>
    public Flux<Car> findAll() {
        return carRepository.findAll();
    }

    public Mono<Car> create(Car car) {
        return carRepository.save(car);
    }

    public Mono<Car> findById(int carId) {
        return carRepository.findById(carId);
    }
}

Контроллер

Контроллер, в свою очередь, использует методы сервиса для обработки HTTP-запросов и возвращает реактивные типы

@RestController
@RequestMapping("/cars")
public class CarController {
    // В контроллере используем методы сервиса
    @Autowired
    private CarService carService;

    @GetMapping(path = "")
    public Flux<Car> getCars() {
        return carService.findAll();
    }

    @GetMapping(path = "/{id}")
    public Mono<Car> getCar(@PathVariable int id) {
        return carService.findById(id);
    }

    @PostMapping(path = "")
    public Mono<Car> createCar(@RequestBody Car car) {
        return carService.create(car);
    }
}

Сервер Netty

В качестве сервера по умолчанию проект Spring WebFlux использует Netty. Netty - это асинхронный сервер, который позволяет обрабатывать несколько запросов одновременно, не блокируя основной поток выполнения.

В отличие от Tomcat, который создает большое количество потоков, блокирущихся в ожидания ответа от базы данных или других ресурсов, Netty работает на основе неблокирующего ввода/вывода и использует Event Loop для обработки событий. Event Loop работает как бесконечный цикл, который постоянно мониторит соединения и обрабатывает события, такие как приход новых данных или закрытие соединения. Когда событие происходит, Event Loop вызывает соответствующий обработчик, который обрабатывает событие и выполняет необходимые действия.


Дополнительные материалы

  1. Документация Spring WebFlux
  2. Функциональные эндпоинты в Spring WebFlux

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff