使用 REST 存取 Neo4j 資料

本指南將引導您完成建立應用程式的流程,該應用程式透過基於超媒體的 RESTful 前端存取基於圖形的資料。

您將建置的內容

您將建置一個 Spring 應用程式,讓您可以使用 Spring Data REST 建立和檢索儲存在 Neo4j NoSQL 資料庫中的 Person 物件。Spring Data REST 結合了 Spring HATEOASSpring Data Neo4j 的功能,並自動將它們結合在一起。

Spring Data REST 也支援 Spring Data JPASpring Data GemfireSpring Data MongoDB 作為後端資料儲存庫,但本指南著重於 Neo4j。

您需要的東西

如何完成本指南

與大多數 Spring 入門指南 一樣,您可以從頭開始並完成每個步驟,或者您可以跳過您已經熟悉的基本設定步驟。無論哪種方式,您最終都會得到可運作的程式碼。

若要從頭開始,請繼續前往 [從頭開始]

若要跳過基本步驟,請執行以下操作

當您完成時,您可以根據 {project_id}/complete 中的程式碼檢查您的結果。

啟動 Neo4j 伺服器

在您可以建置此應用程式之前,您需要設定 Neo4j 伺服器。

Neo4j 有一個您可以免費安裝的開放原始碼伺服器。

在安裝了 Homebrew 的 Mac 上,您可以在終端機視窗中輸入以下內容

$ brew install neo4j

如需其他選項,請參閱 https://neo4j.com/download/community-edition/

安裝 Neo4j 後,您可以執行以下命令以預設設定啟動它

$ neo4j start

您應該會看到類似以下的訊息

Starting Neo4j.
Started neo4j (pid 96416). By default, it is available at https://127.0.0.1:7474/
There may be a short delay until the server is ready.
See /usr/local/Cellar/neo4j/3.0.6/libexec/logs/neo4j.log for current status.

預設情況下,Neo4j 的使用者名稱和密碼為 neo4jneo4j。但是,它要求變更新帳戶密碼。若要執行此操作,請執行以下命令

$ curl -v -u neo4j:neo4j POST localhost:7474/user/neo4j/password -H "Content-type:application/json" -d "{\"password\":\"secret\"}"

這會將密碼從 neo4j 變更為 secret (在生產環境中絕對不能這樣做!) 完成後,您應該可以執行本指南了。

從 Spring Initializr 開始

您可以使用這個 預先初始化的專案,然後按一下 [Generate] 下載 ZIP 檔案。此專案已設定為符合本教學課程中的範例。

若要手動初始化專案

  1. 瀏覽至 https://start.spring.io。此服務會提取應用程式所需的所有相依性,並為您完成大部分設定。

  2. 選擇 Gradle 或 Maven 以及您想要使用的語言。本指南假設您選擇 Java。

  3. 按一下 [Dependencies] 並選取 [Rest Repositories] 和 [Spring Data Neo4j]。

  4. 按一下 [Generate]。

  5. 下載產生的 ZIP 檔案,該檔案是使用您的選擇設定的 Web 應用程式的封存檔。

如果您的 IDE 具有 Spring Initializr 整合,您可以從 IDE 完成此流程。
您也可以從 Github 分支專案,並在您的 IDE 或其他編輯器中開啟它。

存取 Neo4j 的權限

Neo4j Community Edition 需要憑證才能存取。您可以透過在 src/main/resources/application.properties 中設定屬性來設定憑證,如下所示

spring.neo4j.uri=bolt://127.0.0.1:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret

這包括預設使用者名稱 (neo4j) 和您稍早設定的新密碼 (secret)。

請勿將真實憑證儲存在您的原始碼儲存庫中。而是使用 Spring Boot 的屬性覆寫,在您的執行階段中設定它們。

建立網域物件

您需要建立新的網域物件來呈現人員,如下列範例 (在 src/main/java/com/example/accessingneo4jdatarest/Person.java 中) 所示

package com.example.accessingneo4jdatarest;

import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.GeneratedValue;

@Node
public class Person {

  @Id @GeneratedValue private Long id;

  private String firstName;
  private String lastName;

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
}

Person 物件具有名字和姓氏。還有一個 ID 物件已設定為自動產生,因此您無需執行此操作。

建立 Person 儲存庫

接下來,您需要建立一個簡單的儲存庫,如下列範例 (在 src/main/java/com/example/accessingneo4jdatarest/PersonRepository.java 中) 所示

package com.example.accessingneo4jdatarest;

import java.util.List;

import org.springframework.data.repository.PagingAndSortingRepository;
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 PagingAndSortingRepository<Person, Long>, CrudRepository<Person, Long> {

  List<Person> findByLastName(@Param("name") String name);

}

此儲存庫是一個介面,可讓您執行各種涉及 Person 物件的操作。它透過擴充 Spring Data Commons 中定義的 PagingAndSortingRepositry 介面來取得這些操作。

在執行階段,Spring Data REST 會自動建立此介面的實作。然後,它會使用 @RepositoryRestResource 註解來指示 Spring MVC 在 /people 建立 RESTful 端點。

@RepositoryRestResource 不是儲存庫匯出所必需的。它僅用於變更匯出詳細資料,例如使用 /people 而不是預設值 /persons

在這裡,您也定義了自訂查詢,以根據 lastName 值檢索 Person 物件的清單。您可以在本指南稍後查看如何叫用它。

尋找應用程式類別

當您使用 Spring Initializr 建立專案時,它會建立一個應用程式類別。您可以在 src/main/java/com/example/accessingneo4jdatarest/Application.java 中找到它。請注意,Spring Initializr 會串連 (並正確變更大小寫) 套件名稱,並將其新增至 Application 以建立應用程式類別名稱。在本例中,我們會取得 AccessingNeo4jDataRestApplication,如下列清單所示

package com.example.accessingneo4jdatarest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement
@EnableNeo4jRepositories
@SpringBootApplication
public class AccessingNeo4jDataRestApplication {

  public static void main(String[] args) {
    SpringApplication.run(AccessingNeo4jDataRestApplication.class, args);
  }
}

對於本範例,您無需對此應用程式類別進行任何變更

@SpringBootApplication 是一個便利的註解,它新增了以下所有內容

  • @Configuration:將類別標記為應用程式內容的 Bean 定義來源。

  • @EnableAutoConfiguration:告訴 Spring Boot 開始根據類別路徑設定、其他 Bean 和各種屬性設定來新增 Bean。例如,如果類別路徑上有 spring-webmvc,則此註解會將應用程式標記為 Web 應用程式,並啟動主要行為,例如設定 DispatcherServlet

  • @ComponentScan:告訴 Spring 在 com/example 套件中尋找其他元件、組態和服務,使其能夠找到控制器。

main() 方法使用 Spring Boot 的 SpringApplication.run() 方法來啟動應用程式。您是否注意到沒有單行 XML?也沒有 web.xml 檔案。此 Web 應用程式是 100% 純 Java,而且您不必處理設定任何管線或基礎結構。

@EnableNeo4jRepositories 註解會啟動 Spring Data Neo4j。Spring Data Neo4j 會建立 PersonRepository 的具體實作,並將其設定為使用 Cypher 查詢語言與內嵌 Neo4j 資料庫通訊。

建置可執行 JAR

您可以使用 Gradle 或 Maven 從命令列執行應用程式。您也可以建置包含所有必要相依性、類別和資源的單一可執行 JAR 檔案並執行該檔案。建置可執行 JAR 檔案可讓您輕鬆地在整個開發生命週期、跨不同環境等情況下,將服務作為應用程式來運送、版本控制和部署。

如果您使用 Gradle,您可以使用 ./gradlew bootRun 來執行應用程式。或者,您可以使用 ./gradlew build 建置 JAR 檔案,然後執行 JAR 檔案,如下所示

java -jar build/libs/{project_id}-0.1.0.jar

如果您使用 Maven,您可以使用 ./mvnw spring-boot:run 來執行應用程式。或者,您可以使用 ./mvnw clean package 建置 JAR 檔案,然後執行 JAR 檔案,如下所示

java -jar target/{project_id}-0.1.0.jar
此處描述的步驟會建立可執行 JAR。您也可以 建置傳統 WAR 檔案

會顯示記錄輸出。服務應在幾秒鐘內啟動並執行。

測試應用程式

現在應用程式正在執行中,您可以對其進行測試。您可以使用您想要的任何 REST 用戶端。以下範例使用名為 curl 的 *nix 工具。

首先,您想要查看最上層的服務。以下範例 (及其輸出) 顯示如何執行此操作

$ curl https://127.0.0.1:8080
{
  "_links" : {
    "people" : {
      "href" : "https://127.0.0.1:8080/people{?page,size,sort}",
      "templated" : true
    }
  }
}

在這裡,您可以初步了解此伺服器提供的內容。有一個 people 連結位於 https://127.0.0.1:8080/people。它具有一些選項,例如 ?page?size?sort

Spring Data REST 使用 HAL 格式 進行 JSON 輸出。它很靈活,並提供了一種方便的方式來提供與所服務資料相鄰的連結。
$ curl https://127.0.0.1:8080/people
{
  "_links" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people{?page,size,sort}",
      "templated" : true
    },
    "search" : {
      "href" : "https://127.0.0.1:8080/people/search"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 0,
    "totalPages" : 0,
    "number" : 0
  }
}

目前沒有任何元素,因此也沒有任何頁面,因此現在是建立新 Person 的時候了!若要執行此操作,請執行以下命令 (及其輸出)

$ 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/0
Content-Length: 0
Date: Wed, 26 Feb 2014 20:26:55 GMT
  • -i 確保您可以查看回應訊息,包括標頭。顯示新建立的 Person 的 URI

  • -X POST 表示這是用於建立新條目的 POST

  • -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" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people{?page,size,sort}",
      "templated" : true
    },
    "search" : {
      "href" : "https://127.0.0.1:8080/people/search"
    }
  },
  "_embedded" : {
    "people" : [ {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "_links" : {
        "self" : {
          "href" : "https://127.0.0.1:8080/people/0"
        }
      }
    } ]
  },
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  }
}

people 物件包含包含佛羅多的清單。請注意它如何包含 self 連結。Spring Data REST 也使用 Evo Inflector 程式庫來將群組的實體名稱複數化。

您可以執行以下命令 (及其輸出) 直接查詢個別記錄

$ curl https://127.0.0.1:8080/people/0
{
  "firstName" : "Frodo",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people/0"
    }
  }
}
這可能看起來純粹是基於 Web 的,但實際上,後端有一個內嵌的 Neo4j 圖形資料庫。在生產環境中,您可能會連線到獨立的 Neo4j 伺服器。

在本指南中,只有一個網域物件。對於更複雜的系統,網域物件彼此相關,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" : {
    "people" : [ {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "_links" : {
        "self" : {
          "href" : "https://127.0.0.1:8080/people/0"
        },
        "person" : {
          "href" : "https://127.0.0.1:8080/people/0"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people/search/findByLastName?name=Baggins"
    }
  }
}

因為您將其定義為在程式碼中傳回 List<Person>,所以它會傳回所有結果。如果您已將其定義為僅傳回 Person,它會選擇其中一個 Person 物件傳回。由於這可能無法預測,因此對於可以傳回多個條目的查詢,您可能不想這樣做。

您也可以發出 PUTPATCHDELETE REST 呼叫,以取代、更新或刪除現有記錄。以下範例 (及其輸出) 顯示 PUT 呼叫

$ curl -X PUT -H "Content-Type:application/json" -d '{ "firstName": "Bilbo", "lastName": "Baggins" }' https://127.0.0.1:8080/people/0
$ curl https://127.0.0.1:8080/people/0
{
  "firstName" : "Bilbo",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people/0"
    }
  }
}

以下範例 (及其輸出) 顯示 PATCH 呼叫

$ curl -X PATCH -H "Content-Type:application/json" -d '{ "firstName": "Bilbo Jr." }' https://127.0.0.1:8080/people/0
$ curl https://127.0.0.1:8080/people/0
{
  "firstName" : "Bilbo Jr.",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people/0"
    }
  }
}
PUT 會取代整個記錄。未提供的欄位會取代為 nullPATCH 可用於更新項目的子集。

您也可以刪除記錄,如下列範例 (及其輸出) 所示

$ curl -X DELETE https://127.0.0.1:8080/people/0
$ curl https://127.0.0.1:8080/people
{
  "_links" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people{?page,size,sort}",
      "templated" : true
    },
    "search" : {
      "href" : "https://127.0.0.1:8080/people/search"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 0,
    "totalPages" : 0,
    "number" : 0
  }
}

這種超媒體驅動介面的一個方便之處在於,您可以使用 curl (或您喜歡的任何 REST 用戶端) 探索所有 RESTful 端點。您無需與您的客戶交換正式合約或介面文件。

摘要

恭喜!您剛剛開發了一個具有 基於超媒體 的 RESTful 前端和基於 Neo4j 的後端的應用程式。

取得程式碼