Utiliser Spring Data R2DBC avec Azure Database pour MySQL

Cet article décrit la création d’un exemple d’application qui utilise Spring Data R2DBC pour stocker et récupérer des informations dans Azure Database pour MySQL en utilisant l’implémentation R2DBC pour MySQL du dépôt GitHub r2dbc-mysql.

R2DBC permet d’utiliser des API réactives avec les bases de données relationnelles classiques. Vous pouvez l’utiliser avec Spring WebFlux pour créer des applications Spring Boot entièrement réactives qui utilisent des API non bloquantes. Il offre une meilleure scalabilité que l’approche classique « un thread par connexion ».

Prérequis

Voir l’exemple d’application

Dans cet article, vous allez coder un exemple d’application. Si vous souhaitez aller plus vite, cette application est déjà codée et disponible sur https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-mysql.

Préparer l’environnement de travail

Tout d’abord, configurez certaines variables d’environnement en exécutant les commandes suivantes :

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>

Remplacez les espaces réservés par les valeurs suivantes, qui sont utilisées dans cet article :

  • <YOUR_DATABASE_NAME> : nom de votre serveur MySQL, qui doit être unique dans Azure.
  • <YOUR_AZURE_REGION>: région Azure que vous allez utiliser. Vous pouvez utiliser eastus par défaut, mais nous vous recommandons de configurer une région plus proche de l’endroit où vous vivez. Vous pouvez voir la liste complète des régions disponibles à l’aide az account list-locationsde .
  • <YOUR_MYSQL_ADMIN_PASSWORD> et <YOUR_MYSQL_NON_ADMIN_PASSWORD>: mot de passe de votre serveur de base de données MySQL, qui doit comporter au moins huit caractères. Il doit contenir des caractères de trois des catégories suivantes : Lettres majuscules, lettres minuscules, chiffres (0-9) et caractères non alphanumériques (comme !, $, #, %, etc.).

Créez ensuite un groupe de ressources :

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

Créer une instance Azure Database pour MySQL et configurer l’utilisateur administrateur

La première chose que vous allez créer est un serveur MySQL managé avec un utilisateur administrateur.

Remarque

Vous trouverez des informations plus détaillées sur la création de serveurs MySQL dans l’article Création d’un serveur Azure Database pour MySQL à l’aide du portail 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

Configurer une base de données MySQL

Créez une base de données nommée demo à l’aide de la commande suivante :

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

Configurer une règle de pare-feu pour votre serveur MySQL

Les instances Azure Database pour MySQL sont sécurisées par défaut. Elles ont un pare-feu qui n’autorise aucune connexion entrante.

Vous pouvez ignorer cette étape si vous utilisez Bash, car la commande flexible-server create a déjà détecté votre adresse IP locale et l’a définie sur le serveur MySQL.

Si vous vous connectez à votre serveur MySQL à partir de Sous-système Windows pour Linux (WSL) sur un ordinateur Windows, vous devez ajouter l’ID d’hôte WSL à votre pare-feu. Obtenez l’adresse IP de votre ordinateur hôte en exécutant la commande suivante dans WSL :

cat /etc/resolv.conf

Copiez l’adresse IP suivant le terme nameserver, puis utilisez la commande suivante pour définir une variable d’environnement pour l’adresse IP de WSL :

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

Ensuite, utilisez la commande suivante pour ouvrir le pare-feu du serveur sur votre application 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

Créer un utilisateur non-administrateur MySQL et accorder des autorisations

Cette étape crée un utilisateur non administrateur et lui accorde toutes les autorisations sur la demo base de données.

Remarque

Vous pouvez lire des informations plus détaillées sur la création d’utilisateurs MySQL dans Créer des utilisateurs dans Azure Database pour MySQL.

Tout d’abord, créez un script SQL appelé create_user.sql pour créer un utilisateur non administrateur. Ajoutez le contenu suivant et enregistrez-le localement :

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

Ensuite, utilisez la commande suivante pour exécuter le script SQL pour créer l’utilisateur non administrateur :

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

Utilisez maintenant la commande suivante pour supprimer le fichier de script SQL temporaire :

rm create_user.sql

Créer une application Spring Boot réactive

Pour créer une application Spring Boot réactive, nous allons utiliser Spring Initializr. L’application que nous allons créer utilise :

  • Spring Boot 2.7.11.
  • Les dépendances suivantes : Spring React Web (également appelé Spring WebFlux) et Spring Data R2DBC.

Générer l’application à l’aide de Spring Initializr

Générez cette application à l’aide de la ligne de commande en tapant :

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 -

Ajouter l’implémentation du pilote MySQL réactif

Ouvrez le fichier pom.xml du projet généré pour ajouter le pilote MySQL réactif à partir du dépôt r2dbc-mysql sur GitHub.

Après la dépendance spring-boot-starter-webflux, ajoutez l’extrait de code suivant :

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

Configurer Spring Boot pour qu’il utilise Azure Database pour MySQL

Ouvrez le fichier src/main/resources/application.properties et ajoutez :

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

Remplacez les $AZ_DATABASE_NAME variables et $AZ_MYSQL_NON_ADMIN_PASSWORD les valeurs que vous avez configurées au début de cet article.

Remarque

Pour de meilleures performances, la propriété spring.r2dbc.url est configurée de manière à utiliser un pool de connexions avec r2dbc-pool.

Vous devez maintenant être en mesure de démarrer votre application à l’aide du wrapper Maven fourni :

./mvnw spring-boot:run

Voici une capture d’écran de l’application s’exécutant pour la première fois :

Screenshot of the running application.

Créer le schéma de la base de données

Dans la classe principale DemoApplication, configurez un nouveau bean Spring qui créera le schéma de base de données, à l’aide du code suivant :

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

Ce bean Spring utilise un fichier nommé schema.sql. Créez ce fichier dans le dossier src/main/resources et ajoutez le texte suivant :

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

Arrêtez l’application en cours d’exécution, puis redémarrez-la. L’application utilise désormais la base de données demo que vous avez créée précédemment et crée une table todo dans cette base de données.

./mvnw spring-boot:run

Voici une capture d’écran de la table de base de données en cours de création :

Screenshot of the creation of the database table.

Coder l’application

Ensuite, ajoutez le code Java qui utilisera R2DBC pour stocker et récupérer des données à partir de votre serveur MySQL.

Créez une classe Java Todo parallèlement à la classe DemoApplication en utilisant le code suivant :

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

Cette classe est un modèle de domaine mappé sur la table todo que vous avez créée précédemment.

Pour gérer cette classe, vous avez besoin d’un référentiel. Définissez une nouvelle interface TodoRepository dans le même package en utilisant le code suivant :

package com.example.demo;

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

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

Ce dépôt est un dépôt réactif géré par Spring Data R2DBC.

Terminez l’application en créant un contrôleur pouvant stocker et récupérer des données. Implémentez une classe TodoController dans le même package, puis ajoutez le code suivant :

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

Pour finir, arrêtez l’application et redémarrez-la à l’aide de la commande suivante :

./mvnw spring-boot:run

Test de l’application

Pour tester l’application, vous pouvez utiliser cURL.

Tout d’abord, créez un élément « todo » dans la base de données à l’aide de la commande suivante :

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

Cette commande doit retourner l’élément créé, comme illustré ici :

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

Ensuite, récupérez les données à l’aide d’une nouvelle requête cURL avec la commande suivante :

curl http://127.0.0.1:8080

Cette commande retourne la liste des éléments « todo », y compris celui que vous avez créé, comme illustré ici :

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

Voici une capture d’écran de ces requêtes cURL :

Screenshot of the cURL test.

Félicitations ! Vous avez créé une application Spring Boot entièrement réactive, qui utilise R2DBC pour stocker et récupérer des données à partir d’Azure Database pour MySQL.

Nettoyer les ressources

Pour propre toutes les ressources utilisées pendant ce guide de démarrage rapide, supprimez le groupe de ressources à l’aide de la commande suivante :

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

Étapes suivantes

Pour en savoir plus sur le déploiement d’une application Spring Data sur Azure Spring Apps et l’utilisation d’une identité managée, consultez Tutoriel : Déployer une application Spring sur Azure Spring Apps avec une connexion sans mot de passe à une base de données Azure.

Pour en savoir plus sur Spring et Azure, poursuivez vers le centre de documentation Spring sur Azure.

Voir aussi

Pour plus d’informations sur Spring Data R2DBC, consultez la documentation de référence de Spring.

Pour plus d’informations sur l’utilisation d’Azure avec Java, consultez Azure pour les développeurs Java et Utilisation d’Azure DevOps et Java.