使用 REST 存取 MongoDB 資料

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

您將建構的內容

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

Spring Data REST 也支援 Spring Data JPASpring Data GemfireSpring Data Neo4j 作為後端資料儲存,但這些不在本指南的範圍內。

您需要的東西

如何完成本指南

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

若要從頭開始,請前往「從 Spring Initializr 開始」

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

完成後,您可以將您的結果與 gs-accessing-mongodb-data-rest/complete 中的程式碼進行比較。

從 Spring Initializr 開始

您可以使用這個預先初始化的專案,然後點擊「Generate」下載 ZIP 檔案。這個專案已配置為符合本教學課程中的範例。

若要手動初始化專案

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

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

  3. 點擊「Dependencies」並選擇 「Rest Repositories」「Spring Data MongoDB」

  4. 點擊「Generate」

  5. 下載產生的 ZIP 檔案,這是一個根據您的選擇配置的網路應用程式的封存檔。

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

安裝和啟動 MongoDB

為了讓本指南能夠運作,您必須架設一個本地 MongoDB 伺服器。

在已安裝 Homebrew 的 Mac OS X 機器上,執行以下命令

brew install mongodb

您可以在 https://docs.mongodb.org/manual/installation/ 找到更多安裝選項。

安裝 MongoDB 後,您需要啟動 mongo daemon。在 Mac 上,您可以使用以下命令

$ mongod
all output going to: /usr/local/var/log/mongodb/mongo.log

您可以從另一個終端機視窗執行 mongo 命令來啟動 MongoDB 客戶端。

建立網域物件

建立一個新的網域物件來表示一個人,如下列範例 (在 src/main/java/com/example/accessingmongodbdatarest/Person.java 中) 所示

package com.example.accessingmongodbdatarest;

import org.springframework.data.annotation.Id;

public class Person {

  @Id private String 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 Repository

接下來,您需要建立一個簡單的 repository,如下列程式碼 (在 src/main/java/com/example/accessingmongodbdatarest/PersonRepository.java 中) 所示

package com.example.accessingmongodbdatarest;

import java.util.List;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends MongoRepository<Person, String> {

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

}

這個 repository 是一個介面,可讓您執行各種涉及 Person 物件的操作。它透過擴展 MongoRepository 來獲得這些操作,而 MongoRepository 又擴展了 Spring Data Commons 中定義的 PagingAndSortingRepository 介面。

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

匯出 repository 並不需要 @RepositoryRestResource。它僅用於變更匯出詳細資訊,例如使用 /people 而不是預設值 /persons

在這裡,您還定義了一個自訂查詢,以根據 lastName 值檢索 Person 物件的列表。您可以在本指南的後續部分看到如何調用它。

預設情況下,Spring Boot 嘗試連接到本地託管的 MongoDB 實例。請閱讀參考文件,了解如何將您的應用程式指向託管在其他地方的 MongoDB 實例。

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

  • @Configuration:將類別標記為應用程式上下文的 bean 定義來源。

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

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

main() 方法使用 Spring Boot 的 SpringApplication.run() 方法來啟動應用程式。您是否注意到沒有一行 XML 程式碼?也沒有 web.xml 檔案。這個網路應用程式是 100% 純 Java,您不必處理任何管線或基礎架構的配置。

建構可執行 JAR 檔

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

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

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

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

java -jar target/gs-accessing-mongodb-data-rest-0.1.0.jar
這裡描述的步驟會建立可執行的 JAR 檔。您也可以建構傳統的 WAR 檔

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

測試應用程式

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

首先您想要查看頂層服務,如下列範例所示

$ 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 輸出。它很靈活,並提供了一種方便的方式來提供與所服務資料相鄰的連結。

當您使用 people 連結時,您會看到資料庫中的 Person 記錄 (目前沒有)

$ 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 了!

如果您多次執行本指南,可能會留下剩餘資料。如果您需要重新開始,請參閱 MongoDB shell 快速參考以取得尋找和刪除資料庫的命令。

以下命令建立一個名為 “Frodo Baggins” 的人

$ 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/53149b8e3004990b1af9f229
Content-Length: 0
Date: Mon, 03 Mar 2014 15:08:46 GMT
  • -i:確保您可以查看回應訊息,包括標頭。會顯示新建立的 Person 的 URI。

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

  • -H "Content-Type:application/json":設定內容類型,以便應用程式知道 payload 包含 JSON 物件。

  • -d '{ "firstName" : "Frodo", "lastName" : "Baggins" }':是要傳送的資料。

請注意先前的 POST 操作如何包含 Location 標頭。這包含新建立資源的 URI。Spring Data REST 還有兩種方法 (RepositoryRestConfiguration.setReturnBodyOnCreate(…)setReturnBodyOnUpdate(…)),您可以使用它們來配置框架以立即傳回剛建立/更新的資源的表示。

從這裡您可以查詢所有人員,如下列範例所示

$ 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" : {
    "persons" : [ {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "_links" : {
        "self" : {
          "href" : "https://127.0.0.1:8080/people/53149b8e3004990b1af9f229"
        }
      }
    } ]
  },
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  }
}

persons 物件包含一個包含 Frodo 的列表。請注意它如何包含一個 self 連結。Spring Data REST 還使用 Evo Inflector 來將群組實體的名稱複數化。

您可以直接查詢個別記錄,如下列範例所示

$ curl https://127.0.0.1:8080/people/53149b8e3004990b1af9f229
{
  "firstName" : "Frodo",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people/53149b8e3004990b1af9f229"
    }
  }
}
這可能看起來純粹是基於網路的,但實際上,它正在與您啟動的 MongoDB 資料庫進行通訊。

在本指南中,只有一個網域物件。在更複雜的系統中,網域物件彼此相關,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/53149b8e3004990b1af9f229"
        }
      }
    } ]
  }
}

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

您也可以發出 PUTPATCHDELETE REST 呼叫,分別用於取代、更新或刪除現有記錄。

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

以下範例使用 PUT 呼叫

$ curl -X PATCH -H "Content-Type:application/json" -d "{ \"firstName\": \"Bilbo Jr.\" }" https://127.0.0.1:8080/people/53149b8e3004990b1af9f229
$ curl https://127.0.0.1:8080/people/53149b8e3004990b1af9f229
{
  "firstName" : "Bilbo Jr.",
  "lastName" : "Baggins",
  "_links" : {
    "self" : {
      "href" : "https://127.0.0.1:8080/people/53149b8e3004990b1af9f229"
    }
  }
}
以下範例使用 PATCH 呼叫

PUT 會取代整個記錄。未提供的欄位將被取代為 null。您可以使用 PATCH 來更新項目子集。

$ curl -X DELETE https://127.0.0.1:8080/people/53149b8e3004990b1af9f229
$ 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 端點。無需與您的客戶交換正式合約或介面文件。

總結

所有指南均以 ASLv2 授權發布程式碼,並以 Attribution, NoDerivatives 創用 CC 授權發布寫作內容。