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 preview. In preview, backward compatibility and presence in the ecosystem is not guaranteed. Specific improvements might require changing configuration or APIs, and plans to become stable are under way. Feedback is welcome on our mailing list or as issues in our GitHub issue tracker. 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+ installed with
JAVA_HOME
configured appropriately -
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.