<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" 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"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.0</version> </parent> <groupId>org.springframework</groupId> <artifactId>gs-accessing-gemfire-data-rest</artifactId> <version>0.1.0</version> <properties> <spring-shell.version>1.2.0.RELEASE</spring-shell.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-geode</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.shell</groupId> <artifactId>spring-shell</artifactId> <version>${spring-shell.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
使用 REST 訪問 Pivotal GemFire 中的資料
本指南將引導您建立一個應用,該應用透過一個基於超媒體的 REST 前端訪問儲存在 Apache Geode 中的資料。
您將構建什麼
您將構建一個 Spring Web 應用,該應用允許您使用 Spring Data REST 建立和檢索儲存在 Apache Geode 記憶體資料網格 (IMDG) 中的 Person
物件。Spring Data REST 自動集成了 Spring HATEOAS 和 Spring Data for Apache Geode 的特性。
Spring Data REST 還支援 Spring Data JPA、Spring Data MongoDB 和 Spring Data Neo4j 作為後端資料儲存,但這些不屬於本指南的範圍。 |
要了解有關 Apache Geode 概念以及如何從 Apache Geode 訪問資料的更多通用知識,請閱讀指南:使用 Apache Geode 訪問資料。 |
您將需要什麼
-
大約 15 分鐘
-
您喜歡的文字編輯器或 IDE
-
Java 1.8 或更高版本
-
您也可以將程式碼直接匯入到您的 IDE 中
如何完成本指南
與大多數 Spring 入門指南一樣,您可以從頭開始並完成每個步驟,或者您可以跳過您已經熟悉的基本設定步驟。無論哪種方式,您最終都會得到可以執行的程式碼。
要從頭開始,請繼續閱讀從 Spring Initializr 開始。
要跳過基礎部分,請執行以下操作
-
下載並解壓本指南的原始碼庫,或者使用 Git 克隆:
git clone https://github.com/spring-guides/gs-accessing-gemfire-data-rest.git
-
進入目錄
gs-accessing-gemfire-data-rest/initial
-
直接跳轉到建立域物件。
完成後,您可以對照 gs-accessing-gemfire-data-rest/complete
中的程式碼檢查您的結果。
從 Spring Initializr 開始
對於所有的 Spring 應用,您都應該從 Spring Initializr 開始。Spring Initializr 提供了一種快速獲取應用所需所有依賴並進行大量設定的方式。本示例需要 "Spring for Apache Geode" 依賴。
以下列表顯示了使用 Maven 時的示例 pom.xml
檔案
以下列表顯示了使用 Gradle 時的示例 build.gradle
檔案
plugins { id 'org.springframework.boot' version '2.7.0' 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 targetCompatibility = 1.8 repositories { mavenCentral() } dependencies { implementation "org.springframework.boot:spring-boot-starter-data-rest" implementation "org.springframework.data:spring-data-geode" implementation "org.projectlombok:lombok" runtimeOnly "org.springframework.shell:spring-shell:1.2.0.RELEASE" testImplementation "org.springframework.boot:spring-boot-starter-test" } test { useJUnitPlatform() } bootJar { baseName = 'gs-accessing-gemfire-data-rest' version = '0.1.0' }
建立域物件
建立一個新的域物件來表示一個人。
src/main/java/hello/Person.java
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.gemfire.mapping.annotation.Region;
import lombok.Data;
@Data
@Region("People")
public class Person {
private static AtomicLong COUNTER = new AtomicLong(0L);
@Id
private Long id;
private String firstName;
private String lastName;
@PersistenceConstructor
public Person() {
this.id = COUNTER.incrementAndGet();
}
}
Person
物件有名字和姓氏。Apache Geode 域物件需要一個 ID,因此使用了 AtomicLong
來在每個 Person
物件建立時遞增。
建立 Person 倉庫
接下來,您需要建立一個簡單的倉庫 (Repository) 來持久化/訪問儲存在 Apache Geode 中的 Person
物件。
src/main/java/hello/PersonRepository.java
package hello;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends CrudRepository<Person, Long> {
List<Person> findByLastName(@Param("name") String name);
}
這個倉庫 (Repository) 是一個介面,它允許您執行涉及 Person
物件的各種資料訪問操作(例如基本的 CRUD 和簡單查詢)。它透過擴充套件 CrudRepository
獲得這些操作。
在執行時,Spring Data for Apache Geode 將自動建立此介面的實現。然後,Spring Data REST 將使用 @RepositoryRestResource 註解,指示 Spring MVC 在 /people
處建立 REST 端點。
匯出倉庫 (Repository) 不需要使用 @RepositoryRestResource 。它僅用於更改匯出詳情,例如使用 /people 代替預設值 /persons 。 |
在這裡,您還定義了一個自定義查詢,用於根據 lastName
檢索 Person
物件的列表。在本指南的後續部分中,您將瞭解如何呼叫它。
使應用可執行
雖然可以將此服務打包成傳統的 WAR 檔案部署到外部應用伺服器,但下面演示的更簡單的方法是建立一個獨立應用。您將所有內容打包到一個單獨的可執行 JAR 檔案中,由經典的 Java main()
方法驅動。在此過程中,您使用了 Spring 對嵌入 Tomcat servlet 容器作為 HTTP 執行時的支援,而不是部署到外部 servlet 容器。
src/main/java/hello/Application.java
package hello;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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 = "AccessingGemFireDataRestApplication")
@EnableEntityDefinedRegions(
basePackageClasses = Person.class,
clientRegionShortcut = ClientRegionShortcut.LOCAL
)
@EnableGemfireRepositories
@SuppressWarnings("unused")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication
是一個便捷註解,它添加了以下所有功能
-
@Configuration
:將類標記為應用上下文的 Bean 定義源。 -
@EnableAutoConfiguration
:告訴 Spring Boot 根據類路徑設定、其他 Bean 和各種屬性設定開始新增 Bean。例如,如果類路徑中有spring-webmvc
,此註解會將應用標記為 Web 應用並激活關鍵行為,例如設定DispatcherServlet
。 -
@ComponentScan
:告訴 Spring 在hello
包中查詢其他元件、配置和服務,從而找到控制器。
main()
方法使用 Spring Boot 的 SpringApplication.run()
方法啟動應用。您是否注意到沒有一行 XML 程式碼?也沒有 web.xml
檔案。這個 Web 應用是 100% 純 Java 的,您無需處理任何底層或基礎設施的配置。
@EnableGemfireRepositories
註解啟用 Spring Data for Apache Geode 的倉庫 (Repositories) 功能。Spring Data for Apache Geode 將建立 PersonRepository
介面的具體實現,並將其配置為與嵌入式的 Apache Geode 例項通訊。
構建可執行 JAR
您可以使用 Gradle 或 Maven 從命令列執行應用。您還可以構建一個包含所有必要依賴、類和資源的單個可執行 JAR 檔案並執行它。構建可執行 JAR 使服務在整個開發生命週期中、跨不同環境等情況下,易於交付、版本化和部署為應用。
如果您使用 Gradle,您可以使用 ./gradlew bootRun
執行應用。或者,您可以使用 ./gradlew build
構建 JAR 檔案,然後按如下方式執行該 JAR 檔案
如果您使用 Maven,您可以使用 ./mvnw spring-boot:run
執行應用。或者,您可以使用 ./mvnw clean package
構建 JAR 檔案,然後按如下方式執行該 JAR 檔案
此處描述的步驟會建立一個可執行的 JAR。您還可以構建一個經典的 WAR 檔案。 |
將顯示日誌輸出。服務應在幾秒鐘內啟動並執行。
測試應用
應用執行後,您可以測試它。您可以使用任何您喜歡的 REST 客戶端。以下示例使用了 *nix 工具 curl
。
首先您想檢視頂層服務。
$ curl https://:8080
{
"_links" : {
"people" : {
"href" : "https://:8080/people"
}
}
}
在這裡,您將第一次看到這個伺服器提供了什麼。有一個名為 people 的連結位於 https://:8080/people。Spring Data for Apache Geode 不像其他 Spring Data REST 指南那樣支援分頁,因此沒有額外的導航連結。
Spring Data REST 使用 HAL 格式輸出 JSON。它非常靈活,並提供了一種方便的方式在所提供的資料旁邊提供連結。 |
$ curl https://:8080/people
{
"_links" : {
"search" : {
"href" : "https://:8080/people/search"
}
}
}
現在來建立一個新的 Person
物件!
$ curl -i -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Frodo", "lastName" : "Baggins" }' https://:8080/people
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Location: https://:8080/people/1
Content-Length: 0
Date: Wed, 05 Mar 2014 20:16:11 GMT
-
-i
確保您可以看到響應訊息,包括頭部。顯示了新建立的Person
的 URI -
-X POST
傳送一個POST
HTTP 請求來建立新條目 -
-H "Content-Type:application/json"
設定內容型別,以便應用知道請求體包含一個 JSON 物件 -
-d '{ "firstName" : "Frodo", "lastName" : "Baggins" }'
是正在傳送的資料
注意之前的 POST 操作如何包含一個 Location 頭部。這包含了新建立資源的 URI。Spring Data REST 還在 RepositoryRestConfiguration 上有兩個方法 setReturnBodyOnCreate(…) 和 setReturnBodyOnCreate(…) ,您可以使用它們配置框架,使其在資源建立後立即返回該資源的表示形式。 |
從這裡您可以查詢所有的人
$ curl https://:8080/people
{
"_links" : {
"search" : {
"href" : "https://:8080/people/search"
}
},
"_embedded" : {
"persons" : [ {
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/1"
}
}
} ]
}
}
people 集合資源包含一個包含 Frodo 的列表。注意它如何包含一個 self 連結。Spring Data REST 還使用 Evo Inflector 來將實體名稱複數化以進行分組。
您可以直接查詢單個記錄
$ curl https://:8080/people/1
{
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/1"
}
}
}
這可能看起來完全基於 Web,但在幕後,它正在與一個嵌入式的 Apache Geode 資料庫進行通訊。 |
在本指南中,只有一個域物件。在一個域物件相互關聯的更復雜的系統中,Spring Data REST 將渲染額外的連結,以幫助導航到相關的記錄。
查詢所有自定義查詢
$ curl https://:8080/people/search
{
"_links" : {
"findByLastName" : {
"href" : "https://:8080/people/search/findByLastName{?name}",
"templated" : true
}
}
}
您可以看到查詢的 URL,其中包括 HTTP 查詢引數 name
。您會注意到,這與介面中嵌入的 @Param("name")
註解相匹配。
要使用 findByLastName
查詢,請執行此操作
$ curl https://:8080/people/search/findByLastName?name=Baggins
{
"_embedded" : {
"persons" : [ {
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/1"
}
}
} ]
}
}
因為您在程式碼中將其定義為返回 List<Person>
,所以它將返回所有結果。如果您定義為僅返回 Person
,它將選擇一個 Person
物件返回。由於這可能無法預測,對於可以返回多個條目的查詢,您可能不希望這樣做。
您還可以發出 PUT
、PATCH
和 DELETE
REST 呼叫來替換、更新或刪除現有記錄。
$ curl -X PUT -H "Content-Type:application/json" -d '{ "firstName": "Bilbo", "lastName": "Baggins" }' https://:8080/people/1
$ curl https://:8080/people/1
{
"firstName" : "Bilbo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/1"
}
}
}
$ curl -X PATCH -H "Content-Type:application/json" -d '{ "firstName": "Bilbo Jr." }' https://:8080/people/1
$ curl https://:8080/people/1
{
"firstName" : "Bilbo Jr.",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/1"
}
}
}
PUT 會替換整個記錄。未提供的欄位將用 null 替換。PATCH 可用於更新部分條目。 |
您可以刪除記錄
$ curl -X DELETE https://:8080/people/1
$ curl https://:8080/people
{
"_links" : {
"search" : {
"href" : "https://:8080/people/search"
}
}
}
這種超媒體驅動介面的一個非常方便之處在於,您可以使用 curl
(或您正在使用的任何 REST 客戶端)發現所有 REST 端點。無需與您的客戶交換正式合同或介面文件。
另請參閱
以下指南可能也會有所幫助
想撰寫新指南或對現有指南做出貢獻?請檢視我們的貢獻指南。
所有指南的程式碼均以 ASLv2 許可證釋出,文字內容則以知識共享署名-禁止演繹(Attribution, NoDerivatives)許可證釋出。 |