Рубрики
Без рубрики

Реактивное программирование с использованием Java Spring, R2DBC и MariaDB

Независимо от того, активно ли вы развивались на одном из языков JVM или нет, скорее всего, вы это сделали… Помечен как r2 odbc, mariadb, java, spring.

Независимо от того, активно ли вы развивались на одном из языков JVM или нет, вы, вероятно, по крайней мере слышали о концепции реактивного программирования к настоящему времени. Если нет, я, безусловно, призываю вас провести небольшое исследование всей идеи декларативного программирования с использованием потоков данных .

В этой статье мы рассмотрим (очень) краткую предысторию не только того, что такое Реактивное подключение к реляционным базам данных (R2DBC) , но и того, почему оно существует, а затем погрузимся в код, чтобы увидеть, как новый MariaDB Разъем R2 ODBC может использоваться для создания полностью реактивного, Приложения Java Spring (загрузка и данные)!

Мы рассмотрим процесс создания простого приложения todo, но если вы предпочитаете перейти непосредственно к коду, вы можете найти его здесь .

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

Для начала важно знать (или вспомнить, в зависимости от ваших текущих обстоятельств), что реактивное программирование сводится к идее использования асинхронных потоков данных.

Поток данных – это, по сути, то, на что это похоже, поток данных. Но что это на самом деле означает?

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

Хотя мы, безусловно, могли бы еще глубже погрузиться во множество вариантов использования потоков данных, это немного выходит за рамки этого пошагового руководства (я обещаю, что все это завершится пошаговым описанием). Вместо этого мы сосредоточимся на том, что структура потока данных – это то, что воплощает концепцию реактивных потоков в жизнь.

Хорошо, хорошо, я знаю, о чем ты думаешь; “Черт возьми, этот чувак употребляет слово “реактивный” больше, чем житель Среднего Запада, бродящий в толпе, используя это слово ‘ |/открыть ‘”. Потерпи меня, во всем этом безумии есть смысл. Я обещаю!

Реактивные потоки – это просто стандарт для асинхронной обработки потоков, использующий идею неблокирующего обратного давления.

“Серьезно, Роб! Обратное давление?! Ты просто сейчас все выдумываешь? Я думаю, что у меня возвращается давление, просто читая эту чушь”.

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

Противодавление – важная концепция, потому что это основа, на которой основана инициатива “реактивные потоки”.

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

TL;DR – реактивные потоки создают стандартный подход.

Следующая (очень высокоуровневая) диаграмма показывает взаимодействия (для управления, да, вы уже догадались, потоками данных!) между издателями и подписчиками.

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

Для наших целей нас интересует сама спецификация, в частности, как она используется при подключении к реактивной реляционной базе данных (R2DBC).

R2DBC начинался как эксперимент и доказательство концепции, позволяющей интегрировать базы данных SQL в системы, использующие модели реактивного программирования. Это необходимо из-за ограничений |/API подключения к базе данных Java (JDBC) .

В соответствии с http://r2dbc.io :

“R2DBC определяет интерфейс поставщика услуг (SPI) это предназначено для реализации поставщиками драйверов и использования клиентскими библиотеками. Используя SPI R2DBC, приложения, написанные на языке программирования JVM, могут запускать операторы SQL и получать результаты с использованием базового источника данных.”

И если вы еще не догадались, SPI R2DBC основан на Реактивных потоках и использует концепции издателей и подписчиков для обеспечения неблокирующего доступа к данным с учетом обратного давления. Ах, да, мы прошли полный круг!

TL;DR – R2DBC – это новая спецификация подключения, которая поддерживает реактивные взаимодействия вплоть до уровня базы данных.

Корпорация MariaDB недавно выпустила свою реализацию соединителя R2DBC. Он полностью с открытым исходным кодом и соответствует спецификациям R2DBC 0.8.1 .

Вот где ты торжественно хрустишь костяшками пальцев. Пришло время кодировать!

Прежде чем перейти к коду, вам нужно убедиться, что на вашем компьютере есть несколько вещей:

Давайте предположим, что вы либо никогда не использовали MariaDB, либо в настоящее время на вашем компьютере не запущен экземпляр. Нет проблем! Запуск и запуск MariaDB с использованием контейнера Docker занимает всего пару минут. Если у вас уже запущен экземпляр, не стесняйтесь переходить к той части, где мы создаем новую схему.

Чтобы извлечь изображение сервера MariaDB и развернуть контейнер, просто откройте окно терминала и выполните следующее:

$ docker run -p 3306:3306 -d --name mariadb -eMARIADB_ROOT_PASSWORD=Password123! mariadb/server:10.4 

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

Существует множество SQL-клиентов, доступных в дикой природе. Для простоты я решил продемонстрировать, как использовать официальный клиент MariaDB, но, конечно, не стесняйтесь использовать любой клиент, который вы предпочитаете.

Подключитесь к вашему экземпляру MariaDB, выполнив следующую команду в окне терминала.

Вы должны увидеть что-то вроде следующего, что означает, что вы успешно подключились к экземпляру MariaDB!

Затем создайте новую базу данных для нашего приложения TODO.

CREATE DATABASE todo;

Затем создайте новую таблицу для хранения наших задач.

CREATE TABLE todo.tasks (id int, description varchar(200), completed boolean);

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

Создайте проект Maven

Начните с перехода к https://start.spring.io , который позволит вам создать новый Весна -основанный Maven проект.

Для этого проекта вы можете ввести следующие критерии.

Затем добавьте следующие зависимости:

Наконец, нажмите кнопку “СОЗДАТЬ”, чтобы создать и загрузить проект (содержащийся в zip-файле) в нужное место на вашем компьютере.

Добавьте разъем ODBC MariaDB R2

Перейдите в папку, в которую вы загрузили новый проект Maven (zip-файл), и разархивируйте его. Затем используйте редактор кода, чтобы открыть проект, и откройте pom.xml .

Добавьте новую зависимость для соединителя ODBC R2 от MariaDB в коллекцию зависимостей.


    org.mariadb
    r2dbc-mariadb
    0.8.2-alpha2

Соединитель ODBC MariaDB R2 недоступен в списке зависимостей Spring, поскольку в настоящее время он все еще находится в альфа-фазе разработки.

Подготовка к интеграции данных

Теперь, когда вы создали проект, содержащий все необходимые вам зависимости, пришло время приступить к настоящему кодированию. Как правило, мне нравится начинать с создания классов сущностей (или моделей).

Перейдите в/src/main/java/com/пример/задачи , создайте новую папку под названием “модели” и создайте в ней новый файл с именем “Task.java “.

Открыть “Task.java ” и добавьте следующий код.

package com.mariadb.todo.models;

import org.springframework.data.relational.core.mapping.Table;

import lombok.Data;

// Lombok annotation that eliminates getter/setter boilerplate code
@Data 
// Annotation that will point to table "tasks" (pluralized in the database)
@Table("tasks")
public class Task {
    @Id private Integer id;
    private String description;
    private Boolean completed;
}

Затем создайте новую папку под названием “репозитории” в/src/main/java/com/mariadb/to do и создайте в ней новый файл с именем “TasksRepository.java “

Открыть “TasksRepository.java ” и добавьте следующий код.

package com.mariadb.todo.repositories;

import com.mariadb.todo.models.Task;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;

// Registered as a Spring Repository (Component)
// Repository = a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects
public interface TasksRepository extends ReactiveCrudRepository {
}

Интерфейс Реактивный CrudRepository обеспечивает операции CRUD в репозитории для определенного типа и следует реактивным парадигмам и использует Реактор проекта типы, которые построены поверх реактивных потоков.

Настройка конфигурации подключения

Как упоминалось ранее, для создания подключения к базе данных с использованием R2DBC необходимо сначала создать СоединениеФабрика . Реализация интерфейса ConnectionFactory в MariaDB называется Maria dbConnectionFactory и для этого требуется экземпляр конфигурации подключения Mariadb , который содержит различные сведения о конфигурации , используемые для подключения к экземпляру базы данных MariaDB.

Создайте новую папку под названием “конфигурация” в/src/main/java/com/mariadb/для выполнения и создайте в ней новый файл с именем “R2DBCConfig.java “

Открыть “R2DBCConfig.java ” и добавьте следующий код.

package com.mariadb.todo.config;

import org.mariadb.r2dbc.MariadbConnectionConfiguration;
import org.mariadb.r2dbc.MariadbConnectionFactory;
import org.mariadb.r2dbc.SslMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

@Configuration
@EnableR2dbcRepositories
public class R2DBCConfig extends AbstractR2dbcConfiguration {
    @Override
    @Bean
    public MariadbConnectionFactory connectionFactory() {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Properties props = new Properties();
        try (InputStream f = loader.getResourceAsStream("db.properties")) {
            props.load(f); 
            return new MariadbConnectionFactory(MariadbConnectionConfiguration.builder()
                .host(props.getProperty("host"))
                .port(Integer.parseInt(props.getProperty("port")))
                .username(props.getProperty("username"))
                .password(props.getProperty("password"))
                .database(props.getProperty("database"))
                .build());
        }
        catch (IOException e) {
            System.out.println(e.getMessage());
            return null;
        }
    }
}

Обратите внимание, что R2DBCConfig извлекает сведения о подключении к базе данных из файла под названием “db.properties”. Чтобы добавить конфигурацию подключения, перейдите в/src/main/java/com/mariadb/ресурсы, создайте новый файл под названием “db.свойства” и добавьте следующий код.

host=127.0.0.1
port=3306
username=USERNAME_HERE
password=PASSWORD_HERE
database=todo

Хотя это и не рекомендуется, вы можете добавить сведения о подключении непосредственно в R2DBCConfig.java .

Создайте службу передачи данных

Службы можно использовать для управления бизнес-логикой вашего приложения. Единственная служба, служба задач, в этом приложении используется для проверки объекта задачи и интеграции с TasksRepository.

Создайте новую папку под названием “службы” в/src/main/java/com/mariadb/для выполнения и создайте в ней новый файл с именем “TasksService.java “

Открыть “TasksService.java ” и добавьте следующий код.

package com.mariadb.todo.services;

import com.mariadb.todo.models.Task;
import com.mariadb.todo.repositories.TasksRepository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

// Registered as a Spring Service (Component)
@Service
public class TaskService {

    // Automatically instantiate (via Spring IoC) 
    @Autowired
    private TasksRepository repository;

    // 
    public Boolean isValid(final Task task) {
        if (task != null && !task.getDescription().isEmpty()) {
            return true;
        }
        return false;
    }

    // Get all records from the tasks table
    public Flux getAllTasks() {
        return this.repository.findAll();
    }

    // Save a new task record
    public Mono createTask(final Task task) {
        return this.repository.save(task);
    }

    // Update an existing task record
    @Transactional
    public Mono updateTask(final Task task) {
        return this.repository.findById(task.getId())
                .flatMap(t -> {
                    t.setDescription(task.getDescription());
                    t.setCompleted(task.getCompleted());
                    return this.repository.save(t);
                });
    }

    // Delete the task record by specified id
    @Transactional
    public Mono deleteTask(final int id){
        return this.repository.findById(id)
                .flatMap(this.repository::delete);
    }
}

Выставлять конечные точки API

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

Создайте новую папку под названием “контроллеры” в/src/main/java/com/mariadb/для выполнения и создайте в ней новый файл с именем “TasksController.java “

Открыть “TasksController.java ” и добавьте следующий код.

package com.mariadb.todo.controllers;

import com.mariadb.todo.models.Task;
import com.mariadb.todo.services.TaskService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/api/tasks")
public class TasksController {

    @Autowired
    private TaskService service;

    @GetMapping()
    public ResponseEntity> get() {
        return ResponseEntity.ok(this.service.getAllTasks());
    }

    @PostMapping()
    public ResponseEntity> post(@RequestBody Task task) {
        if (service.isValid(task)) {
            return ResponseEntity.ok(this.service.createTask(task));
        }
        return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT).build();
    }

    @PutMapping()
    public ResponseEntity> put(@RequestBody Task task) {
        if (service.isValid(task)) {
            return ResponseEntity.ok(this.service.updateTask(task));
        }
        return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT).build();
    }

    @DeleteMapping()
    public ResponseEntity> delete(@RequestParam int id) {
        if (id > 0) {
            return ResponseEntity.ok(this.service.deleteTask(id));
        }
        return ResponseEntity.status(HttpStatus.I_AM_A_TEAPOT).build();
    }
}

Теперь, когда все построено, пришло время проверить это!

Во-первых, создайте приложение.

$ mvn package

А затем запустите его.

$ mvn spring-boot:run

Во-первых, начните с добавления новой задачи в свой список дел.

$ curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"description":"A New Task"}' \
  http://localhost:8080/api/tasks

Хотя вы, безусловно, можете напрямую запросить базу данных, чтобы подтвердить добавление новой записи о задаче, в чем же в этом удовольствие? Вернемся к API!

$ curl https://localhost:8080/api/tasks

Если все пойдет хорошо, вы должны получить следующий JSON-ответ:

{ "id": 1, "description": "A New Task", "completed": false }

Вуаля, полностью реактивное приложение Java Spring, использующее R2DBC и MariaDB!

Чтобы просмотреть этот код полностью, ознакомьтесь с исходным кодом здесь . И если вам интересно, “было бы здорово увидеть реализацию с пользовательским интерфейсом”, вам повезло! Вы можете найти полностью развернутую реализацию приложения TODO с помощью React.js и ваш выбор из нескольких проектов API ((R2 ODBC, JDBC, Node.js и Python), которые напрямую интегрируются с MariaDB здесь !

Теперь, когда вы успешно создали новый проект Maven с использованием Spring Data, R2DBC и MariaDB, у вас есть все необходимые инструменты, чтобы начать создавать полностью реактивные приложения, используя возможности MariaDB, самостоятельно!

Если у вас есть какие-либо вопросы, предложения или проблемы с этим сообщением в блоге, пожалуйста, дайте мне знать здесь или свяжитесь со мной напрямую в Твиттере по адресу @probablyrealrob !

Спасибо, что нашли время прочитать это, и счастливого кодирования!

Оригинал: “https://dev.to/probablyrealrob/reactive-programming-with-java-spring-r2dbc-and-mariadb-3327”