{
"content":"Hello, World!",
"_links":{
"self":{
"href":"https://127.0.0.1:8080/greeting?name=World"
}
}
}
建構 Hypermedia 驅動的 RESTful Web 服務
本指南將引導您使用 Spring 建立「Hello, World」Hypermedia 驅動的 REST Web 服務。
Hypermedia 是 REST 的重要面向。它讓您建構服務,大幅度地解耦用戶端和伺服器,並讓它們獨立演進。為 REST 資源傳回的表示形式不僅包含資料,也包含相關資源的連結。因此,表示形式的設計對於整體服務的設計至關重要。
您將建構什麼
您將使用 Spring HATEOAS 建構一個 hypermedia 驅動的 REST 服務:一個 API 函式庫,您可以使用它來建立指向 Spring MVC 控制器的連結、建構資源表示形式,並控制它們如何呈現為支援的 hypermedia 格式(例如 HAL)。
此服務將接受位於 https://127.0.0.1:8080/greeting
的 HTTP GET 請求。
它將以 JSON 格式回應問候語,其中包含最簡單的 hypermedia 元素,即指向資源本身的連結。以下列表顯示了輸出
回應已指出您可以使用查詢字串中的選用 name
參數自訂問候語,如下列列表所示
https://127.0.0.1:8080/greeting?name=User
name
參數值會覆寫預設值 World
,並反映在回應中,如下列列表所示
{
"content":"Hello, User!",
"_links":{
"self":{
"href":"https://127.0.0.1:8080/greeting?name=User"
}
}
}
您需要的東西
-
約 15 分鐘
-
您慣用的文字編輯器或 IDE
-
Java 17 或更高版本
-
您也可以將程式碼直接匯入到您的 IDE 中
如何完成本指南
與大多數 Spring 開始使用指南 一樣,您可以從頭開始並完成每個步驟,或者您可以跳過您已經熟悉的基本設定步驟。無論哪種方式,您最終都會得到可運作的程式碼。
若要從頭開始,請繼續前往 從 Spring Initializr 開始。
若要跳過基本步驟,請執行以下操作
-
下載 並解壓縮本指南的原始碼儲存庫,或使用 Git 克隆它:
git clone https://github.com/spring-guides/gs-rest-hateoas.git
-
cd into
gs-rest-hateoas/initial
-
跳到 建立資源表示類別。
當您完成時,您可以將您的結果與 gs-rest-hateoas/complete
中的程式碼進行比較。
從 Spring Initializr 開始
您可以使用此 預先初始化的專案,然後按一下 Generate 以下載 ZIP 檔案。此專案已設定為符合本教學課程中的範例。
若要手動初始化專案
-
導覽至 https://start.spring.io。此服務會提取應用程式所需的所有相依性,並為您完成大部分的設定。
-
選擇 Gradle 或 Maven 以及您想要使用的語言。本指南假設您選擇了 Java。
-
按一下Dependencies 並選取 Spring HATEOAS。
-
按一下Generate。
-
下載產生的 ZIP 檔案,這是一個使用您的選擇設定的 Web 應用程式的封存檔。
如果您的 IDE 具有 Spring Initializr 整合,您可以從您的 IDE 完成此程序。 |
您也可以從 Github fork 此專案,並在您的 IDE 或其他編輯器中開啟它。 |
建立資源表示類別
現在您已經設定了專案和建置系統,您可以建立您的 Web 服務。
從思考服務互動開始此流程。
此服務將在 /greeting
公開一個資源,以處理 GET
請求,可選擇性地在查詢字串中使用 name
參數。GET
請求應傳回 200 OK
回應,並在主體中使用 JSON 來表示問候語。
除此之外,資源的 JSON 表示形式將在 _links
屬性中加入 hypermedia 元素列表。最基本的形式是指向資源本身的連結。表示形式應類似於以下列表
{
"content":"Hello, World!",
"_links":{
"self":{
"href":"https://127.0.0.1:8080/greeting?name=World"
}
}
}
content
是問候語的文字表示形式。_links
元素包含連結列表(在本例中,只有一個,其關係類型為 rel
,且 href
屬性指向被存取的資源)。
為了對問候語表示形式進行建模,請建立一個資源表示類別。由於 _links
屬性是表示模型的基本屬性,因此 Spring HATEOAS 隨附一個基底類別(稱為 RepresentationModel
),可讓您新增 Link
的執行個體,並確保它們如先前所示呈現。
建立一個擴展 RepresentationModel
的簡單 Java 物件,並為內容以及建構函式新增欄位和存取器,如下列列表(來自 src/main/java/com/example/resthateoas/Greeting.java
)所示
package com.example.resthateoas;
import org.springframework.hateoas.RepresentationModel;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Greeting extends RepresentationModel<Greeting> {
private final String content;
@JsonCreator
public Greeting(@JsonProperty("content") String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
-
@JsonCreator:表示 Jackson 如何建立此 POJO 的執行個體。
-
@JsonProperty:標記 Jackson 應將此建構函式引數放入的欄位。
正如您將在本指南稍後看到的,Spring 將使用 Jackson JSON 函式庫自動將 Greeting 類型的執行個體封送處理為 JSON。 |
接下來,建立將提供這些問候語的資源控制器。
建立 REST 控制器
在 Spring 建構 RESTful Web 服務的方法中,HTTP 請求由控制器處理。這些元件由 @RestController
註解識別,它結合了 @Controller
和 @ResponseBody
註解。以下 GreetingController
(來自 src/main/java/com/example/resthateoas/GreetingController.java
)透過傳回 Greeting
類別的新執行個體來處理 /greeting
的 GET
請求
package com.example.resthateoas;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RestController
public class GreetingController {
private static final String TEMPLATE = "Hello, %s!";
@RequestMapping("/greeting")
public HttpEntity<Greeting> greeting(
@RequestParam(value = "name", defaultValue = "World") String name) {
Greeting greeting = new Greeting(String.format(TEMPLATE, name));
greeting.add(linkTo(methodOn(GreetingController.class).greeting(name)).withSelfRel());
return new ResponseEntity<>(greeting, HttpStatus.OK);
}
}
此控制器簡潔而簡單,但有很多事情正在發生。我們逐步分解它。
@RequestMapping
註解確保對 /greeting
的 HTTP 請求會對應到 greeting()
方法。
以上範例未指定 GET 與 PUT 、POST 等,因為 @RequestMapping 預設會對應所有 HTTP 操作。使用 @GetMapping("/greeting") 來縮小此對應範圍。在這種情況下,您也需要 import org.springframework.web.bind.annotation.GetMapping; 。 |
@RequestParam
將查詢字串參數 name
的值繫結到 greeting()
方法的 name
參數。由於使用了 defaultValue
屬性,因此此查詢字串參數隱含地並非 required
。如果請求中不存在,則使用 defaultValue
World
。
由於類別上存在 @RestController
註解,因此會將隱含的 @ResponseBody
註解新增至 greeting
方法。這會導致 Spring MVC 將傳回的 HttpEntity
及其酬載 (Greeting
) 直接呈現給回應。
方法實作中最有趣的部分是如何建立指向控制器方法的連結,以及如何將其新增至表示模型。linkTo(…)
和 methodOn(…)
都是 ControllerLinkBuilder
上的靜態方法,可讓您模擬對控制器的呼叫方法。傳回的 LinkBuilder
將檢查控制器方法的對應註解,以建構方法對應到的確切 URI。
Spring HATEOAS 尊重各種 X-FORWARDED- 標頭。如果您將 Spring HATEOAS 服務置於 Proxy 後方,並使用 X-FORWARDED-HOST 標頭正確設定它,則產生的連結將會正確格式化。 |
對 withSelfRel()
的呼叫會建立一個 Link
執行個體,您將其新增至 Greeting
表示模型。
@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,您不必處理任何管線或基礎架構的設定。
建置可執行 JAR 檔
您可以使用 Gradle 或 Maven 從命令列執行應用程式。您也可以建置一個包含所有必要相依性、類別和資源的單個可執行 JAR 檔並執行它。建置可執行 JAR 檔可以輕鬆地在整個開發生命週期、跨不同環境等情況下,將服務作為應用程式運送、版本控制和部署。
如果您使用 Gradle,您可以使用 ./gradlew bootRun
來執行應用程式。或者,您可以使用 ./gradlew build
來建置 JAR 檔,然後執行 JAR 檔,如下所示
如果您使用 Maven,您可以使用 ./mvnw spring-boot:run
來執行應用程式。或者,您可以使用 ./mvnw clean package
來建置 JAR 檔,然後執行 JAR 檔,如下所示
此處描述的步驟會建立可執行 JAR。您也可以 建置傳統 WAR 檔。 |
將顯示記錄輸出。服務應在幾秒鐘內啟動並執行。
測試服務
現在服務已啟動,請造訪 https://127.0.0.1:8080/greeting,您應該會看到以下內容
{
"content":"Hello, World!",
"_links":{
"self":{
"href":"https://127.0.0.1:8080/greeting?name=World"
}
}
}
透過造訪以下 URL 提供 name
查詢字串參數:https://127.0.0.1:8080/greeting?name=User
。請注意 content
屬性的值如何從 Hello, World!
變更為 Hello, User!
,並且 self
連結的 href
屬性也反映了該變更,如下列列表所示
{
"content":"Hello, User!",
"_links":{
"self":{
"href":"https://127.0.0.1:8080/greeting?name=User"
}
}
}
此變更示範了 GreetingController
中的 @RequestParam
配置如預期般運作。name
參數已給定預設值 World
,但始終可以透過查詢字串明確覆寫。
摘要
恭喜!您剛剛使用 Spring HATEOAS 開發了一個 hypermedia 驅動的 RESTful Web 服務。