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

W tym artykule przedstawiono tworzenie przykładowej aplikacji korzystającej z narzędzia Spring Data R2DBC do przechowywania i pobierania informacji w usłudze Azure Database for MySQL przy użyciu implementacji R2DBC dla bazy danych MySQL z repozytorium GitHub r2dbc-mysql.

Łączność R2DBC wprowadza reaktywne interfejsy 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 MySQL.

  • 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-mysql.

Przygotowywanie środowiska roboczego

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

export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_MYSQL_ADMIN_USERNAME=spring
export AZ_MYSQL_ADMIN_PASSWORD=<YOUR_MYSQL_ADMIN_PASSWORD>
export AZ_MYSQL_NON_ADMIN_USERNAME=spring-non-admin
export AZ_MYSQL_NON_ADMIN_PASSWORD=<YOUR_MYSQL_NON_ADMIN_PASSWORD>

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

  • <YOUR_DATABASE_NAME>: nazwa serwera MySQL, który powinien być unikatowy na platformie Azure.
  • <YOUR_AZURE_REGION>: region platformy Azure, którego będziesz używać. Możesz domyślnie zastosować region eastus, ale zalecamy skonfigurowanie regionu bliżej Twojego miejsca zamieszkania. Pełną listę dostępnych regionów można wyświetlić przy użyciu polecenia az account list-locations.
  • <YOUR_MYSQL_ADMIN_PASSWORD> i <YOUR_MYSQL_NON_ADMIN_PASSWORD>: Hasło serwera bazy danych MySQL, 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.).

Następnie utwórz grupę zasobów:

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

Tworzenie wystąpienia usługi Azure Database for MySQL i konfigurowanie użytkownika administratora

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

Uwaga

Więcej szczegółowych informacji na temat tworzenia serwerów MySQL można znaleźć w artykule Tworzenie serwera usługi Azure Database for MySQL przy użyciu witryny Azure Portal.

az mysql flexible-server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --admin-user $AZ_MYSQL_ADMIN_USERNAME \
    --admin-password $AZ_MYSQL_ADMIN_PASSWORD \
    --yes \
    --output tsv

Konfigurowanie bazy danych MySQL

Utwórz nową bazę danych o nazwie demo przy użyciu następującego polecenia:

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

Konfigurowanie reguły zapory dla serwera MySQL

Wystąpienia usługi Azure Database for MySQL są domyślnie zabezpieczone. Ma ona zaporę, która nie zezwala na żadne połączenie przychodzące.

Jeśli używasz powłoki Bash, możesz pominąć ten krok, ponieważ flexible-server create polecenie już wykryło lokalny adres IP i ustawiło go na serwerze MySQL.

Jeśli łączysz się z serwerem MySQL z Podsystem Windows dla systemu Linux (WSL) na komputerze z systemem Windows, musisz dodać identyfikator hosta WSL do zapory. Uzyskaj 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 mysql flexible-server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --start-ip-address $AZ_WSL_IP_ADDRESS \
    --end-ip-address $AZ_WSL_IP_ADDRESS \
    --rule-name allowiprange \
    --output tsv

Tworzenie użytkownika innego niż administrator programu MySQL i udzielanie uprawnień

Ten krok spowoduje utworzenie użytkownika niebędącego administratorem i przyznanie mu wszystkich uprawnień do demo bazy danych.

Uwaga

Więcej szczegółowych informacji na temat tworzenia użytkowników programu MySQL można znaleźć w temacie Tworzenie użytkowników w usłudze Azure Database for MySQL.

Najpierw 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:

cat << EOF > create_user.sql
CREATE USER '$AZ_MYSQL_NON_ADMIN_USERNAME'@'%' IDENTIFIED BY '$AZ_MYSQL_NON_ADMIN_PASSWORD';
GRANT ALL PRIVILEGES ON demo.* TO '$AZ_MYSQL_NON_ADMIN_USERNAME'@'%';
FLUSH PRIVILEGES;
EOF

Następnie użyj następującego polecenia, aby uruchomić skrypt SQL w celu utworzenia użytkownika niebędącego administratorem:

mysql -h $AZ_DATABASE_NAME.mysql.database.azure.com --user $AZ_MYSQL_ADMIN_USERNAME --enable-cleartext-plugin --password=$AZ_MYSQL_ADMIN_PASSWORD < 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, wprowadzając następujące polecenie:

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 MySQL

Otwórz plik pom.xml wygenerowanego projektu, aby dodać reaktywny sterownik MySQL z repozytorium r2dbc-mysql w usłudze GitHub.

Za zależnością spring-boot-starter-webflux dodaj następujący fragment kodu:

<dependency>
  <groupId>io.asyncer</groupId>
  <artifactId>r2dbc-mysql</artifactId>
  <version>0.9.1</version>
</dependency>

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

Otwórz plik src/main/resources/application.properties i dodaj:

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

spring.r2dbc.url=r2dbc:pool:mysql://$AZ_DATABASE_NAME.mysql.database.azure.com:3306/demo?tlsVersion=TLSv1.2
spring.r2dbc.username=spring-non-admin
spring.r2dbc.password=$AZ_MYSQL_NON_ADMIN_PASSWORD

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

Uwaga

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

Teraz powinno być możliwe uruchomienie aplikacji przy użyciu dostarczonej otoki narzędzia Maven:

./mvnw spring-boot:run

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

Screenshot of the running application.

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 fasola Spring używa 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. Aplikacja będzie teraz korzystać z utworzonej wcześniej bazy danych demo i utworzy w niej tabelę todo.

./mvnw spring-boot:run

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

Screenshot of the creation of the database table.

Kodowanie aplikacji

Następnie dodaj kod Java, który będzie używać R2DBC do przechowywania i pobierania danych z serwera MySQL.

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, które zarządza rozwiązaniem 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:

Screenshot of the cURL test.

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

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.