本指南将引导您完成创建通过基于超媒体的 REST-ful前端访问Pivotal GemFire数据的应用程序的过程。

你会建立什么

您将构建一个Spring Web应用程序,让您创建和检索Person使用Spring Data REST存储在Pivotal GemFire内存数据网格中的对象。 Spring Data REST具有Spring HATEOASSpring Data for Pivotal GemFire的功能 ,并将它们自动组合在一起。

Spring Data REST还支持将Spring Data JPASpring Data MongoDBSpring Data Neo4j作为后端数据存储,但是这些都不属于本指南的一部分。
有关Pivotal GemFire概念以及从Pivotal GemFire访问数据的更多常规知识,请通读指南“ 使用Pivotal GemFire访问数据”

你需要什么

如何完成本指南

像大多数Spring 入门指南一样,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都可以使用工作代码。

从头开始 ,请继续使用Gradle构建

跳过基础知识 ,请执行以下操作:

完成后 ,您可以根据中的代码检查结果gs-accessing-gemfire-data-rest/complete

用Gradle构建

用Gradle构建

首先,您设置一个基本的构建脚本。在使用Spring构建应用程序时,可以使用任何喜欢的构建系统,但是此处包含使用GradleMaven所需的代码。如果您都不熟悉,请参阅使用Gradle 构建Java项目使用Maven构建Java项目

创建目录结构

在您选择的项目目录中,创建以下子目录结构;例如, mkdir -p src/main/java/hello在* nix系统上:

└── src
    └── main
        └── java
            └── hello

创建一个Gradle构建文件

build.gradle

buildscript {
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/libs-release" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE")
    }
}

plugins {
    id "io.spring.dependency-management" version "1.0.5.RELEASE"
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8
targetCompatibility = 1.8

bootJar {
    baseName = 'gs-accessing-gemfire-data-rest'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/libs-release" }
}

dependencies {

    compile("org.springframework.boot:spring-boot-starter-data-rest") {
        exclude group: "org.springframework.boot", module: "spring-boot-starter-logging"
    }
    compile("org.springframework.data:spring-data-gemfire")
    compile("org.projectlombok:lombok")

    runtime("org.springframework.shell:spring-shell:1.2.0.RELEASE")

    testCompile("org.springframework.boot:spring-boot-starter-test") {
        exclude group: "org.springframework.boot", module: "spring-boot-starter-logging"
    }
}

Spring Boot gradle插件提供了许多方便的功能:

  • 它收集类路径上的所有jar,并构建一个可运行的单个“über-jar”,这使执行和传输服务更加方便。

  • 它搜索public static void main()标记为可运行类的方法。

  • 它提供了一个内置的依赖项解析器,用于设置版本号以匹配Spring Boot依赖项 。您可以覆盖所需的任何版本,但是它将默认为Boot选择的一组版本。

用Maven构建

用Maven构建

首先,您设置一个基本的构建脚本。使用Spring构建应用程序时,可以使用任何喜欢的构建系统,但是此处包含了使用Maven所需的代码。如果您不熟悉Maven,请参阅使用Maven 构建Java项目

创建目录结构

在您选择的项目目录中,创建以下子目录结构;例如, mkdir -p src/main/java/hello在* nix系统上:

└── src
    └── main
        └── java
            └── hello

pom.xml

<?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.1.6.RELEASE</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>

    <repositories>
        <repository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-gemfire</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.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Spring Boot Maven插件提供了许多方便的功能:

  • 它收集类路径上的所有jar,并构建一个可运行的单个“über-jar”,这使执行和传输服务更加方便。

  • 它搜索public static void main()标记为可运行类的方法。

  • 它提供了一个内置的依赖项解析器,用于设置版本号以匹配Spring Boot依赖项 。您可以覆盖所需的任何版本,但是它将默认为Boot选择的一组版本。

使用您的IDE进行构建

使用您的IDE进行构建

创建一个域对象

创建一个新的域对象来呈现一个人。

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有名字和姓氏。关键的GemFire域对象需要一个ID,因此AtomicLong被用来增加每个Person对象创建。

创建个人资料库

接下来,您需要创建一个简单的存储库以持久/访问Person存储在Pivotal GemFire中的对象。

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);

}

存储库是一个界面,将允许您执行各种数据访问操作(例如,基本的CRUD和简单查询),其中涉及Person对象。它通过扩展获得这些操作CrudRepository

在运行时, 适用于Pivotal GemFire的Spring Data将自动创建此接口的实现。然后,Spring Data REST将使用@RepositoryRestResource批注来指示Spring MVC在以下位置创建REST风格的端点/people

@RepositoryRestResource不需要导出存储库 。它仅用于更改导出详细信息,例如使用/people而不是默认值/persons

在这里,您还定义了一个自定义查询来检索以下内容的列表Person基于的对象lastName 。您将在本指南中进一步了解如何调用它。

使应用程序可执行

尽管可以将该服务打包为传统的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", logLevel = "error")
@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批注激活Pivotal GemFire 存储库的 Spring数据Pivotal GemFire的Spring数据将创建PersonRepository接口并对其进行配置以与Pivotal GemFire的嵌入式实例进行对话。

构建可执行的JAR

您可以使用Gradle或Maven从命令行运行该应用程序。您还可以构建一个包含所有必需的依赖项,类和资源的可执行JAR文件,然后运行该文件。构建可执行的jar使得在整个开发生命周期中,跨不同环境等等的情况下,可以轻松地将服务作为应用程序进行发布,版本化和部署。

如果您使用Gradle,则可以使用./gradlew bootRun 。或者,您可以通过使用以下命令构建JAR文件: ./gradlew build然后运行JAR文件,如下所示:

java -jar build/libs/gs-accessing-gemfire-data-rest-0.1.0.jar

如果使用Maven,则可以通过使用以下命令运行应用程序./mvnw spring-boot:run 。或者,您可以使用以下命令构建JAR文件: ./mvnw clean package然后运行JAR文件,如下所示:

java -jar target/gs-accessing-gemfire-data-rest-0.1.0.jar
此处描述的步骤将创建可运行的JAR。您还可以构建经典的WAR文件

显示日志记录输出。该服务应在几秒钟内启动并运行。

测试应用

现在该应用程序正在运行,您可以对其进行测试。您可以使用任何所需的REST客户端。以下示例使用* nix工具curl

首先,您要查看顶级服务。

$ curl http://localhost:8080
{
  "_links" : {
    "people" : {
      "href" : "http://localhost:8080/people"
    }
  }
}

在这里,您可以初步了解该服务器所提供的功能。在http:// localhost:8080 / people上有一个人员链接。 Pivotal GemFire的Spring Data不像其他Spring Data REST指南那样支持分页,因此没有额外的导航链接。

Spring Data REST使用HAL格式进行JSON输出。它非常灵活,并提供了一种便捷的方式来提供与所提供数据相邻的链接。
$ curl http://localhost:8080/people
{
  "_links" : {
    "search" : {
      "href" : "http://localhost:8080/people/search"
    }
  }
}

是时候创建一个新的Person

$ curl -i -X POST -H "Content-Type:application/json" -d '{  "firstName" : "Frodo",  "lastName" : "Baggins" }' http://localhost:8080/people
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Location: http://localhost:8080/people/1
Content-Length: 0
Date: Wed, 05 Mar 2014 20:16:11 GMT
  • -i确保您可以看到包含标题的响应消息。新创建的URI Person显示

  • -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 http://localhost:8080/people
{
  "_links" : {
    "search" : {
      "href" : "http://localhost:8080/people/search"
    }
  },
  "_embedded" : {
    "persons" : [ {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/people/1"
        }
      }
    } ]
  }
}

人员集合资源包含Frodo的列表。注意它如何包含一个自我链接。Spring Data REST还使用Evo Inflector来对实体名称进行复数以进行分组。

您可以直接查询单个记录:

$ curl http://localhost:8080/people/1
{
  "firstName" : "Frodo",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/1"
    }
  }
}
这似乎纯粹是基于Web的,但是在后台,它正在与嵌入式Pivotal GemFire数据库进行通信。

在本指南中,只有一个域对象。在域对象相互关联的更复杂的系统中,Spring Data REST将提供附加链接以帮助导航到连接的记录。

查找所有自定义查询:

$ curl http://localhost:8080/people/search
{
  "_links" : {
    "findByLastName" : {
      "href" : "http://localhost:8080/people/search/findByLastName{?name}",
      "templated" : true
    }
  }
}

您可以看到查询的URL,包括HTTP查询参数name 。如果您会注意到,这与@Param("name")嵌入在界面中的注释。

要使用findByLastName查询,执行以下操作:

$ curl http://localhost:8080/people/search/findByLastName?name=Baggins
{
  "_embedded" : {
    "persons" : [ {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/people/1"
        }
      }
    } ]
  }
}

因为您将其定义为返回List在代码中,它将返回所有结果。如果已将其定义为仅返回Person ,它将选择其中之一Person要返回的对象。由于这可能是不可预测的,因此您可能不想对可以返回多个条目的查询执行此操作。

您也可以发出PUTPATCHDELETE REST调用以替换,更新或删除现有记录。

$ curl -X PUT -H "Content-Type:application/json" -d '{ "firstName": "Bilbo", "lastName": "Baggins" }' http://localhost:8080/people/1
$ curl http://localhost:8080/people/1
{
  "firstName" : "Bilbo",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/1"
    }
  }
}
$ curl -X PATCH -H "Content-Type:application/json" -d '{ "firstName": "Bilbo Jr." }' http://localhost:8080/people/1
$ curl http://localhost:8080/people/1
{
  "firstName" : "Bilbo Jr.",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/1"
    }
  }
}
PUT替换整个记录。未提供的字段将替换为nullPATCH可用于更新项的子集。

您可以删除记录:

$ curl -X DELETE http://localhost:8080/people/1
$ curl http://localhost:8080/people
{
  "_links" : {
    "search" : {
      "href" : "http://localhost:8080/people/search"
    }
  }
}

超媒体驱动的界面的一个非常方便的方面是如何使用以下方法发现所有REST风格的端点curl (或您使用的任何REST客户端)。无需与客户交换正式合同或接口文档。

摘要

恭喜你!您刚刚开发了一个具有基于超媒体的 RESTful前端和基于Pivotal GemFire的后端的应用程序。