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:
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:
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
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:
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
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:
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
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:
quarkus build --native
./mvnw install -Dnative
./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.