新聞中心
本指南演練了使用阿帕奇大地的數(shù)據(jù)管理系統(tǒng),用于緩存應用程序代碼中的某些調用。

創(chuàng)新互聯(lián)服務項目包括張灣網(wǎng)站建設、張灣網(wǎng)站制作、張灣網(wǎng)頁制作以及張灣網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,張灣網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到張灣省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!
有關Apache Geode概念和從Apache Geode訪問數(shù)據(jù)的更多一般知識,請閱讀指南,使用 Apache Geode 訪問數(shù)據(jù)。
您將構建的內(nèi)容
您將構建一個服務,該服務從CloudFoundry托管的報價服務請求報價,并將其緩存在Apache Geode中。
然后,您將看到再次獲取相同的報價消除了對報價服務的昂貴調用,因為Spring的緩存抽象由Apache Geode支持,將用于緩存結果,給定相同的請求。
報價服務位于:
https://quoters.apps.pcfone.io。
報價服務具有以下 API:
GET /api - get all quotes
GET /api/random - get random quote
GET /api/{id} - get specific quote
您將需要什么
- 約15分鐘。
- 喜歡的文本編輯器或 IDE。
- JDK 1.8或更高版本。
- 格拉德爾 4+或梅文 3.2+。
- 您還可以將代碼直接導入到 IDE 中:
- 彈簧工具套件 (STS)。
- IntelliJ IDEA。
如何完成本指南
像大多數(shù)春天一樣入門指南,您可以從頭開始并完成每個步驟,也可以繞過您已經(jīng)熟悉的基本設置步驟。無論哪種方式,你最終都會得到工作代碼。
要從頭開始,請轉到從 Spring Initializr 開始。
要跳過基礎知識,請執(zhí)行以下操作:
- 下載并解壓縮本指南的源存儲庫,或使用Git:git clone 。 https://github.com/spring-guides/gs-caching-gemfire.git。
- 光盤成gs-caching-gemfire/initial。
- 跳到創(chuàng)建用于提取數(shù)據(jù)的可綁定對象。
完成后,您可以根據(jù) 中的代碼檢查結果。
gs-caching-gemfire/complete。
從 Spring Initializr 開始
對于所有Spring應用程序,您應該從Spring Initializr.Spring Initializr提供了一種快速的方法來提取應用程序所需的所有依賴項,并為您完成許多設置。此示例需要"Apache Geode 的 Spring for Apache Geode"依賴項。
以下清單顯示了使用 Maven 時的示例文件:pom.xml。
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.5.6
org.springframework
gs-caching-gemfire
0.1.0
1.2.0.RELEASE
javax.cache
cache-api
runtime
org.springframework.boot
spring-boot-starter
org.springframework.data
spring-data-geode
com.fasterxml.jackson.core
jackson-databind
org.projectlombok
lombok
org.springframework.shell
spring-shell
${spring-shell.version}
runtime
org.springframework.boot
spring-boot-maven-plugin
以下清單顯示了使用 Gradle 時的示例文件:build.gradle。
plugins {
id 'org.springframework.boot' version '2.5.6'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'io.freefair.lombok' version '6.3.0'
id 'java'
}
apply plugin: 'eclipse'
apply plugin: 'idea'
group = "org.springframework"
version = "0.1.0"
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter"
implementation "org.springframework.data:spring-data-geode"
implementation "com.fasterxml.jackson.core:jackson-databind"
implementation "org.projectlombok:lombok"
runtimeOnly "javax.cache:cache-api"
runtimeOnly "org.springframework.shell:spring-shell:1.2.0.RELEASE"
}
創(chuàng)建用于提取數(shù)據(jù)的可綁定對象
現(xiàn)在,您已經(jīng)設置了項目并生成系統(tǒng),您可以專注于定義捕獲從 Quote 服務提取引號(數(shù)據(jù))所需的位所需的域對象。
src/main/java/hello/Quote.java。
package hello;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.springframework.util.ObjectUtils;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@SuppressWarnings("unused")
public class Quote {
private Long id;
private String quote;
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Quote)) {
return false;
}
Quote that = (Quote) obj;
return ObjectUtils.nullSafeEquals(this.getId(), that.getId());
}
@Override
public int hashCode() {
int hashValue = 17;
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(getId());
return hashValue;
}
@Override
public String toString() {
return getQuote();
}
}COPY
域類具有 和 屬性。這些是您將在本指南中進一步收集的兩個主要屬性。通過使用QuoteidquoteQuote龍目島項目。
此外,還會捕獲報價服務在報價請求中發(fā)送的響應的整個有效負載。它包括請求的(又名 )以及 .此類還使用
QuoteQuoteResponsestatustypequote龍目島項目以簡化實現(xiàn)。
src/main/java/hello/QuoteResponse.java。
package hello;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class QuoteResponse {
@JsonProperty("value")
private Quote quote;
@JsonProperty("type")
private String status;
@Override
public String toString() {
return String.format("{ @type = %1$s, quote = '%2$s', status = %3$s }",
getClass().getName(), getQuote(), getStatus());
}
}COPY
報價服務的典型響應如下所示:
{
"type":"success",
"value": {
"id":1,
"quote":"Working with Spring Boot is like pair-programming with the Spring developers."
}
}COPY這兩個類都標有 。這意味著即使可以檢索其他 JSON 屬性,它們也會被忽略。@JsonIgnoreProperties(ignoreUnknown=true)。
查詢數(shù)據(jù)報價服務
下一步是創(chuàng)建一個查詢報價的服務類。
src/main/java/hello/QuoteService.java。
package hello;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@SuppressWarnings("unused")
@Service
public class QuoteService {
protected static final String ID_BASED_QUOTE_SERVICE_URL = "https://quoters.apps.pcfone.io/api/{id}";
protected static final String RANDOM_QUOTE_SERVICE_URL = "https://quoters.apps.pcfone.io/api/random";
private volatile boolean cacheMiss = false;
private final RestTemplate quoteServiceTemplate = new RestTemplate();
/**
* Determines whether the previous service method invocation resulted in a cache miss.
*
* @return a boolean value indicating whether the previous service method invocation resulted in a cache miss.
*/
public boolean isCacheMiss() {
boolean cacheMiss = this.cacheMiss;
this.cacheMiss = false;
return cacheMiss;
}
protected void setCacheMiss() {
this.cacheMiss = true;
}
/**
* Requests a quote with the given identifier.
*
* @param id the identifier of the {@link Quote} to request.
* @return a {@link Quote} with the given ID.
*/
@Cacheable("Quotes")
public Quote requestQuote(Long id) {
setCacheMiss();
return requestQuote(ID_BASED_QUOTE_SERVICE_URL, Collections.singletonMap("id", id));
}
/**
* Requests a random quote.
*
* @return a random {@link Quote}.
*/
@CachePut(cacheNames = "Quotes", key = "#result.id")
public Quote requestRandomQuote() {
setCacheMiss();
return requestQuote(RANDOM_QUOTE_SERVICE_URL);
}
protected Quote requestQuote(String URL) {
return requestQuote(URL, Collections.emptyMap());
}
protected Quote requestQuote(String URL, MapurlVariables) {
return Optional.ofNullable(this.quoteServiceTemplate.getForObject(URL, QuoteResponse.class, urlVariables))
.map(QuoteResponse::getQuote)
.orElse(null);
}
}COPY
使用 Spring 的來查詢報價服務的QuoteServiceRestTemplate應用程序接口.Quote 服務返回一個 JSON 對象,但 Spring 使用 Jackson 將數(shù)據(jù)綁定到一個對象,并最終綁定到一個對象。QuoteResponseQuote。
此服務類的關鍵部分是如何使用 進行注釋。requestQuote@Cacheable("Quotes")Spring's Caching Abstraction截獲調用 以檢查服務方法是否已被調用。如果是這樣,Spring的緩存抽象只返回緩存的副本。否則,Spring 將繼續(xù)調用該方法,將響應存儲在緩存中,然后將結果返回給調用方。requestQuote。
我們還在服務方法上使用了注釋。由于從此服務方法調用返回的報價將是隨機的,因此我們不知道將收到哪個報價。因此,我們不能在調用之前查閱緩存(即),但我們可以緩存調用的結果,這將對后續(xù)調用產(chǎn)生積極影響,假設感興趣的報價是之前隨機選擇和緩存的。@CachePutrequestRandomQuoteQuotesrequestQuote(id)。
使用 SpEL 表達式 ("#result.id") 訪問服務方法調用的結果,并檢索要用作緩存鍵的 ID。您可以了解有關Spring的Cache Abstraction SpEL上下文的更多信息@CachePutQuote這里。
您必須提供緩存的名稱。出于演示目的,我們將其命名為"報價",但在生產(chǎn)中,建議選擇一個適當?shù)拿枋鲂悦Q。這也意味著不同的方法可以與不同的緩存相關聯(lián)。如果每個緩存具有不同的配置設置(如不同的過期或逐出策略等),這將非常有用。
稍后,當您運行代碼時,您將看到運行每個調用所需的時間,并能夠辨別緩存對服務響應時間的影響。這演示了緩存某些調用的價值。如果您的應用程序不斷查找相同的數(shù)據(jù),則緩存結果可以顯著提高性能。
使應用程序可執(zhí)行
盡管 Apache Geode 緩存可以嵌入到 Web 應用程序和 WAR 文件中,但下面演示的更簡單方法會創(chuàng)建一個獨立的應用程序。您將所有內(nèi)容打包到一個可執(zhí)行的JAR文件中,由一個很好的舊Java方法驅動。main()。
src/main/java/hello/Application.java。
package hello;
import java.util.Optional;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.cache.config.EnableGemfireCaching;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions;
@SpringBootApplication
@ClientCacheApplication(name = "CachingGemFireApplication")
@EnableCachingDefinedRegions(clientRegionShortcut = ClientRegionShortcut.LOCAL)
@EnableGemfireCaching
@SuppressWarnings("unused")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
ApplicationRunner runner(QuoteService quoteService) {
return args -> {
Quote quote = requestQuote(quoteService, 12L);
requestQuote(quoteService, quote.getId());
requestQuote(quoteService, 10L);
};
}
private Quote requestQuote(QuoteService quoteService, Long id) {
long startTime = System.currentTimeMillis();
Quote quote = Optional.ofNullable(id)
.map(quoteService::requestQuote)
.orElseGet(quoteService::requestRandomQuote);
long elapsedTime = System.currentTimeMillis();
System.out.printf("\"%1$s\"%nCache Miss [%2$s] - Elapsed Time [%3$s ms]%n", quote,
quoteService.isCacheMiss(), (elapsedTime - startTime));
return quote;
}
}COPY
@SpringBootApplication是添加以下所有內(nèi)容的便利注釋:
- @Configuration:將類標記為應用程序上下文的 Bean 定義的源。
- @EnableAutoConfiguration:告訴 Spring Boot 根據(jù)類路徑設置、其他 Bean 和各種屬性設置開始添加 Bean。例如,如果在類路徑上,則此批注將應用程序標記為 Web 應用程序并激活關鍵行為,如設置 .spring-webmvcDispatcherServlet。
- @ComponentScan:告訴Spring在軟件包中查找其他組件、配置和服務,讓它找到控制器。hello。
該方法使用Spring Boot的方法啟動應用程序。您是否注意到?jīng)]有一行 XML?也沒有文件。此Web應用程序是100%純Java,您不必處理配置任何管道或基礎架構。main()SpringApplication.run()web.xml。
配置的頂部是一個至關重要的注釋:這將打開緩存(即使用Spring的注釋進行元注釋),并在后臺聲明其他重要的bean,以支持使用Apache Geode作為緩存提供程序的緩存。@EnableGemfireCaching@EnableCaching。
第一個 Bean 是用于訪問 Quotes REST-ful Web 服務的實例。QuoteService。
另外兩個用于緩存報價并執(zhí)行應用程序的操作。
- quotesRegion在緩存中定義一個 Apache Geode 客戶端區(qū)域來存儲報價。它被特別命名為"報價",以匹配我們方法的用法。LOCAL@Cacheable("Quotes")QuoteService。
- runner是用于運行應用程序的 Spring Boot 接口的一個實例。ApplicationRunner。
第一次請求報價(使用)時,會發(fā)生緩存未命中,并且將調用服務方法,從而產(chǎn)生明顯的延遲,該延遲不會接近于零毫秒。在這種情況下,緩存由服務方法 的輸入?yún)?shù)(即 )鏈接。換句話說,方法參數(shù)是緩存鍵。對 ID 標識的相同報價的后續(xù)請求將導致緩存命中,從而避免昂貴的服務調用。requestQuote(id)idrequestQuoteid。
出于演示目的,對 的調用被包裝在一個單獨的方法(類內(nèi)部)中,以捕獲進行服務調用的時間。這使您可以確切地查看任何一個請求需要多長時間。
QuoteServicerequestQuoteApplication。
構建可執(zhí)行的 JAR
您可以使用 Gradle 或 Maven 從命令行運行應用程序。您還可以構建一個包含所有必要依賴項、類和資源的可執(zhí)行 JAR 文件并運行該文件。通過構建可執(zhí)行 jar,可以輕松地在整個開發(fā)生命周期中跨不同環(huán)境等將服務作為應用程序進行交付、版本控制和部署。
如果您使用 Gradle,則可以使用 運行應用程序。或者,您可以使用 JAR 文件構建 JAR 文件,然后運行該 JAR 文件,如下所示:./gradlew bootRun./gradlew build。
java -jar build/libs/gs-caching-gemfire-0.1.0.jar
如果使用 Maven,則可以使用 運行應用程序?;蛘?,您可以使用 JAR 文件構建 JAR 文件,然后運行該 JAR 文件,如下所示:./mvnw spring-boot:run./mvnw clean package。
java -jar target/gs-caching-gemfire-0.1.0.jar
此處描述的步驟將創(chuàng)建一個可運行的 JAR。您還可以構建經(jīng)典 WAR 文件。
將顯示日志記錄輸出。該服務應在幾秒鐘內(nèi)啟動并運行。
"@springboot with @springframework is pure productivity! Who said in #java one has to write double the code than in other langs? #newFavLib"
Cache Miss [true] - Elapsed Time [776 ms]
"@springboot with @springframework is pure productivity! Who said in #java one has to write double the code than in other langs? #newFavLib"
Cache Miss [false] - Elapsed Time [0 ms]
"Really loving Spring Boot, makes stand alone Spring apps easy."
Cache Miss [true] - Elapsed Time [96 ms]
從中可以看出,第一次調用報價服務以獲取報價需要 776 毫秒,并導致緩存未命中。但是,請求相同報價的第二個調用花費了 0 毫秒,并導致緩存命中。這清楚地表明,第二個調用已被緩存,并且從未實際命中報價服務。但是,當對特定的非緩存報價請求進行最終服務調用時,它花費了 96 毫秒并導致緩存未命中,因為在調用之前,此新報價之前不在緩存中。
總結
祝賀!您剛剛構建了一個服務,該服務執(zhí)行了一個代價高昂的操作并對其進行了標記,以便緩存結果。
標題名稱:Spring認證指南:了解如何在GemFire中緩存數(shù)據(jù)
標題網(wǎng)址:http://m.fisionsoft.com.cn/article/cdgdogi.html


咨詢
建站咨詢
