Używanie rozwiązania Spring Data R2DBC z usługą Azure Database for PostgreSQL

W tym artykule pokazano, jak używać rozwiązania Spring Data R2DBC z Azure Database for PostgreSQL w celu utworzenia skalowalnej, w pełni reaktywnej aplikacji Spring Boot, która przechowuje i pobiera informacje. W przykładzie użyto implementacji R2DBC dla bazy danych PostgreSQL z repozytorium r2dbc-postgresql w GitHub.

R2DBC wprowadza reaktywne API do tradycyjnych relacyjnych baz danych. Można go używać z platformą Spring WebFlux, aby utworzyć w pełni reaktywne aplikacje Spring Boot korzystające z nieblokujących interfejsów API. Zapewnia lepszą skalowalność niż klasyczne podejście "jeden wątek na połączenie".

Wymagania wstępne

  • Klient wiersza polecenia postgreSQL.

  • cURL lub podobne narzędzie HTTP do testowania funkcjonalności.

Zobacz przykładową aplikację

W tym artykule kodujesz przykładową aplikację. Jeśli chcesz przyspieszyć, ta aplikacja jest już kodowana i dostępna pod adresem https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-postgresql.

Przygotowywanie środowiska roboczego

Najpierw skonfiguruj niektóre zmienne środowiskowe, uruchamiając następujące polecenia:

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>

Zastąp symbole zastępcze następującymi wartościami, które są używane w tym artykule:

  • <YOUR_DATABASE_SERVER_NAME>: nazwa serwera PostgreSQL, który powinien być unikatowy na platformie Azure.
  • <YOUR_DATABASE_NAME>: nazwa bazy danych serwera PostgreSQL, który powinien być unikatowy na platformie Azure.
  • <YOUR_AZURE_REGION>: region platformy Azure, którego będziesz używać. Możesz użyć eastus domyślnie, ale skonfigurować region bliżej miejsca, w którym mieszkasz. Zobacz pełną listę dostępnych regionów przy użyciu polecenia az account list-locations.
  • <YOUR_POSTGRESQL_ADMIN_PASSWORD> i <YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>: hasło serwera bazy danych PostgreSQL, które powinno zawierać co najmniej osiem znaków. Znaki powinny pochodzić z trzech z następujących kategorii: wielkie litery angielskie, małe litery angielskie, cyfry (0–9) i znaki inne niż alfanumeryczne (!, $, #, %itd.).
  • <YOUR_LOCAL_IP_ADDRESS>: adres IP komputera lokalnego, z którego będzie uruchamiana aplikacja Spring Boot. Jednym z wygodnych sposobów znalezienia go jest otwarcie whatismyip.akamai.com.

Uwaga

Firma Microsoft zaleca korzystanie z najbezpieczniejszego dostępnego przepływu uwierzytelniania. Przepływ uwierzytelniania opisany w tej procedurze, taki jak bazy danych, pamięci podręczne, komunikaty lub usługi sztucznej inteligencji, wymaga bardzo wysokiego stopnia zaufania w aplikacji i niesie ze sobą ryzyko, które nie występują w innych przepływach. Użyj tego przepływu tylko wtedy, gdy bardziej bezpieczne opcje, takie jak tożsamości zarządzane dla połączeń bez hasła lub bez kluczy, nie są opłacalne. W przypadku operacji maszyny lokalnej preferuj tożsamości użytkowników dla połączeń bez hasła lub bez klucza.

Następnie utwórz grupę zasobów przy użyciu następującego polecenia:

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

Utwórz wystąpienie usługi Azure Database for PostgreSQL i skonfiguruj użytkownika administracyjnego

Pierwszą rzeczą, którą tworzysz, jest zarządzany serwer PostgreSQL z użytkownikiem administratora.

Uwaga

Aby uzyskać więcej informacji na temat tworzenia serwerów PostgreSQL, zobacz Tworzenie serwera Azure Database for PostgreSQL przy użyciu portalu Azure.

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

Konfigurowanie bazy danych PostgreSQL

Utworzony wcześniej serwer PostgreSQL jest pusty. Użyj następującego polecenia, aby utworzyć nową bazę danych.

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

Konfigurowanie reguły zapory dla serwera PostgreSQL

Wystąpienia usługi Azure Database for PostgreSQL są domyślnie zabezpieczone. Ma ona zaporę, która nie zezwala na żadne połączenie przychodzące. Aby użyć bazy danych, należy dodać regułę zapory, która umożliwia lokalnemu adresowi IP uzyskiwanie dostępu do serwera bazy danych.

Ponieważ na początku tego artykułu skonfigurowano lokalny adres IP, możesz otworzyć zaporę serwera, uruchamiając następujące polecenie:

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

Jeśli łączysz się z serwerem PostgreSQL z poziomu Podsystemu Windows dla systemu Linux (WSL) na komputerze z systemem Windows, musisz dodać identyfikator hosta systemu WSL do zapory.

Pobierz adres IP maszyny hosta, uruchamiając następujące polecenie w programie WSL:

cat /etc/resolv.conf

Skopiuj adres IP zgodnie z terminem nameserver, a następnie użyj następującego polecenia, aby ustawić zmienną środowiskową dla adresu IP WSL:

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

Następnie użyj następującego polecenia, aby otworzyć zaporę serwera w aplikacji opartej na protokole 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

Tworzenie użytkownika niebędącego administratorem bazy danych PostgreSQL i udzielanie uprawnień

Następnie utwórz użytkownika niebędącego administratorem i przyznaj wszystkie uprawnienia do bazy danych.

Uwaga

Aby uzyskać więcej informacji na temat tworzenia użytkowników postgreSQL, zobacz Tworzenie użytkowników w Azure Database for PostgreSQL.

Utwórz skrypt SQL o nazwie create_user.sql na potrzeby tworzenia użytkownika niebędącego administratorem. Dodaj następującą zawartość i zapisz ją lokalnie:

Uwaga

Firma Microsoft zaleca korzystanie z najbezpieczniejszego dostępnego przepływu uwierzytelniania. Przepływ uwierzytelniania opisany w tej procedurze, taki jak bazy danych, pamięci podręczne, komunikaty lub usługi sztucznej inteligencji, wymaga bardzo wysokiego stopnia zaufania w aplikacji i niesie ze sobą ryzyko, które nie występują w innych przepływach. Użyj tego przepływu tylko wtedy, gdy bardziej bezpieczne opcje, takie jak tożsamości zarządzane dla połączeń bez hasła lub bez kluczy, nie są opłacalne. W przypadku operacji maszyny lokalnej preferuj tożsamości użytkowników dla połączeń bez hasła lub bez klucza.

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

Następnie użyj następującego polecenia, aby uruchomić skrypt SQL i utworzyć Microsoft Entra użytkownika niebędącego administratorem:

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

Teraz użyj następującego polecenia, aby usunąć tymczasowy plik skryptu SQL:

rm create_user.sql

Tworzenie reaktywnej aplikacji Spring Boot

Aby utworzyć reaktywną aplikację Spring Boot, użyjemy narzędzia Spring Initializr. Aplikacja, którą utworzymy, używa następujących funkcji:

  • Spring Boot 2.7.11.
  • Następujące zależności: Spring Reactive Web (znany również jako Spring WebFlux) i Spring Data R2DBC.

Generowanie aplikacji przy użyciu narzędzia Spring Initializr

Wygeneruj aplikację w wierszu polecenia przy użyciu następującego polecenia:

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 -

Dodawanie reaktywnej implementacji sterownika PostgreSQL

Otwórz plik pom.xml wygenerowanego projektu, a następnie dodaj reaktywny sterownik PostgreSQL z repozytorium r2dbc-postgresql w serwisie GitHub. Po zależności spring-boot-starter-webflux dodaj następujący tekst:

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

Konfigurowanie platformy Spring Boot do korzystania z usługi Azure Database for PostgreSQL

Otwórz plik src/main/resources/application.properties i dodaj następujący tekst:

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

Zastąp zmienne $AZ_DATABASE_SERVER_NAME, $AZ_DATABASE_NAME i $AZ_POSTGRESQL_NON_ADMIN_PASSWORD wartościami skonfigurowanymi na początku tego artykułu.

Ostrzeżenie

Ze względów bezpieczeństwa Azure Database for PostgreSQL wymaga połączeń SSL. spring.r2dbc.properties.sslMode=REQUIRE Dodaj właściwość konfiguracji. W przeciwnym razie sterownik PostgreSQL R2DBC próbuje nawiązać połączenie przy użyciu niezabezpieczonego połączenia, co kończy się niepowodzeniem.

Uwaga

Aby uzyskać lepszą wydajność, właściwość spring.r2dbc.url jest skonfigurowana do korzystania z puli połączeń przy użyciu r2dbc-pool.

Możesz teraz uruchomić aplikację za pomocą dostarczonego wrappera Maven w następujący sposób:

./mvnw spring-boot:run

Oto zrzut ekranu przedstawiający aplikację uruchomioną po raz pierwszy:

Zrzut ekranu przedstawiający uruchomioną aplikację.

Tworzenie schematu bazy danych

W klasie głównej DemoApplication skonfiguruj nową fasolę Spring, która utworzy schemat bazy danych przy użyciu następującego kodu:

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

Ten komponent Spring korzysta z pliku o nazwie schema.sql, więc utwórz ten plik w folderze src/main/resources i dodaj następujący tekst:

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

Zatrzymaj uruchomioną aplikację i uruchom ją ponownie, używając następującego polecenia. Aplikacja używa teraz bazy danych demo, którą utworzono wcześniej, i tworzy w niej tabelę todo.

./mvnw spring-boot:run

Oto zrzut ekranu przedstawiający tabelę bazy danych podczas jej tworzenia:

Zrzut ekranu przedstawiający tworzenie tabeli bazy danych.

Kodowanie aplikacji

Następnie dodaj kod Java, który używa protokołu R2DBC do przechowywania i pobierania danych z serwera PostgreSQL.

Utwórz nową Todo klasę Języka Java obok DemoApplication klasy przy użyciu następującego kodu:

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

Ta klasa jest modelem domeny zamapowanym na utworzonej wcześniej tabeli todo.

Do zarządzania tą klasą potrzebujesz repozytorium. Zdefiniuj nowy TodoRepository interfejs w tym samym pakiecie przy użyciu następującego kodu:

package com.example.demo;

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

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

To repozytorium jest reaktywnym repozytorium zarządzanym przez Spring Data R2DBC.

Zakończ aplikację, tworząc kontroler, który może przechowywać i pobierać dane. Zaimplementuj klasę TodoController w tym samym pakiecie i dodaj następujący kod:

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

Na koniec wstrzymaj działanie aplikacji i uruchom ją ponownie za pomocą następującego polecenia:

./mvnw spring-boot:run

Testowanie aplikacji

Do przetestowania aplikacji możesz użyć narzędzia cURL.

Najpierw utwórz nowy element typu „czynność do wykonania” w bazie danych przy użyciu następującego polecenia:

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

To polecenie powinno zwrócić utworzony element, jak pokazano poniżej:

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

Następnie pobierz dane przy użyciu nowego żądania cURL za pomocą następującego polecenia:

curl http://127.0.0.1:8080

To polecenie zwróci listę elementów "todo", w tym utworzony element, jak pokazano poniżej:

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

Oto zrzut ekranu przedstawiający te żądania cURL:

Zrzut ekranu przedstawiający test cURL.

Gratulacje! Utworzono w pełni reaktywną aplikację Spring Boot, która używa protokołu R2DBC do przechowywania i pobierania danych z Azure Database for PostgreSQL.

Czyszczenie zasobów

Aby wyczyścić wszystkie zasoby używane w tym przewodniku Szybki start, usuń grupę zasobów przy użyciu następującego polecenia:

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

Następne kroki

Aby dowiedzieć się więcej na temat wdrażania aplikacji Spring Data w usłudze Azure Spring Apps i używania tożsamości zarządzanej, zobacz Samouczek: wdrażanie aplikacji Spring w usłudze Azure Spring Apps przy użyciu połączenia bez hasła z bazą danych platformy Azure.

Aby dowiedzieć się więcej na temat oprogramowania Spring i platformy Azure, przejdź do centrum dokumentacji dotyczącej oprogramowania Spring na platformie Azure.

Zobacz też

Aby uzyskać więcej informacji na temat rozwiązania Spring Data R2DBC, zobacz dokumentację referencyjną platformy Spring.

Aby uzyskać więcej informacji na temat używania platformy Azure z językiem Java, zobacz artykuły dotyczące platformy Azure dla deweloperów języka Java oraz pracy z usługą Azure DevOps i językiem Java.