Condividi tramite


Usare Spring Data R2DBC con Database di Azure per MySQL

Questo articolo illustra la creazione di un'applicazione di esempio che usa Spring Data R2DBC per archiviare e recuperare informazioni in Database di Azure per MySQL usando l'implementazione R2DBC per MySQL dal repository GitHub r2dbc-mysql.

R2DBC introduce le API reattive nei database relazionali tradizionali. È possibile usarlo con Spring WebFlux per creare applicazioni Spring Boot completamente reattive che usano API non bloccanti. Offre una migliore scalabilità rispetto all'approccio classico di "un thread per connessione".

Prerequisiti

  • Client della riga di comando di MySQL.

  • cURL o un'utilità HTTP simile per testare la funzionalità.

Vedere l'applicazione di esempio

In questo articolo verrà codificata un'applicazione di esempio. Per procedere più rapidamente, è possibile usare l'applicazione già pronta, disponibile all'indirizzo https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-mysql.

Preparare l'ambiente di lavoro

Prima di tutto, configurare alcune variabili di ambiente eseguendo i comandi seguenti:

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>

Sostituire i segnaposto con i valori seguenti, che vengono usati nell'intero articolo:

  • <YOUR_DATABASE_NAME>: nome del server MySQL, che deve essere univoco in Azure.
  • <YOUR_AZURE_REGION>: l'area di Azure da usare. È possibile usare eastus per impostazione predefinita, ma è consigliabile configurare un'area più vicina a dove si risiede. È possibile visualizzare l'elenco completo delle aree disponibili usando az account list-locations.
  • <YOUR_MYSQL_ADMIN_PASSWORD> e <YOUR_MYSQL_NON_ADMIN_PASSWORD>: password del server di database MySQL, che deve contenere almeno otto caratteri. La password deve contenere caratteri di tre delle categorie seguenti: lettere maiuscole, lettere minuscole, numeri (0-9) e caratteri non alfanumerici (!, $, #, % e così via).

Nota

Microsoft consiglia di usare il flusso di autenticazione più sicuro disponibile. Il flusso di autenticazione descritto in questa procedura, ad esempio per database, cache, messaggistica o servizi di intelligenza artificiale, richiede un livello di attendibilità molto elevato nell'applicazione e comporta rischi non presenti in altri flussi. Usare questo flusso solo quando le opzioni più sicure, ad esempio le identità gestite per le connessioni senza password o senza chiave, non sono valide. Per le operazioni del computer locale, preferire le identità utente per le connessioni senza password o senza chiave.

Successivamente, creare un gruppo di risorse:

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

Creare un'istanza di Database di Azure per MySQL e configurare l'utente amministratore

La prima cosa che si creerà è un server MySQL gestito con un utente amministratore.

Nota

Per informazioni più dettagliate sulla creazione di server MySQL, vedere Creare un server di Database di Azure per MySQL nel portale di Azure.

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

Configurare un database MySQL

Creare un nuovo database denominato demo con il comando seguente:

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

Configurare una regola del firewall per il server MySQL

Le istanze di Database di Azure per MySQL sono protette per impostazione predefinita. Includono un firewall che non consente alcuna connessione in ingresso.

È possibile ignorare questo passaggio se si usa Bash perché il comando ha già rilevato l'indirizzo flexible-server create IP locale e impostarlo nel server MySQL.

Se ci si connette al server MySQL da sottosistema Windows per Linux (WSL) in un computer Windows, è necessario aggiungere l'ID host WSL al firewall. Ottenere l'indirizzo IP del computer host eseguendo il comando seguente in WSL:

cat /etc/resolv.conf

Copiare l'indirizzo IP seguendo il termine nameserver, quindi usare il comando seguente per impostare una variabile di ambiente per l'indirizzo IP WSL:

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

Usare quindi il comando seguente per aprire il firewall del server all'app basata su 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

Creare un utente non amministratore di MySQL e concedere l'autorizzazione

Questo passaggio creerà un utente non amministratore e concederà tutte le autorizzazioni per il demo database.

Nota

Per altre informazioni dettagliate sulla creazione di utenti MySQL, vedere Creare utenti in Database di Azure per MySQL.

Creare prima di tutto uno script SQL denominato create_user.sql per la creazione di un utente non amministratore. Aggiungervi il contenuto seguente e salvarlo in locale:

Nota

Microsoft consiglia di usare il flusso di autenticazione più sicuro disponibile. Il flusso di autenticazione descritto in questa procedura, ad esempio per database, cache, messaggistica o servizi di intelligenza artificiale, richiede un livello di attendibilità molto elevato nell'applicazione e comporta rischi non presenti in altri flussi. Usare questo flusso solo quando le opzioni più sicure, ad esempio le identità gestite per le connessioni senza password o senza chiave, non sono valide. Per le operazioni del computer locale, preferire le identità utente per le connessioni senza password o senza chiave.

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

Usare quindi il comando seguente per eseguire lo script SQL per creare l'utente non amministratore:

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

A questo punto, usare il comando seguente per rimuovere il file di script SQL temporaneo:

rm create_user.sql

Creare un'applicazione Spring Boot reattiva

Per creare un'applicazione Spring Boot reattiva, si userà Spring Initializr. L'applicazione che verrà creata usa:

  • Spring Boot 2.7.11.
  • Le dipendenze seguenti: Spring Reactive Web (nota anche come Spring WebFlux) e Spring Data R2DBC.

Generare l'applicazione con Spring Initializr

Per generare l'applicazione, immettere quanto segue sulla riga di comando:

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 -

Aggiungere l'implementazione del driver MySQL reattivo

Aprire il file pom.xml del progetto generato per aggiungere il driver MySQL reattivo dal repository GitHub r2dbc-mysql.

Dopo la dipendenza spring-boot-starter-webflux aggiungere il frammento di codice seguente:

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

Configurare Spring Boot per l'uso di Database di Azure per MySQL

Aprire il file src/main/resources/application.properties e aggiungere:

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

Sostituire le $AZ_DATABASE_NAME variabili e $AZ_MYSQL_NON_ADMIN_PASSWORD con i valori configurati all'inizio di questo articolo.

Nota

Per prestazioni più elevate, la proprietà spring.r2dbc.url viene configurata per l'uso di un pool di connessioni tramite r2dbc-pool.

A questo punto dovrebbe essere possibile avviare l'applicazione usando il wrapper Maven fornito:

./mvnw spring-boot:run

Ecco uno screenshot dell'applicazione in esecuzione per la prima volta:

Screenshot dell'applicazione in esecuzione.

Creare lo schema del database

All'interno della classe DemoApplication principale configurare un nuovo bean Spring che creerà uno schema del database, usando il codice seguente:

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

Questo bean Spring usa un file denominato schema.sql, quindi creare il file nella cartella src/main/resources e aggiungere il testo seguente:

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

Arrestare l'applicazione in esecuzione e quindi riavviarla. L'applicazione userà ora il database demo creato in precedenza e creerà una todo tabella al suo interno.

./mvnw spring-boot:run

Ecco uno screenshot della tabella di database creata:

Screenshot della creazione della tabella di database.

Codice dell'applicazione

Aggiungere quindi il codice Java che userà R2DBC per archiviare e recuperare i dati dal server MySQL.

Creare una nuova classe Java Todo accanto alla classe DemoApplication usando il codice seguente:

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

Questa classe è un modello di dominio mappato alla tabella todo creata in precedenza.

Per gestire questa classe è necessario un repository. Definire una nuova interfaccia TodoRepository nello stesso pacchetto usando il codice seguente:

package com.example.demo;

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

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

Questo repository è un repository reattivo gestito da Spring Data R2DBC.

Completare l'applicazione creando un controller in grado di archiviare e recuperare dati. Implementare una classe TodoController nello stesso pacchetto e aggiungere il codice seguente:

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

Infine, arrestare l'applicazione e quindi riavviarla usando il comando seguente:

./mvnw spring-boot:run

Testare l'applicazione

Per testare l'applicazione, è possibile usare cURL.

Creare prima di tutto un elemento "todo" nel database con il comando seguente:

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

Questo comando restituirà l'elemento creato, come illustrato qui:

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

Recuperare quindi i dati usando una nuova richiesta cURL con il comando seguente:

curl http://127.0.0.1:8080

Questo comando restituirà l'elenco di elementi "todo", incluso quello creato, come illustrato qui:

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

Ecco uno screenshot di queste richieste cURL:

Screenshot del test cURL.

Complimenti. È stata creata un'applicazione Spring Boot completamente reattiva che usa R2DBC per archiviare e recuperare i dati da Database di Azure per MySQL.

Pulire le risorse

Per pulire tutte le risorse usate durante questa guida introduttiva, eliminare il gruppo di risorse usando il comando seguente:

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

Passaggi successivi

Per altre informazioni sulla distribuzione di un'applicazione Spring Data in Azure Spring Apps e sull'uso dell'identità gestita, vedere Esercitazione: Distribuire un'applicazione Spring in Azure Spring Apps con una connessione senza password a un database di Azure.

Per altre informazioni su Spring e Azure, passare al centro di documentazione di Spring in Azure.

Vedi anche

Per altre informazioni su Spring Data R2DBC, vedere la documentazione di riferimento di Spring.

Per altre informazioni sull'uso di Azure con Java, vedere Azure per sviluppatori Java e la documentazione relativa all'uso di Azure DevOps e Java.