Usando o Cliente Redis
Este guia demonstra como a sua aplicação Quarkus pode se conectar a um servidor Redis utilizando a extensão Redis Client.
Essa tecnologia é considerada stable. Being stable, backward compatibility and presence in the ecosystem are taken very seriously. Para obter uma lista completa de possíveis status, consulte nosso FAQ. |
Pré-requisitos
Para concluir este guia, você precisa:
-
Cerca de 15 minutos
-
Um IDE
-
JDK 17+ instalado com
JAVA_HOME
configurado corretamente -
Apache Maven 3.9.9
-
Opcionalmente, o Quarkus CLI se você quiser usá-lo
-
Opcionalmente, Mandrel ou GraalVM instalado e configurado apropriadamente se você quiser criar um executável nativo (ou Docker se você usar uma compilação de contêiner nativo)
-
Um ambiente Docker funcional
Arquitetura
Neste guia, vamos expor uma API Rest simples para incrementar números usando o comando INCRBY . Ao longo do caminho, veremos como usar outros comandos do Redis, como GET
, SET
(do grupo de strings), DEL
e KEYS
(do grupo de chaves).
Vamos utilizar a extensão Quarkus Redis para nos conectar e interagir com o Redis.
Solução
Recomendamos que siga as instruções nas seções seguintes e crie a aplicação passo a passo. No entanto, você pode ir diretamente para o exemplo completo.
Clone o repositório Git: git clone https://github.com/quarkusio/quarkus-quickstarts.git
, ou baixe um arquivo.
A solução está localizada no diretório redis-quickstart
.
Criando o projeto Maven
Primeiro, precisamos de um novo projeto. Crie um novo projeto com o seguinte comando:
Para usuários do Windows:
-
Se estiver usando cmd, (não use barra invertida '\' e coloque tudo na mesma linha)
-
Se estiver usando o Powershell, envolva os parâmetros '-D' entre aspas duplas, por exemplo, '"-DprojectArtifactId=redis-quickstart"'
Este comando gera um novo projeto, importando a extensão Redis.
Se já tiver o projeto Quarkus configurado, você pode adicionar a extensão redis-client
ao projeto executando o seguinte comando no diretório base do projeto:
quarkus extension add redis-client
./mvnw quarkus:add-extension -Dextensions='redis-client'
./gradlew addExtension --extensions='redis-client'
Isto irá adicionar o seguinte trecho no seu arquivo de build:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-redis-client</artifactId>
</dependency>
implementation("io.quarkus:quarkus-redis-client")
Criando o POJO Incremento
Vamos modelar nossos incrementos usando o POJO Increment
. Crie o arquivo src/main/java/org/acme/redis/Increment.java
, com o seguinte conteúdo:
package org.acme.redis;
public class Increment {
public String key; (1)
public long value; (2)
public Increment(String key, long value) {
this.key = key;
this.value = value;
}
public Increment() {
}
}
1 | A variável chave que será utilizada como chave do Redis |
2 | A variável valor que será o valor mantido pela chave Redis |
Criando o Serviço de Incremento
Vamos criar uma classe IncrementService
que desempenhará o papel de um cliente Redis. Com essa classe, poderemos executar os comandos Redis SET
, GET
, DEL
, KEYS
e INCRBY
.
Criar o arquivo src/main/java/org/acme/redis/IncrementoService.java
, com o seguinte conteúdo:
package org.acme.redis;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import io.quarkus.redis.datasource.ReactiveRedisDataSource;
import io.quarkus.redis.datasource.RedisDataSource;
import io.quarkus.redis.datasource.keys.KeyCommands;
import io.quarkus.redis.datasource.keys.ReactiveKeyCommands;
import io.quarkus.redis.datasource.string.StringCommands;
import io.smallrye.mutiny.Uni;
@ApplicationScoped
public class IncrementService {
// This quickstart demonstrates both the imperative
// and reactive Redis data sources
// Regular applications will pick one of them.
private ReactiveKeyCommands<String> keyCommands; (1)
private ValueCommands<String, Long> countCommands; (2)
public IncrementService(RedisDataSource ds, ReactiveRedisDataSource reactive) { (3)
countCommands = ds.value(Long.class); (4)
keyCommands = reactive.key(); (5)
}
long get(String key) {
Long value = countCommands.get(key); (6)
if (value == null) {
return 0L;
}
return value;
}
void set(String key, Long value) {
countCommands.set(key, value); (7)
}
void increment(String key, Long incrementBy) {
countCommands.incrby(key, incrementBy); (8)
}
Uni<Void> del(String key) {
return keyCommands.del(key) (9)
.replaceWithVoid();
}
Uni<List<String>> keys() {
return keyCommands.keys("*"); (10)
}
}
1 | O campo utilizado para manipular chaves |
2 | O campo utilizado para manipular o contador |
3 | Injeta os datasources imperativo e reativo |
4 | Recuperar os comandos para manipular os contadores |
5 | Recuperar os comandos para manipular as chaves |
6 | Recupera o valor associado à chave indicada. Se null , retorna 0. |
7 | Define o valor associado a uma determinada chave |
8 | Incrementa o valor associado à chave indicada |
9 | Exclui uma chave (e o respetivo valor associado) |
10 | Lista todas as chaves |
Criando o recurso de incremento IncrementoResource
Criar o arquivo src/main/java/org/acme/redis/IncrementoResource.java
, com o seguinte conteúdo:
package org.acme.redis;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.DELETE;
import java.util.List;
import io.smallrye.mutiny.Uni;
@Path("/increments")
public class IncrementResource {
@Inject
IncrementService service;
@GET
public Uni<List<String>> keys() {
return service.keys();
}
@POST
public Increment create(Increment increment) {
service.set(increment.key, increment.value);
return increment;
}
@GET
@Path("/{key}")
public Increment get(String key) {
return new Increment(key, service.get(key));
}
@PUT
@Path("/{key}")
public void increment(String key, long value) {
service.increment(key, value);
}
@DELETE
@Path("/{key}")
public Uni<Void> delete(String key) {
return service.del(key);
}
}
Criando a classe de teste
Edite o arquivo pom.xml
para adicionar a seguinte dependência:
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
Crie o arquivo src/test/java/org/acme/redis/IncrementoResourceTest.java
com o seguinte conteúdo:
package org.acme.redis;
import static org.hamcrest.Matchers.is;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
import static io.restassured.RestAssured.given;
import io.restassured.http.ContentType;
@QuarkusTest
public class IncrementResourceTest {
@Test
public void testRedisOperations() {
// verify that we have nothing
given()
.accept(ContentType.JSON)
.when()
.get("/increments")
.then()
.statusCode(200)
.body("size()", is(0));
// create a first increment key with an initial value of 0
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.body("{\"key\":\"first-key\",\"value\":0}")
.when()
.post("/increments")
.then()
.statusCode(200)
.body("key", is("first-key"))
.body("value", is(0));
// create a second increment key with an initial value of 10
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.body("{\"key\":\"second-key\",\"value\":10}")
.when()
.post("/increments")
.then()
.statusCode(200)
.body("key", is("second-key"))
.body("value", is(10));
// increment first key by 1
given()
.contentType(ContentType.JSON)
.body("1")
.when()
.put("/increments/first-key")
.then()
.statusCode(204);
// verify that key has been incremented
given()
.accept(ContentType.JSON)
.when()
.get("/increments/first-key")
.then()
.statusCode(200)
.body("key", is("first-key"))
.body("value", is(1));
// increment second key by 1000
given()
.contentType(ContentType.JSON)
.body("1000")
.when()
.put("/increments/second-key")
.then()
.statusCode(204);
// verify that key has been incremented
given()
.accept(ContentType.JSON)
.when()
.get("/increments/second-key")
.then()
.statusCode(200)
.body("key", is("second-key"))
.body("value", is(1010));
// verify that we have two keys in registered
given()
.accept(ContentType.JSON)
.when()
.get("/increments")
.then()
.statusCode(200)
.body("size()", is(2));
// delete first key
given()
.accept(ContentType.JSON)
.when()
.delete("/increments/first-key")
.then()
.statusCode(204);
// verify that we have one key left after deletion
given()
.accept(ContentType.JSON)
.when()
.get("/increments")
.then()
.statusCode(200)
.body("size()", is(1));
// delete second key
given()
.accept(ContentType.JSON)
.when()
.delete("/increments/second-key")
.then()
.statusCode(204);
// verify that there is no key left
given()
.accept(ContentType.JSON)
.when()
.get("/increments")
.then()
.statusCode(200)
.body("size()", is(0));
}
}
Executando a aplicação
Se você seguiu as instruções, deverá ter o servidor Redis em execução. Em seguida, você só precisa executar a aplicação usando:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
Abra outro terminal e execute o comando curl http://localhost:8080/incrementos
.
Interagindo com a aplicação
Como vimos acima, a API expõe cinco endpoints Rest. Nesta seção, veremos como inicializar um incremento, ver a lista de incrementos atuais, incrementar um valor com sua chave, recuperar o valor atual de um incremento e, por fim, excluir uma chave.
Criando um novo incremento
curl -X POST -H "Content-Type: application/json" -d '{"key":"first","value":10}' http://localhost:8080/increments (1)
1 | Criamos o primeiro incremento, com a chave primeira e um valor inicial de 10 . |
A execução do comando acima deve retornar o resultado abaixo:
{
"key": "first",
"value": 10
}
Ver as chaves atuais de incrementos
Para ver a lista de chaves de incrementos atuais, execute o seguinte comando:
curl http://localhost:8080/increments
O comando acima deve retornar ["first"]
indicando que temos apenas um incremento até o momento.
Recuperar um novo incremento
Para recuperar um incremento utilizando a sua chave, teremos de executar o comando abaixo:
curl http://localhost:8080/increments/first (1)
1 | Ao executar este comando, deverá obter o seguinte resultado: |
{
"key": "first",
"value": 10
}
Incrementa um valor dada a sua chave
Para incrementar um valor, execute o seguinte comando:
curl -X PUT -H "Content-Type: application/json" -d '27' http://localhost:8080/increments/first (1)
1 | Incrementa o valor primeira em 27. |
Agora, ao executar o comando curl http://localhost:8080/incrementos/primeira
deve retornar o seguinte resultado:
{
"key": "first",
"value": 37 (1)
}
1 | Vemos que o valor da chave primeira é agora 37 que é exatamente o resultado de 10 + 27 . |
Excluindo uma chave
Utilize o comando abaixo, para excluir um incremento dada a sua chave.
curl -X DELETE http://localhost:8080/increments/first (1)
1 | Excluir o incremento primeira . |
Agora, ao executar o comando curl http://localhost:8080/incrementos
deve retornar uma lista vazia []
Configuração para produção
Neste ponto, o Quarkus usa o Redis Dev Service para executar um servidor Redis e configurar a aplicação. No entanto, em produção, você executará seu próprio Redis (ou usará uma oferta de nuvem).
Vamos iniciar um servidor Redis na porta 6379 usando:
docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name redis_quarkus_test -p 6379:6379 redis:5.0.6
Em seguida, abra o arquivo src/main/resources/application.properties
e adicione:
%prod.quarkus.redis.hosts=redis://localhost:6379
Empacotando e execução no modo JVM
Você pode executar a aplicação como um arquivo jar convencional.
Em primeiro lugar, temos que empacotar a aplicação:
quarkus build
./mvnw install
./gradlew build
Este comando iniciará uma instância Redis para executar os testes. |
Em seguida, execute:
java -jar target/quarkus-app/quarkus-run.jar
Executando em modo nativo
Você também pode criar um executável nativo a partir dessa aplicação sem fazer nenhuma alteração no código-fonte. Um executável nativo elimina a dependência do JVM: tudo o que é necessário para executar o aplicativo na plataforma de destino está incluído no executável, permitindo que o aplicativo seja executado com o mínimo de sobrecarga de recursos.
A compilação de um executável nativo demora um pouco mais, pois o GraalVM executa etapas adicionais para remover caminhos de código desnecessários. Use o perfil native
para compilar um executável nativo:
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.native.enabled=true
Quando a compilação estiver concluída, pode rodar o executável com:
./target/redis-quickstart-1.0.0-SNAPSHOT-runner
Indo mais longe
Para saber mais sobre a extensão Quarkus Redis, consulte o guia de referência da extensão Redis.