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

Extensão do Quarkus para a API do Spring Cache

Embora os usuários sejam incentivados a usar as anotações do Quarkus para armazenamento em cache , o Quarkus fornece uma camada de compatibilidade para as anotações do Spring Cache na forma da extensão spring-cache .

Este guia explica como um aplicativo Quarkus pode aproveitar as conhecidas anotações do Spring Cache para habiblitar o cache de dados do aplicativo para seus beans Spring.

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)

  • Alguma familiaridade com a extensão Spring DI

Criar o projeto Maven

Primeiro, precisamos de um novo projeto. Crie um novo projeto com o seguinte comando:

CLI
quarkus create app org.acme:spring-cache-quickstart \
    --extension='rest,spring-di,spring-cache' \
    --no-code
cd spring-cache-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.16.3:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=spring-cache-quickstart \
    -Dextensions='rest,spring-di,spring-cache' \
    -DnoCode
cd spring-cache-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=spring-cache-quickstart"'

Esse comando gera um projeto que importa as extensões spring-cache e spring-di .

Se você já tem seu projeto Quarkus configurado, você pode adicionar a extensão spring-cache para seu projeto executando o seguinte comando no diretório base do projeto:

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

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

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

Criando a API REST

Vamos começar criando um serviço que simulará uma chamada extremamente lenta para um serviço meteorológico externo. Crie src/main/java/org/acme/spring/cache/WeatherForecastService.java com o seguinte conteúdo:

package org.acme.spring.cache;

import java.time.LocalDate;

import org.springframework.stereotype.Component;

@Component
public class WeatherForecastService {

    public String getDailyForecast(LocalDate date, String city) {
        try {
            Thread.sleep(2000L); (1)
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return date.getDayOfWeek() + " will be " + getDailyResult(date.getDayOfMonth() % 4) + " in " + city;
    }

    private String getDailyResult(int dayOfMonthModuloFour) {
        switch (dayOfMonthModuloFour) {
            case 0:
                return "sunny";
            case 1:
                return "cloudy";
            case 2:
                return "chilly";
            case 3:
                return "rainy";
            default:
                throw new IllegalArgumentException();
        }
    }
}
1 É daí que vem a lentidão.

Também precisamos de uma classe que contenha a resposta enviada aos usuários quando eles solicitarem a previsão do tempo para os próximos três dias. Crie src/main/java/org/acme/spring/cache/WeatherForecast.java dessa forma:

package org.acme.spring.cache;

import java.util.List;

public class WeatherForecast {

    private List<String> dailyForecasts;

    private long executionTimeInMs;

    public WeatherForecast(List<String> dailyForecasts, long executionTimeInMs) {
        this.dailyForecasts = dailyForecasts;
        this.executionTimeInMs = executionTimeInMs;
    }

    public List<String> getDailyForecasts() {
        return dailyForecasts;
    }

    public long getExecutionTimeInMs() {
        return executionTimeInMs;
    }
}

Agora, precisamos criar a classe src/main/java/org/acme/spring/cache/WeatherForecastResource.java para usar o serviço e responder:

package org.acme.spring.cache;

import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.jboss.resteasy.reactive.RestQuery;

@Path("/weather")
public class WeatherForecastResource {

    @Inject
    WeatherForecastService service;

    @GET
    public WeatherForecast getForecast(@RestQuery String city, @RestQuery long daysInFuture) { (1)
        long executionStart = System.currentTimeMillis();
        List<String> dailyForecasts = Arrays.asList(
                service.getDailyForecast(LocalDate.now().plusDays(daysInFuture), city),
                service.getDailyForecast(LocalDate.now().plusDays(daysInFuture + 1L), city),
                service.getDailyForecast(LocalDate.now().plusDays(daysInFuture + 2L), city)
        );
        long executionEnd = System.currentTimeMillis();
        return new WeatherForecast(dailyForecasts, executionEnd - executionStart);
    }
}
1 Se o parâmetro de consulta daysInFuture for omitido, a previsão do tempo para três dias começará a partir do dia atual. Caso contrário, ela começará a partir do dia atual mais o valor daysInFuture .

Já está tudo pronto! Vamos verificar se tudo está funcionando.

Primeiro, execute o aplicativo usando:

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

Em seguida, chame o http://localhost:8080/weather?city=Raleigh de um navegador. Após seis longos segundos, o aplicativo responderá alguma coisa parecido com isto:

{"dailyForecasts":["MONDAY will be cloudy in Raleigh","TUESDAY will be chilly in Raleigh","WEDNESDAY will be rainy in Raleigh"],"executionTimeInMs":6001}

O conteúdo da resposta pode variar dependendo do dia em que você executar o código.

Você pode tentar ligar para a mesma URL várias vezes, mas ele sempre levará seis segundos para responder.

Ativação do cache

Agora que seu aplicativo Quarkus está em funcionamento, vamos melhorar muito seu tempo de resposta armazenando em cache as respostas do serviço meteorológico externo. Atualize a classe WeatherForecastService da seguinte forma:

package org.acme.cache;

import java.time.LocalDate;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class WeatherForecastService {

    @Cacheable("weather-cache") (1)
    public String getDailyForecast(LocalDate date, String city) {
        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return date.getDayOfWeek() + " will be " + getDailyResult(date.getDayOfMonth() % 4) + " in " + city;
    }

    private String getDailyResult(int dayOfMonthModuloFour) {
        switch (dayOfMonthModuloFour) {
            case 0:
                return "sunny";
            case 1:
                return "cloudy";
            case 2:
                return "chilly";
            case 3:
                return "rainy";
            default:
                throw new IllegalArgumentException();
        }
    }
}
1 Adicionamos apenas essa anotação (e a importação associada, é claro).

Vamos tentar chamar http://localhost:8080/weather?city=Raleigh novamente. Você ainda está esperando muito tempo antes de receber uma resposta. Isso é normal, pois o servidor acabou de ser reiniciado e o cache estava vazio.

Espere um segundo! O servidor reiniciou após a atualização do WeatherForecastService ? Sim, esse é um dos incríveis recursos do Quarkus para desenvolvedores, chamado live coding .

Agora que o cache foi carregado durante a chamada anterior, tente chamar a mesma URL. Dessa vez, você deve obter uma resposta super rápida com um valor executionTimeInMs próximo de 0.

Vamos ver o que acontece se começarmos a partir de um dia no futuro usando o http://localhost:8080/weather?city=Raleigh&daysInFuture=1 URL. Você deve obter uma resposta dois segundos depois, pois dois dos dias solicitados já foram carregados no cache.

Você também pode tentar chamar a mesma URL com uma cidade diferente e ver o cache em ação novamente. A primeira chamada levará seis segundos e as seguintes serão respondidas imediatamente.

Parabéns! Você acabou de adicionar o cache de dados do aplicativo a sua aplicação Quarkus com uma única linha de código!

Recursos suportados

O Quarkus oferece compatibilidade com as seguintes anotações do Spring Cache:

  • @Cacheable

  • @CachePut

  • @CacheEvict

Observe que, nesta primeira versão da extensão de anotações do Spring Cache, nem todos os recursos dessas anotações são suportados (com os erros apropriados sendo registrados ao tentar usar um recurso não suportado). No entanto, recursos adicionais estão planejados para versões futuras.

Conteúdo Relacionado