Spring認證指南:了解如何使用 Gemfire 的數(shù)據(jù)結(jié)構(gòu)構(gòu)建應(yīng)用程序。(Spring中國教育管理中心)
在 Pivotal GemFire 中訪問數(shù)據(jù)
本指南將引導您完成構(gòu)建Apache Geode數(shù)據(jù)管理系統(tǒng)應(yīng)用程序的過程。
你將建造什么
您將使用Spring Data for Apache Geode來存儲和檢索 POJO,。
你需要什么
約15分鐘
最喜歡的文本編輯器或 IDE
JDK 1.8或更高版本
Gradle 4+或Maven 3.2+
您還可以將代碼直接導入 IDE:
彈簧工具套件 (STS)
IntelliJ IDEA
如何完成本指南
像大多數(shù) Spring入門指南一樣,您可以從頭開始并完成每個步驟,,也可以繞過您已經(jīng)熟悉的基本設(shè)置步驟,。無論哪種方式,您最終都會得到工作代碼,。
要從頭開始,,請繼續(xù)從 Spring Initializr 開始。
要跳過基礎(chǔ)知識,,請執(zhí)行以下操作:
下載并解壓本指南的源代碼庫,,或使用Git克隆它:git clone https://github.com/spring-guides/gs-accessing-data-gemfire.git
光盤進入gs-accessing-data-gemfire/initial
跳轉(zhuǎn)到定義一個簡單實體。
完成后,,您可以對照中的代碼檢查結(jié)果
gs-accessing-data-gemfire/complete,。
從 Spring Initializr 開始
對于所有 Spring 應(yīng)用程序,您應(yīng)該從Spring Initializr開始,。Spring Initializr 提供了一種快速的方法來獲取應(yīng)用程序所需的所有依賴項,,并為您完成大量設(shè)置。此示例需要 Spring for Apache Geode 依賴項,。
您可以使用這個預(yù)先初始化的項目并單擊 Generate 下載 ZIP 文件,。此項目配置為適合本教程中的示例。
手動初始化項目:
在 Web 瀏覽器中,,導航到https://start.,。該服務(wù)提取應(yīng)用程序所需的所有依賴項,并為您完成大部分設(shè)置,。
選擇 Gradle 或 Maven 以及您要使用的語言,。本指南假定您選擇了 Java。
單擊Dependencies并為 Apache Geode選擇Spring ,。
單擊生成,。
下載生成的 ZIP 文件,該文件是根據(jù)您的選擇配置的 Web 應(yīng)用程序的存檔,。
如果您的 IDE 具有 Spring Initializr 集成,,您可以從您的 IDE 完成此過程。
你也可以從 Github 上 fork 項目并在你的 IDE 或其他編輯器中打開它,。
定義一個簡單的實體
Apache Geode 是一種將數(shù)據(jù)映射到區(qū)域的內(nèi)存中數(shù)據(jù)網(wǎng)格 (IMDG),。您可以配置在集群中的多個節(jié)點之間分區(qū)和復(fù)制數(shù)據(jù)的分布式區(qū)域,。但是,在本指南中,,我們使用了一個LOCAL區(qū)域,,因此您無需設(shè)置任何額外內(nèi)容,例如整個服務(wù)器集群,。
Apache Geode 是一個鍵/值存儲,,一個區(qū)域?qū)崿F(xiàn)
java.util.concurrent.ConcurrentMap接口。盡管您可以將區(qū)域視為java.util.Map,,但它比簡單的 Java 復(fù)雜得多Map,,因為數(shù)據(jù)是在區(qū)域內(nèi)分布、復(fù)制和管理的,。
在此示例中,,您Person僅使用幾個注釋將對象存儲在 Apache Geode(一個區(qū)域)中。
src/main/java/hello/Person.java
package hello;import java.io.Serializable;import org.springframework.data.annotation.Id;import org.springframework.data.annotation.PersistenceConstructor;import org.springframework.data.gemfire.mapping.annotation.Region;import lombok.Getter;@Region(value = "People")public class Person implements Serializable { @Id @Getter private final String name; @Getter private final int age; @PersistenceConstructor public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return String.format("%s is %d years old", getName(), getAge()); } }
在這里,,您有一個Person包含兩個字段的類:name和age. 在創(chuàng)建新實例時,,您還有一個持久構(gòu)造函數(shù)來填充實體。該類使用Project Lombok來簡化實現(xiàn),。
請注意,,這個類是用 注釋的@Region("People"),。當 Apache Geode 存儲此類的實例時,,會在該區(qū)People域內(nèi)創(chuàng)建一個新條目。此類還name用 標記該字段@Id,。這表示用于識別和跟蹤PersonApache Geode 內(nèi)部數(shù)據(jù)的標識符,。本質(zhì)上,帶@Id注釋的字段(例如name)是鍵,,而Person實例是鍵/值條目中的值,。Apache Geode 中沒有自動生成密鑰,因此您必須在name將實體持久化到 Apache Geode 之前設(shè)置 ID (the ),。
下一個重要的部分是這個人的年齡,。在本指南的后面部分,我們使用它來設(shè)計一些查詢,。
被覆蓋的toString()方法打印出人的姓名和年齡,。
創(chuàng)建簡單查詢
Spring Data for Apache Geode 專注于使用 Spring 在 Apache Geode 中存儲和訪問數(shù)據(jù)。它還繼承了 Spring Data Commons 項目的強大功能,,例如派生查詢的能力,。本質(zhì)上,您不需要學習 Apache Geode (OQL) 的查詢語言,。您可以編寫一些方法,,框架會為您編寫查詢,。
要查看其工作原理,請創(chuàng)建一個查詢Person存儲在 Apache Geode 中的對象的接口:
src/main/java/hello/PersonRepository.java
package hello;import org.springframework.data.gemfire.repository.query.annotation.Trace;import org.springframework.data.repository.CrudRepository;public interface PersonRepository extends CrudRepository<Person, String> { @Trace Person findByName(String name); @Trace Iterable<Person> findByAgeGreaterThan(int age); @Trace Iterable<Person> findByAgeLessThan(int age); @Trace Iterable<Person> findByAgeGreaterThanAndAgeLessThan(int greaterThanAge, int lessThanAge); }
PersonRepository從 Spring Data Commons擴展接口,,并為RepositoryCrudRepository使用的值和 ID(鍵)指定泛型類型參數(shù)的類型(分別為和),。該接口帶有許多操作,包括基本的 CRUD(創(chuàng)建,、讀取,、更新、刪除)和簡單的查詢數(shù)據(jù)訪問操作(例如),。PersonStringfindById(..)
您可以根據(jù)需要通過聲明其方法簽名來定義其他查詢,。在這種情況下,我們添加findByName,,它實質(zhì)上搜索類型的對象Person并找到與 匹配的對象name,。
你還有:
findByAgeGreaterThan: 尋找特定年齡以上的人
findByAgeLessThan: 尋找特定年齡以下的人
findByAgeGreaterThanAndAgeLessThan: 尋找特定年齡段的人
讓我們把它連接起來,看看它是什么樣子的,!
創(chuàng)建應(yīng)用程序類
以下示例創(chuàng)建一個包含所有組件的應(yīng)用程序類:
src/main/java/hello/Application.java
package hello;import static java.util.Arrays.asList;import static java.util.stream.StreamSupport.stream;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.config.annotation.ClientCacheApplication;import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;@SpringBootApplication@ClientCacheApplication(name = "AccessingDataGemFireApplication")@EnableEntityDefinedRegions( basePackageClasses = Person.class, clientRegionShortcut = ClientRegionShortcut.LOCAL )@EnableGemfireRepositoriespublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean ApplicationRunner run(PersonRepository personRepository) { return args -> { Person alice = new Person("Adult Alice", 40); Person bob = new Person("Baby Bob", 1); Person carol = new Person("Teen Carol", 13); System.out.println("Before accessing data in Apache Geode..."); asList(alice, bob, carol).forEach(person -> System.out.println("\t" + person)); System.out.println("Saving Alice, Bob and Carol to Pivotal GemFire..."); personRepository.save(alice); personRepository.save(bob); personRepository.save(carol); System.out.println("Lookup each person by name..."); asList(alice.getName(), bob.getName(), carol.getName()) .forEach(name -> System.out.println("\t" + personRepository.findByName(name))); System.out.println("Query adults (over 18):"); stream(personRepository.findByAgeGreaterThan(18).spliterator(), false) .forEach(person -> System.out.println("\t" + person)); System.out.println("Query babies (less than 5):"); stream(personRepository.findByAgeLessThan(5).spliterator(), false) .forEach(person -> System.out.println("\t" + person)); System.out.println("Query teens (between 12 and 20):"); stream(personRepository.findByAgeGreaterThanAndAgeLessThan(12, 20).spliterator(), false) .forEach(person -> System.out.println("\t" + person)); }; } }
在配置中,,需要添加@EnableGemfireRepositories注解。
默認情況下,,@EnableGemfireRepositories掃描當前包以查找擴展 Spring Data 存儲庫接口之一的任何接口,。您可以使用它basePackageClasses = MyRepository.class來安全地告訴 Spring Data for Apache Geode 按類型掃描不同的根包以獲取特定于應(yīng)用程序的存儲庫擴展。
需要包含一個或多個區(qū)域的 Apache Geode 緩存來存儲所有數(shù)據(jù),。為此,,您可以使用 Spring Data for Apache Geode 方便的基于配置的注釋之一:@ClientCacheApplication、@PeerCacheApplication或@CacheServerApplication.
Apache Geode 支持不同的緩存拓撲,,例如客戶端/服務(wù)器,、點對點 (p2p),甚至是 WAN 安排,。在 p2p 中,,對等緩存實例嵌入在應(yīng)用程序中,您的應(yīng)用程序?qū)⒛軌蜃鳛閷Φ染彺娉蓡T參與集群,。但是,,您的應(yīng)用程序受到作為集群中對等成員的所有約束,因此這不像客戶端/服務(wù)器拓撲那樣常用,。
在我們的例子中,,我們使用@ClientCacheApplication創(chuàng)建一個“客戶端”緩存實例,它能夠連接到服務(wù)器集群并與之通信,。但是,,為了簡單起見,客戶端通過使用LOCAL客戶端區(qū)域在本地存儲數(shù)據(jù),而無需設(shè)置或運行任何服務(wù)器,。
現(xiàn)在,,還記得您是如何標記Person為存儲在People使用 SDG 映射注釋調(diào)用的區(qū)域中的@Region("People")嗎?您可以使用ClientRegionFactoryBean<String, Person>bean 定義在此處定義該區(qū)域,。您需要注入一個剛剛定義的緩存實例,,同時命名它People。
Apache Geode 緩存實例(無論是對等方還是客戶端)只是存儲數(shù)據(jù)的區(qū)域容器,。您可以將緩存視為 RDBMS 中的模式,,將區(qū)域視為表。但是,,緩存還執(zhí)行其他管理功能來控制和管理您的所有區(qū)域,。
類型是,將鍵類型 ( ) 與值類型 ( )<String, Person>匹配,。StringPerson
該public static void main方法使用 Spring BootSpringApplication.run()啟動應(yīng)用程序并調(diào)用ApplicationRunner(另一個 bean 定義),,它使用應(yīng)用程序的 Spring Data 存儲庫在 Apache Geode 上執(zhí)行數(shù)據(jù)訪問操作。
PersonRepository應(yīng)用程序自動裝配您剛剛定義的實例,。Spring Data for Apache Geode 動態(tài)創(chuàng)建一個具體的類來實現(xiàn)這個接口并插入所需的查詢代碼來滿足接口的義務(wù),。該run()方法使用此存儲庫實例來演示功能。
存儲和獲取數(shù)據(jù)
在本指南中,,您將創(chuàng)建三個本地Person對象:Alice,、Baby Bob和Teen Carol。最初,,它們只存在于內(nèi)存中,。創(chuàng)建它們后,您必須將它們保存到 Apache Geode,。
現(xiàn)在您可以運行多個查詢,。第一個按名字查找每個人,。然后,,您可以使用 age 屬性運行一些查詢來查找成人、嬰兒和青少年,。打開日志記錄后,,您可以看到 Spring Data for Apache Geode 代表您編寫的查詢。
要查看 SDG 生成的 Apache Geode OQL 查詢,,請將@ClientCacheApplication注釋logLevel屬性更改為config,。因為查詢方法(例如findByName)使用 SDG 的@Trace注解進行了注解,所以這會打開 Apache Geode 的 OQL 查詢跟蹤(查詢級日志記錄),,它會顯示生成的 OQL,、執(zhí)行時間、查詢是否使用了任何 Apache Geode 索引來收集結(jié)果以及查詢返回的行數(shù)。
構(gòu)建一個可執(zhí)行的 JAR
您可以使用 Gradle 或 Maven 從命令行運行應(yīng)用程序,。您還可以構(gòu)建一個包含所有必要依賴項,、類和資源的單個可執(zhí)行 JAR 文件并運行它。構(gòu)建可執(zhí)行 jar 可以在整個開發(fā)生命周期,、跨不同環(huán)境等中輕松地作為應(yīng)用程序交付,、版本化和部署服務(wù)。
如果您使用 Gradle,,則可以使用./gradlew bootRun. 或者,,您可以使用構(gòu)建 JAR 文件./gradlew build,然后運行 JAR 文件,,如下所示:
java -jar build/libs/gs-accessing-data-gemfire-0.1.0.jar
如果您使用 Maven,,則可以使用./mvnw spring-boot:run. 或者,您可以使用構(gòu)建 JAR 文件,,./mvnw clean package然后運行該 JAR 文件,,如下所示:
java -jar 目標/gs-accessing-data-gemfire-0.1.0.jar
此處描述的步驟創(chuàng)建了一個可運行的 JAR。您還可以構(gòu)建經(jīng)典的 WAR 文件,。
您應(yīng)該會看到類似這樣的內(nèi)容(帶有其他內(nèi)容,,例如查詢):
在與 {apache-geode-name} 鏈接之前... 愛麗絲今年 40 歲。 寶貝鮑勃 1 歲,。 青少年卡羅爾今年 13 歲,。按姓名查找每個人... 愛麗絲今年 40 歲。 寶貝鮑勃 1 歲,。 青少年卡羅爾今年 13 歲,。成人(18 歲以上): 愛麗絲今年 40 歲。嬰兒(5 歲以下): 寶貝鮑勃 1 歲,。青少年(12 至 20 歲): 青少年卡羅爾今年 13 歲,。
概括
恭喜!您設(shè)置了一個 Apache Geode 緩存客戶端,,存儲了簡單的實體,,并開發(fā)了快速查詢。