Поделиться через


Использование R2DBC Spring Data с Базой данных Azure для PostgreSQL

В этой статье описано создание примера приложения, которое использует R2DBC Spring Data для сохранения данных в Базе данных Azure для PostgreSQL и их извлечения из нее. В этом примере будет использоваться реализация R2DBC для PostgreSQL из репозитория r2dbc-postgresql в GitHub.

R2DBC приносит реактивные API к традиционным реляционным базам данных. Вы можете применять это решение со Spring WebFlux для создания полностью реактивных приложений Spring Boot, которые используют неблокирующие API. Оно обеспечивает улучшенную масштабируемость по сравнению с классическим подходом "один поток на подключение".

Необходимые компоненты

  • Клиент командной строки PostgreSQL.

  • cURL или подобная служебная HTTP-программа, с помощью которой можно протестировать функциональные возможности.

См. пример приложения

В этой статье вы закодируем пример приложения. Если вы хотите ускорить работу, готовое приложение доступно здесь: https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-postgresql.

Подготовка среды выполнения

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

export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_SERVER_NAME=<YOUR_DATABASE_SERVER_NAME>
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_POSTGRESQL_ADMIN_USERNAME=spring
export AZ_POSTGRESQL_ADMIN_PASSWORD=<YOUR_POSTGRESQL_ADMIN_PASSWORD>
export AZ_POSTGRESQL_NON_ADMIN_USERNAME=nonspring
export AZ_POSTGRESQL_NON_ADMIN_PASSWORD=<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>

Замените заполнители следующими значениями, которые используются в этой статье:

  • <YOUR_DATABASE_SERVER_NAME>: имя сервера PostgreSQL, который должен быть уникальным в Azure.
  • <YOUR_DATABASE_NAME>: имя базы данных сервера PostgreSQL, которое должно быть уникальным в Azure.
  • <YOUR_AZURE_REGION>: регион Azure, который вы будете использовать. Вы можете использовать eastus по умолчанию, но мы рекомендуем настроить регион, расположенный близко к месту проживания. Полный список доступных регионов можно просмотреть с помощью az account list-locations.
  • <YOUR_POSTGRESQL_ADMIN_PASSWORD> и <YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>: пароль сервера базы данных PostgreSQL, который должен содержать не менее восьми символов. и включать знаки всех следующих типов: прописные латинские буквы, строчные латинские буквы, цифры (0–9) и небуквенно-цифровые знаки (!, $, #, % и т. д.).
  • <YOUR_LOCAL_IP_ADDRESS>: IP-адрес локального компьютера, с которого будет запущено приложение Spring Boot. Один из удобных способов найти его — открыть whatismyip.akamai.com.

Примечание.

Корпорация Майкрософт рекомендует использовать самый безопасный поток проверки подлинности. Поток проверки подлинности, описанный в этой процедуре, например для баз данных, кэшей, сообщений или служб ИИ, требует очень высокой степени доверия к приложению и несет риски, не присутствующих в других потоках. Используйте этот поток, только если более безопасные параметры, такие как управляемые удостоверения для бессерверных или бессерверных подключений, не являются жизнеспособными. Для локальных операций компьютера предпочитайте удостоверения пользователей для бессерверных или бессерверных подключений.

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

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    --output tsv

Создание экземпляра База данных Azure для PostgreSQL и настройка пользователя администратора

Первое, что вы создадите, — это управляемый сервер PostgreSQL с пользователем администратора.

az postgres flexible-server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --location $AZ_LOCATION \
    --admin-user $AZ_POSTGRESQL_ADMIN_USERNAME \
    --admin-password $AZ_POSTGRESQL_ADMIN_PASSWORD \
    --yes \
    --output tsv

Настройка базы данных PostgreSQL

Созданный вами ранее сервер PostgreSQL пуст. Чтобы создать новую базу данных, используйте следующую команду.

az postgres flexible-server db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --database-name $AZ_DATABASE_NAME \
    --server-name $AZ_DATABASE_SERVER_NAME \
    --output tsv

Настройка правила брандмауэра для сервера PostgreSQL

Экземпляры Базы данных Azure для PostgreSQL по умолчанию защищены. В них включен брандмауэр, который блокирует все входящие подключения. Чтобы вы могли использовать нашу базу данных, добавьте правило брандмауэра, которое разрешит локальному IP-адресу обращаться к серверу базы данных.

Так как вы настроили локальный IP-адрес ранее, вы можете открыть брандмауэр сервера, выполнив следующую команду:

az postgres flexible-server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --rule-name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS \
    --output tsv

Если вы подключаетесь к серверу PostgreSQL из подсистема Windows для Linux (WSL) на компьютере Windows, необходимо добавить идентификатор узла WSL в брандмауэр.

Получите IP-адрес хост-компьютера, выполнив следующую команду в WSL:

cat /etc/resolv.conf

Скопируйте IP-адрес после термина nameserver, а затем используйте следующую команду, чтобы задать переменную среды для IP-адреса WSL:

export AZ_WSL_IP_ADDRESS=<the-copied-IP-address>

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

az postgres flexible-server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --rule-name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip \
    --start-ip-address $AZ_WSL_IP_ADDRESS \
    --end-ip-address $AZ_WSL_IP_ADDRESS \
    --output tsv

Создание пользователя, отличного от администратора PostgreSQL, и предоставление разрешения

Затем создайте пользователя без администратора и предоставьте всем разрешения для базы данных.

Примечание.

Дополнительные сведения о создании пользователей PostgreSQL см. в статье "Создание пользователей" в База данных Azure для PostgreSQL.

Создайте скрипт SQL с именем create_user.sql для создания пользователя без администратора. Добавьте следующее содержимое и сохраните его локально:

Примечание.

Корпорация Майкрософт рекомендует использовать самый безопасный поток проверки подлинности. Поток проверки подлинности, описанный в этой процедуре, например для баз данных, кэшей, сообщений или служб ИИ, требует очень высокой степени доверия к приложению и несет риски, не присутствующих в других потоках. Используйте этот поток, только если более безопасные параметры, такие как управляемые удостоверения для бессерверных или бессерверных подключений, не являются жизнеспособными. Для локальных операций компьютера предпочитайте удостоверения пользователей для бессерверных или бессерверных подключений.

cat << EOF > create_user.sql
CREATE ROLE "$AZ_POSTGRESQL_NON_ADMIN_USERNAME" WITH LOGIN PASSWORD '$AZ_POSTGRESQL_NON_ADMIN_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE $AZ_DATABASE_NAME TO "$AZ_POSTGRESQL_NON_ADMIN_USERNAME";
EOF

Затем выполните следующую команду, чтобы запустить скрипт SQL для создания пользователя, отличного от администратора Microsoft Entra:

psql "host=$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com user=$AZ_POSTGRESQL_ADMIN_USERNAME dbname=$AZ_DATABASE_NAME port=5432 password=$AZ_POSTGRESQL_ADMIN_PASSWORD sslmode=require" < create_user.sql

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

rm create_user.sql

Создание реактивного приложения Spring Boot

Чтобы создать реактивное приложение Spring Boot, мы будем использовать Spring Initializr. Приложение, которое мы создадим, использует:

  • Spring Boot 2.7.11.
  • Следующие зависимости: Spring Reactive Web (также известный как Spring WebFlux) и Spring Data R2DBC.

Создание приложения с помощью Spring Initializr

Создайте приложение в командной строке с помощью следующей команды:

curl https://start.spring.io/starter.tgz -d dependencies=webflux,data-r2dbc -d baseDir=azure-database-workshop -d bootVersion=2.7.11 -d javaVersion=17 | tar -xzvf -

Добавление реализации реактивного драйвера PostgreSQL

Откройте файл pom.xml созданного проекта и добавьте реактивный драйвер PostgreSQL из репозитория r2dbc-postgresql на GitHub. После зависимости spring-boot-starter-webflux добавьте следующий текст:

<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-postgresql</artifactId>
    <version>0.8.12.RELEASE</version>
    <scope>runtime</scope>
</dependency>

Настройка Spring Boot для использования Базы данных Azure для PostgreSQL

Откройте файл src/main/resources/application.properties и добавьте следующий текст:

logging.level.org.springframework.data.r2dbc=DEBUG

spring.r2dbc.url=r2dbc:pool:postgres://$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com:5432/$AZ_DATABASE_NAME
spring.r2dbc.username=nonspring
spring.r2dbc.password=$AZ_POSTGRESQL_NON_ADMIN_PASSWORD
spring.r2dbc.properties.sslMode=REQUIRE

Замените $AZ_DATABASE_SERVER_NAME$AZ_DATABASE_NAMEпеременные и $AZ_POSTGRESQL_NON_ADMIN_PASSWORD переменные значениями, настроенными в начале этой статьи.

Предупреждение

Из соображений безопасности для Базы данных Azure для PostgreSQL требуется использовать SSL-соединения. Поэтому вам нужно добавить свойство конфигурации spring.r2dbc.properties.sslMode=REQUIRE. В противном случае драйвер R2DBC PostgreSQL будет использовать небезопасное подключение, что приведет к сбою.

Примечание.

Для лучшей производительности в качестве значения свойства spring.r2dbc.url указан пул подключений, как описано в репозитории r2dbc-pool.

Теперь вы можете запустить приложение с помощью предоставленной программы-оболочки Maven:

./mvnw spring-boot:run

Ниже приведен снимок экрана приложения, выполняемого в первый раз:

Снимок экрана: работающее приложение.

Создание схемы базы данных

В основном классе DemoApplication настройте новый bean-компонент Spring, который создаст схему базы данных, с помощью следующего кода:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.r2dbc.connectionfactory.init.ConnectionFactoryInitializer;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator;

import io.r2dbc.spi.ConnectionFactory;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
        ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
        initializer.setConnectionFactory(connectionFactory);
        ResourceDatabasePopulator populator = new ResourceDatabasePopulator(new ClassPathResource("schema.sql"));
        initializer.setDatabasePopulator(populator);
        return initializer;
    }
}

Этот bean-компонент Spring использует файл с именем schema.sql, поэтому создайте этот файл в папке src/main/resources и добавьте следующий текст:

DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);

Остановите приложение и запустите его снова с помощью следующей команды. Теперь приложение будет использовать созданную ранее базу данных demo и создаст в ней таблицу todo.

./mvnw spring-boot:run

Ниже приведен снимок экрана с создаваемой таблицей базы данных:

Снимок экрана: создание таблицы базы данных.

Добавление кода приложения

Затем добавьте код Java, который будет использовать R2DBC для хранения и извлечения данных с сервера PostgreSQL.

Создайте новый класс Java Todo рядом с классом DemoApplication с помощью следующего кода:

package com.example.demo;

import org.springframework.data.annotation.Id;

public class Todo {

    public Todo() {
    }

    public Todo(String description, String details, boolean done) {
        this.description = description;
        this.details = details;
        this.done = done;
    }

    @Id
    private Long id;

    private String description;

    private String details;

    private boolean done;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDetails() {
        return details;
    }

    public void setDetails(String details) {
        this.details = details;
    }

    public boolean isDone() {
        return done;
    }

    public void setDone(boolean done) {
        this.done = done;
    }
}

Этот класс является моделью предметной области, сопоставленной с таблицей todo, созданной ранее.

Для управления этим классом необходим репозиторий. Определите новый интерфейс TodoRepository в том же пакете с помощью следующего кода:

package com.example.demo;

import org.springframework.data.repository.reactive.ReactiveCrudRepository;

public interface TodoRepository extends ReactiveCrudRepository<Todo, Long> {
}

Этот репозиторий является реактивным репозиторием, управляемым Spring Data R2DBC.

Завершите работу приложения, создав контроллер, который может хранить и извлекать данные. Реализуйте класс TodoController в том же пакете и добавьте следующий код:

package com.example.demo;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/")
public class TodoController {

    private final TodoRepository todoRepository;

    public TodoController(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    @PostMapping("/")
    @ResponseStatus(HttpStatus.CREATED)
    public Mono<Todo> createTodo(@RequestBody Todo todo) {
        return todoRepository.save(todo);
    }

    @GetMapping("/")
    public Flux<Todo> getTodos() {
        return todoRepository.findAll();
    }
}

Остановите приложение и запустите его снова с помощью следующей команды:

./mvnw spring-boot:run

Тестирование приложения

Чтобы протестировать приложение, можно использовать cURL.

Сначала создайте новый элемент todo в базе данных с помощью следующей команды:

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done": "true"}' \
    http://127.0.0.1:8080

Эта команда должна возвращать созданный элемент, как показано здесь:

{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}

Затем извлеките данные, используя новый запрос cURL, с помощью следующей команды:

curl http://127.0.0.1:8080

Эта команда вернет список элементов todo, включая созданный вами элемент, как показано здесь:

[{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}]

Ниже приведен снимок экрана с этими запросами cURL:

Снимок экрана: тест cURL.

Поздравляем! Вы создали полностью реактивное приложение Spring Boot, которое использует R2DBC для хранения и извлечения данных из Базы данных Azure для PostgreSQL.

Очистка ресурсов

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

az group delete \
    --name $AZ_RESOURCE_GROUP \
    --yes

Следующие шаги

Дополнительные сведения о развертывании приложения Spring Data в Azure Spring Apps и использовании управляемого удостоверения см. в руководстве по развертыванию приложения Spring в Azure Spring Apps с подключением без пароля к базе данных Azure.

Дополнительные сведения о Spring и Azure см. в центре документации об использовании Spring в Azure.

См. также

См. сведения о Spring Data R2DBC в справочной документации по Spring.

См. сведения об использовании Java в Azure в руководствах по использованию Azure для разработчиков Java и Azure DevOps и Java.