The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

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 11+ instalado com 'JAVA_HOME' configurado adequadamente

  • Apache Maven 3.9.5

  • 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

In this guide, we are going to expose a simple Rest API to increment numbers by using the INCRBY command. Along the way, we’ll see how to use other Redis commands like GET, SET (from the string group), DEL and KEYS (from the key group).

Vamos utilizar a extensão Quarkus Redis para nos conectar e interagir com o Redis.

Solução

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.

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:

CLI
quarkus create app org.acme:redis-quickstart \
    --extension='redis-client,resteasy-reactive-jackson' \
    --no-code
cd redis-quickstart

Para criar um projeto Gradle, adicione a opção --gradle ou --gradle-kotlin-dsl.

Para obter mais informações sobre como instalar e usar a CLI do Quarkus, consulte o guia Quarkus CLI.

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.5.3:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=redis-quickstart \
    -Dextensions='redis-client,resteasy-reactive-jackson' \
    -DnoCode
cd redis-quickstart

Para criar um projeto Gradle, adicione a opção '-DbuildTool=gradle' ou '-DbuildTool=gradle-kotlin-dsl'.

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.

If you already have your Quarkus project configured, you can add the redis-client extension to your project by running the following command in your project base directory:

CLI
quarkus extension add redis-client
Maven
./mvnw quarkus:add-extension -Dextensions='redis-client'
Gradle
./gradlew addExtension --extensions='redis-client'

Isto irá adicionar o seguinte trecho no seu arquivo de build:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-redis-client</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-redis-client")

Criando o POJO Incremento

We are going to model our increments using the Increment POJO. Create the src/main/java/org/acme/redis/Increment.java file, with the following content:

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 IncrementoService

We are going to create an IncrementService class which will play the role of a Redis client. With this class, we’ll be able to perform the SET, GET , DEL, KEYS and INCRBY Redis commands.

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

If you followed the instructions, you should have the Redis server running. Then, you just need to run the application using:

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

Abra outro terminal e execute o comando curl http://localhost:8080/incrementos.

Interagindo com a aplicação

As we have seen above, the API exposes five Rest endpoints. In this section we are going to see how to initialise an increment, see the list of current increments, incrementing a value given its key, retrieving the current value of an increment, and finally deleting a key.

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

The above command should return ["first"] indicating that we have only one increment thus far.

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

At this point, Quarkus uses the Redis Dev Service to run a Redis server and configure the application. However, in production, you will run your own Redis (or used a Cloud offering).

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:

CLI
quarkus build
Maven
./mvnw install
Gradle
./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

You can also create a native executable from this application without making any source code changes. A native executable removes the dependency on the JVM: everything needed to run the application on the target platform is included in the executable, allowing the application to run with minimal resource overhead.

Compiling a native executable takes a bit longer, as GraalVM performs additional steps to remove unnecessary codepaths. Use the native profile to compile a native executable:

CLI
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.package.type=native

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.

Related content