<?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 中的数据
本指南将指导你完成创建应用程序的过程,该应用程序通过基于超媒体的RESTful 前端访问存储在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
-
cd 到
gs-accessing-gemfire-data-rest/initial
-
跳转到 创建域对象。
完成后,您可以根据 gs-accessing-gemfire-data-rest/complete
中的代码检查您的结果。
从 Spring Initializr 开始
对于所有 Spring 应用程序,您都应从 Spring Initializr 开始。Spring Initializr 提供了一种快速方法来提取应用程序所需的所有依赖项,并为您完成大量设置。此示例需要“适用于 Apache Geode 的 Spring”依赖项。
以下清单显示了使用 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 存储库
接下来,您需要创建一个简单的存储库来持久化/访问存储在 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);
}
此存储库是一个接口,它允许您执行涉及Person
对象的各种数据访问操作(例如,基本 CRUD 和简单查询)。它通过扩展CrudRepository
来获取这些操作。
在运行时,Spring Data for Apache Geode 将自动创建此接口的一个实现。然后,Spring Data REST 将使用 @RepositoryRestResource 注释指示 Spring MVC 在/people
处创建 RESTful 端点。
存储库不需要@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 存储库。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://127.0.0.1:8080
{
"_links" : {
"people" : {
"href" : "https://127.0.0.1:8080/people"
}
}
}
在这里,你可以初步了解此服务器提供的功能。有一个 人员 链接位于 https://127.0.0.1:8080/people。适用于 Apache Geode 的 Spring Data 不支持分页,如其他 Spring Data REST 指南,因此没有额外的导航链接。
Spring Data REST 使用 HAL 格式 作为 JSON 输出。它很灵活,并提供了一种便捷的方式来提供与所提供数据相邻的链接。 |
$ curl https://127.0.0.1:8080/people
{
"_links" : {
"search" : {
"href" : "https://127.0.0.1:8080/people/search"
}
}
}
是时候创建一个新的 人员
了!
$ curl -i -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Frodo", "lastName" : "Baggins" }' https://127.0.0.1:8080/people
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Location: https://127.0.0.1:8080/people/1
Content-Length: 0
Date: Wed, 05 Mar 2014 20:16:11 GMT
-
-i
确保你可以看到响应消息,包括标头。显示了新创建的人员
的 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://127.0.0.1:8080/people
{
"_links" : {
"search" : {
"href" : "https://127.0.0.1:8080/people/search"
}
},
"_embedded" : {
"persons" : [ {
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://127.0.0.1:8080/people/1"
}
}
} ]
}
}
人员 集合资源包含一个包含弗罗多的列表。请注意,它如何包含一个 self 链接。Spring Data REST 还使用 Evo Inflector 为分组的实体名称添加复数形式。
你可以直接查询单个记录
$ curl https://127.0.0.1:8080/people/1
{
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://127.0.0.1:8080/people/1"
}
}
}
这可能看起来完全基于 Web,但实际上,它正在与嵌入式 Apache Geode 数据库通信。 |
在本指南中,只有一个域对象。对于域对象相互关联的更复杂系统,Spring Data REST 将呈现其他链接,以帮助导航到连接的记录。
查找所有自定义查询
$ curl https://127.0.0.1:8080/people/search
{
"_links" : {
"findByLastName" : {
"href" : "https://127.0.0.1:8080/people/search/findByLastName{?name}",
"templated" : true
}
}
}
您可以看到查询的 URL,其中包括 HTTP 查询参数 name
。如果您注意到,这与嵌入在接口中的 @Param("name")
注释相匹配。
若要使用 findByLastName
查询,请执行此操作
$ curl https://127.0.0.1:8080/people/search/findByLastName?name=Baggins
{
"_embedded" : {
"persons" : [ {
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://127.0.0.1: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://127.0.0.1:8080/people/1
$ curl https://127.0.0.1:8080/people/1
{
"firstName" : "Bilbo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://127.0.0.1:8080/people/1"
}
}
}
$ curl -X PATCH -H "Content-Type:application/json" -d '{ "firstName": "Bilbo Jr." }' https://127.0.0.1:8080/people/1
$ curl https://127.0.0.1:8080/people/1
{
"firstName" : "Bilbo Jr.",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://127.0.0.1:8080/people/1"
}
}
}
PUT 替换整个记录。未提供的字段将被替换为 null 。PATCH 可用于更新子集项。 |
您可以删除记录
$ curl -X DELETE https://127.0.0.1:8080/people/1
$ curl https://127.0.0.1:8080/people
{
"_links" : {
"search" : {
"href" : "https://127.0.0.1:8080/people/search"
}
}
}
此 超媒体驱动接口 的一个非常方便的方面是,您可以使用 curl
(或您正在使用的任何 REST 客户端)发现所有 REST 端点。无需与您的客户交换正式合同或接口文档。