Usar o Spring Data R2DBC com o Banco de Dados do Azure para MySQL
Este artigo demonstra como criar um aplicativo de exemplo que usa o Spring Data R2DBC para armazenar e recuperar informações no Banco de Dados do Azure para MySQL usando a implementação do R2DBC para MySQL do repositório do GitHub r2dbc-mysql.
O R2DBC traz APIs reativas para bancos de dados relacionais tradicionais. Você pode usá-lo com o Spring WebFlux para criar aplicativos Spring Boot totalmente reativos que usam APIs sem bloqueio. Ele fornece melhor escalabilidade do que a abordagem clássica "um thread por conexão".
Pré-requisitos
Uma assinatura do Azure – crie uma gratuitamente.
Java Development Kit (JDK), versão 8 ou superior.
O cURL ou um utilitário HTTP semelhante para testar a funcionalidade.
Consulte o aplicativo de exemplo
Neste artigo, você codificará um aplicativo de exemplo. Caso você queira adiantar o processo, esse aplicativo já está codificado e disponível em https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-mysql.
Preparar o ambiente de trabalho
Primeiro, configure algumas variáveis de ambiente executando os seguintes comandos:
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>
Substitua os espaços reservados pelos seguintes valores, que são usados em todo este artigo:
<YOUR_DATABASE_NAME>
: o nome do servidor MySQL, que deve ser exclusivo no Azure.<YOUR_AZURE_REGION>
: A região do Azure que você usará. Você pode usareastus
por padrão, mas é recomendável configurar uma região mais próxima de onde você mora. Você pode ver a lista completa de regiões disponíveis usandoaz account list-locations
o .<YOUR_MYSQL_ADMIN_PASSWORD>
e<YOUR_MYSQL_NON_ADMIN_PASSWORD>
: A senha do seu servidor de banco de dados MySQL, que deve ter no mínimo oito caracteres. Os caracteres deveriam ser de três das seguintes categorias: Letras maiúsculas, letras minúsculas, números (0-9) e caracteres não alfanuméricos (!, $, #, % e assim por diante).
Observação
A Microsoft recomenda usar o fluxo de autenticação mais seguro disponível. O fluxo de autenticação descrito neste procedimento, como bancos de dados, caches, mensagens ou serviços de IA, requer um grau muito alto de confiança no aplicativo e traz riscos não presentes em outros fluxos. Use esse fluxo somente quando opções mais seguras, como identidades gerenciadas para conexões sem senha ou sem chave, não forem viáveis. Para operações de computador local, prefira identidades de usuário para conexões sem senha ou sem chave.
Em seguida, crie um grupo de recursos:
az group create \
--name $AZ_RESOURCE_GROUP \
--location $AZ_LOCATION \
--output tsv
Criar uma instância do Banco de Dados do Azure para MySQL e configurar o usuário administrador
A primeira coisa que você criará é um servidor MySQL gerenciado com um usuário administrador.
Observação
Você pode ler informações mais detalhadas sobre como criar servidores MySQL em Criar um servidor de Banco de Dados do Azure para MySQL usando o portal do 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
Configurar um banco de dados MySQL
Crie um banco de dados chamado demo
usando o seguinte comando:
az mysql flexible-server db create \
--resource-group $AZ_RESOURCE_GROUP \
--database-name demo \
--server-name $AZ_DATABASE_NAME \
--output tsv
Configurar uma regra de firewall para o servidor MySQL
As instâncias do Banco de Dados do Azure para MySQL são protegidas por padrão. Elas têm um firewall que não permite nenhuma conexão de entrada.
Você pode ignorar esta etapa se estiver usando o Bash porque o comando flexible-server create
já detectou seu endereço IP local e o definiu no servidor MySQL.
Se você estiver se conectando ao servidor MySQL do WSL (Subsistema do Windows para Linux) em um computador Windows, será necessário adicionar a ID do host WSL ao firewall. Obtenha o endereço IP do computador host executando o seguinte comando no WSL:
cat /etc/resolv.conf
Copie o endereço IP após o termo nameserver
e use o seguinte comando para definir uma variável de ambiente para o endereço IP WSL:
export AZ_WSL_IP_ADDRESS=<the-copied-IP-address>
Em seguida, use o seguinte comando para abrir o firewall do servidor para seu aplicativo baseado em 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
Criar um usuário não administrador do MySQL e conceder permissão
Esta etapa criará um usuário não administrador e concederá todas as permissões no banco de dados demo
a ele.
Observação
Você pode obter informações mais detalhadas sobre como criar usuários do MySQL em Criar usuários no Banco de Dados do Azure para MySQL.
Primeiro, crie um script SQL chamado create_user.sql para criar um usuário não administrador. Adicione o seguinte conteúdo e salve-o localmente:
Observação
A Microsoft recomenda usar o fluxo de autenticação mais seguro disponível. O fluxo de autenticação descrito neste procedimento, como bancos de dados, caches, mensagens ou serviços de IA, requer um grau muito alto de confiança no aplicativo e traz riscos não presentes em outros fluxos. Use esse fluxo somente quando opções mais seguras, como identidades gerenciadas para conexões sem senha ou sem chave, não forem viáveis. Para operações de computador local, prefira identidades de usuário para conexões sem senha ou sem chave.
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
Em seguida, use o seguinte comando para executar o script SQL para criar o usuário não administrador:
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
Agora, use o seguinte comando para remover o arquivo de script SQL temporário:
rm create_user.sql
Criar um aplicativo Spring Boot reativo
Para criar um aplicativo Spring Boot reativo, usaremos o Spring Initializr. O aplicativo que criaremos usa:
- Bota de mola 2.7.11.
- As seguintes dependências: Spring Reactive Web (também conhecido como Spring WebFlux) e Spring Data R2DBC.
Gerar o aplicativo usando o Spring Initializr
Gere o aplicativo na linha de comando ao digitar:
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 -
Adicionar a implementação do driver MySQL reativo
Abra o arquivo pom.xml do projeto gerado para adicionar o driver MySQL reativo do repositório no GitHub r2dbc-mysql.
Após a dependência spring-boot-starter-webflux
, adicione o seguinte snippet de código:
<dependency>
<groupId>io.asyncer</groupId>
<artifactId>r2dbc-mysql</artifactId>
<version>0.9.1</version>
</dependency>
Configurar o Spring Boot para usar o Banco de Dados do Azure para MySQL
Abra o arquivo src/main/resources/application.properties e adicione:
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
Substitua as $AZ_DATABASE_NAME
variáveis e $AZ_MYSQL_NON_ADMIN_PASSWORD
pelos valores que você configurou no início deste artigo.
Observação
Para obter um melhor desempenho, a propriedade spring.r2dbc.url
está configurada para usar um pool de conexões usando r2dbc-pool.
Agora, você deveria conseguir iniciar o aplicativo usando o wrapper do Maven fornecido:
./mvnw spring-boot:run
Aqui está uma captura de tela do aplicativo em execução pela primeira vez:
Criar o esquema de banco de dados
Dentro da classe principal DemoApplication
, configure um novo bean do Spring que criará um esquema de banco de dados, usando o seguinte código:
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;
}
}
Esse bean do Spring usa um arquivo chamado schema.sql; portanto, crie esse arquivo na pasta src/main/resources e adicione o seguinte texto:
DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);
Pare o aplicativo em execução e inicie-o novamente. O aplicativo agora usará o banco de dados demo
que você criou anteriormente e criará uma tabela todo
dentro dele.
./mvnw spring-boot:run
Aqui está uma captura de tela da tabela do banco de dados enquanto está sendo criada:
Codificar o aplicativo
Em seguida, adicione o código Java que usará o R2DBC para armazenar e recuperar dados do servidor MySQL.
Crie uma classe Java Todo
ao lado da classe DemoApplication
usando o seguinte código:
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;
}
}
Essa classe é um modelo de domínio mapeado na tabela de todo
que você criou anteriormente.
Para gerenciar essa classe, você precisará de um repositório. Defina uma nova interface TodoRepository
no mesmo pacote usando o seguinte código:
package com.example.demo;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
public interface TodoRepository extends ReactiveCrudRepository<Todo, Long> {
}
Esse repositório é um repositório reativo que o Spring Data R2DBC gerencia.
Conclua o aplicativo criando um controlador que pode armazenar e recuperar dados. Implemente uma classe TodoController
no mesmo pacote e adicione o seguinte código:
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();
}
}
Por fim, pare o aplicativo e inicie-o novamente usando o seguinte comando:
./mvnw spring-boot:run
Testar o aplicativo
Para testar o aplicativo, você pode usar cURL.
Primeiro, crie um item "todo" no banco de dados usando o seguinte comando:
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
Este comando deverá retornar o item criado, conforme mostrado aqui:
{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}
Em seguida, recupere os dados usando uma nova solicitação do cURL com o seguinte comando:
curl http://127.0.0.1:8080
Esse comando retornará a lista de itens "todo", incluindo o item que você criou, conforme mostrado aqui:
[{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}]
Aqui está uma captura de tela dessas solicitações cURL:
Parabéns! Você criou um aplicativo Spring Boot totalmente reativo que usa o R2DBC para armazenar e recuperar dados do Banco de Dados do Azure para MySQL.
Limpar os recursos
Para limpar todos os recursos usados durante este início rápido, exclua o grupo de recursos usando o seguinte comando:
az group delete \
--name $AZ_RESOURCE_GROUP \
--yes
Próximas etapas
Para saber mais sobre como implantar um aplicativo Spring Data no Azure Spring Apps e usar a identidade gerenciada, consulte Tutorial: Implantar um aplicativo Spring no Azure Spring Apps com uma conexão sem senha com um banco de dados do Azure.
Para saber mais sobre o Spring e o Azure, continue no Spring no Centro de Documentação do Azure.
Confira também
Para obter mais informações sobre o Spring Data R2DBC, confira a documentação de referência do Spring.
Para obter mais informações sobre como usar o Azure com o Java, confira Azure para desenvolvedores Java e Trabalhar com o Azure DevOps e com o Java.