$ brew install neo4j
使用 REST 訪問 Neo4j 資料
本指南將引導您完成建立一個應用程式的過程,該應用程式透過基於超媒體的 RESTful 前端訪問基於圖的資料。
您將構建什麼
您將構建一個 Spring 應用程式,它允許您使用 Spring Data REST 建立和檢索儲存在Neo4j NoSQL 資料庫中的 Person
物件。Spring Data REST 結合了Spring HATEOAS 和Spring Data Neo4j 的特性,並自動將它們整合在一起。
Spring Data REST 還支援Spring Data JPA、Spring Data Gemfire 和Spring Data MongoDB 作為後端資料儲存,但本指南只涉及 Neo4j。 |
您需要什麼
-
大約 15 分鐘
-
您喜歡的文字編輯器或 IDE
-
Java 17 或更高版本
-
您也可以直接將程式碼匯入到您的 IDE 中
如何完成本指南
與大多數 Spring 入門指南一樣,您可以從頭開始完成每個步驟,或者跳過您已經熟悉的基本設定步驟。無論哪種方式,您最終都會得到可工作的程式碼。
要從頭開始,請繼續閱讀[scratch]。
要跳過基礎部分,請執行以下操作
-
下載並解壓本指南的源倉庫,或使用Git 克隆:
git clone https://github.com/spring-guides/{project_id}.git
-
進入
{project_id}/initial
目錄
完成後,您可以將您的結果與 {project_id}/complete
中的程式碼進行對照檢查。
搭建 Neo4j 伺服器
在構建此應用程式之前,您需要搭建一個 Neo4j 伺服器。
Neo4j 提供了一個免費的開源伺服器供您安裝。
在安裝了 Homebrew 的 Mac 上,您可以在終端視窗中輸入以下命令
安裝 Neo4j 後,您可以透過執行以下命令使用其預設設定啟動它
$ neo4j start
您應該會看到類似以下內容的訊息
Starting Neo4j. Started neo4j (pid 96416). By default, it is available at https://: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 的使用者名稱和密碼都是 neo4j
。但是,它要求更改新賬戶的密碼。要更改密碼,請執行以下命令
$ 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 檔案。此專案已配置好,適合本教程中的示例。
手動初始化專案
-
訪問https://start.spring.io。此服務會自動拉取您應用程式所需的所有依賴,併為您完成大部分設定。
-
選擇 Gradle 或 Maven 以及您想使用的語言。本指南假設您選擇了 Java。
-
點選 Dependencies 並選擇 Rest Repositories 和 Spring Data Neo4j。
-
點選 Generate。
-
下載生成的 ZIP 檔案,它是一個根據您的選擇配置好的 Web 應用程式的壓縮包。
如果您的 IDE 集成了 Spring Initializr,您可以直接在 IDE 中完成此過程。 |
您也可以從 Github fork 專案並在您的 IDE 或其他編輯器中開啟。 |
訪問 Neo4j 的許可權
Neo4j Community Edition 需要憑據才能訪問。您可以透過在 src/main/resources/application.properties
中設定屬性來配置憑據,如下所示
spring.neo4j.uri=bolt://: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 中定義的PagingAndSortingRepository
介面來獲得這些操作。
在執行時,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 檔案
如果您使用 Maven,可以透過執行 ./mvnw spring-boot:run
來執行應用程式。另外,您可以使用 ./mvnw clean package
構建 JAR 檔案,然後按如下方式執行 JAR 檔案
這裡描述的步驟建立了一個可執行的 JAR 檔案。您也可以構建一個經典的 WAR 檔案。 |
將顯示日誌輸出。服務應該在幾秒鐘內啟動並執行。
測試應用程式
應用程式啟動並執行後,您可以對其進行測試。您可以使用任何您喜歡的 REST 客戶端。下面的示例使用了名為 curl
的 *nix 工具。
首先,您想檢視頂級服務。下面的示例(包含輸出)展示瞭如何操作
$ curl https://:8080
{
"_links" : {
"people" : {
"href" : "https://:8080/people{?page,size,sort}",
"templated" : true
}
}
}
在這裡,您可以初步瞭解此伺服器提供的功能。有一個 people
連結,位於https://:8080/people。它包含一些選項,例如 ?page
、?size
和 ?sort
。
Spring Data REST 使用HAL 格式進行 JSON 輸出。它非常靈活,並提供了一種便捷的方式來提供與提供的資料相鄰的連結。 |
$ curl https://:8080/people
{
"_links" : {
"self" : {
"href" : "https://:8080/people{?page,size,sort}",
"templated" : true
},
"search" : {
"href" : "https://: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://:8080/people
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Location: https://: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://:8080/people
{
"_links" : {
"self" : {
"href" : "https://:8080/people{?page,size,sort}",
"templated" : true
},
"search" : {
"href" : "https://:8080/people/search"
}
},
"_embedded" : {
"people" : [ {
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/0"
}
}
} ]
},
"page" : {
"size" : 20,
"totalElements" : 1,
"totalPages" : 1,
"number" : 0
}
}
people
物件包含一個包含 Frodo 的列表。注意它如何包含一個 self
連結。Spring Data REST 還使用Evo Inflector 庫將實體名稱複數化以便進行分組。
您可以透過執行以下命令(包含輸出)直接查詢單個記錄
$ curl https://:8080/people/0
{
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/0"
}
}
}
這看起來似乎完全是基於 Web 的,但實際上,背後有一個嵌入式 Neo4j 圖資料庫。在生產環境中,您可能會連線到一個獨立的 Neo4j 伺服器。 |
在本指南中,只有一個領域物件。在一個更復雜的系統中,如果領域物件相互關聯,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" : {
"people" : [ {
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/0"
},
"person" : {
"href" : "https://:8080/people/0"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "https://:8080/people/search/findByLastName?name=Baggins"
}
}
}
因為您在程式碼中將其定義為返回 List<Person>
,所以它會返回所有結果。如果您將其定義為只返回 Person
,它會隨機選擇一個 Person
物件返回。由於這可能是不可預測的,對於可能返回多個條目的查詢,您可能不希望這樣做。
您還可以發出 PUT
、PATCH
和 DELETE
REST 呼叫來替換、更新或刪除現有記錄。下面的示例(包含輸出)展示了一個 PUT
呼叫
$ curl -X PUT -H "Content-Type:application/json" -d '{ "firstName": "Bilbo", "lastName": "Baggins" }' https://:8080/people/0
$ curl https://:8080/people/0
{
"firstName" : "Bilbo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/0"
}
}
}
下面的示例(包含輸出)展示了一個 PATCH
呼叫
$ curl -X PATCH -H "Content-Type:application/json" -d '{ "firstName": "Bilbo Jr." }' https://:8080/people/0
$ curl https://:8080/people/0
{
"firstName" : "Bilbo Jr.",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "https://:8080/people/0"
}
}
}
PUT 替換整個記錄。未提供的欄位將被替換為 null 。 PATCH 可用於更新專案的子集。 |
您還可以刪除記錄,如下面的示例(包含輸出)所示
$ curl -X DELETE https://:8080/people/0
$ curl https://:8080/people
{
"_links" : {
"self" : {
"href" : "https://:8080/people{?page,size,sort}",
"templated" : true
},
"search" : {
"href" : "https://:8080/people/search"
}
},
"page" : {
"size" : 20,
"totalElements" : 0,
"totalPages" : 0,
"number" : 0
}
}
這種超媒體驅動的介面的一個便捷之處在於,您可以使用 curl(或您喜歡的任何 REST 客戶端)來發現所有 RESTful 端點。您無需與客戶交換正式的合同或介面文件。
總結
恭喜您!您剛剛開發了一個具有基於超媒體的 RESTful 前端和基於 Neo4j 的後端應用程式。