構建 RESTful Web 服務

本指南將引導你完成使用 Spring 建立一個“Hello, World”RESTful Web 服務的整個過程。

你將構建什麼

你將構建一個服務,該服務將接受對 https://:8080/greeting 的 HTTP GET 請求。

它將響應一個問候語的 JSON 表示,如下所示:

{"id":1,"content":"Hello, World!"}

你可以使用查詢字串中的可選 name 引數來自定義問候語,如下所示:

https://:8080/greeting?name=User

name 引數的值將覆蓋預設值 World 並反映在響應中,如下所示:

{"id":1,"content":"Hello, User!"}

你需要什麼

如何完成本指南

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

從頭開始,請繼續閱讀從 Spring Initializr 開始

跳過基礎,請執行以下操作:

完成時,你可以將你的結果與 gs-rest-service/complete 中的程式碼進行對照。

從 Spring Initializr 開始

你可以使用這個預配置專案,然後點選 Generate 下載 ZIP 檔案。這個專案已經配置好以適應本教程中的示例。

手動初始化專案

  1. 訪問 https://start.spring.io。此服務會引入應用程式所需的所有依賴項,併為你完成大部分設定。

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

  3. 點選 Dependencies 並選擇 Spring Web

  4. 點選 Generate

  5. 下載生成的 ZIP 檔案,這是一個根據你的選擇配置好的 Web 應用程式的壓縮包。

如果你的 IDE 集成了 Spring Initializr,你可以在 IDE 中完成這個過程。
你也可以從 Github fork 該專案,並在你的 IDE 或其他編輯器中開啟。

建立資源表示類

現在你已經設定好專案和構建系統,可以建立你的 Web 服務了。

從思考服務互動開始。

該服務將處理對 /greetingGET 請求,可選地包含查詢字串中的 name 引數。GET 請求應返回一個 200 OK 響應,其正文包含代表問候語的 JSON。它應該類似於以下輸出:

{
    "id": 1,
    "content": "Hello, World!"
}

id 欄位是問候語的唯一識別符號,而 content 是問候語的文字表示。

為了建模問候語表示,建立一個資源表示類。為此,提供一個用於 idcontent 資料的 Java record 類,如下面的列表(來自 src/main/java/com/example/restservice/Greeting.java)所示:

package com.example.restservice;

public record Greeting(long id, String content) { }
此應用程式使用 Jackson JSON 庫自動將 Greeting 型別的例項編組(marshal)為 JSON。Jackson 預設包含在 Web Starter 中。

建立資源控制器

在 Spring 構建 RESTful Web 服務的方法中,HTTP 請求由控制器處理。這些元件透過 @RestController 註解標識,如下面列表所示的 GreetingController(來自 src/main/java/com/example/restservice/GreetingController.java)透過返回 Greeting 類的新例項來處理對 /greetingGET 請求:

package com.example.restservice;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

	private static final String template = "Hello, %s!";
	private final AtomicLong counter = new AtomicLong();

	@GetMapping("/greeting")
	public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
		return new Greeting(counter.incrementAndGet(), String.format(template, name));
	}
}

這個控制器簡潔明瞭,但在底層做了很多工作。我們一步步來分析。

@GetMapping 註解確保 HTTP GET 請求到 /greeting 會對映到 greeting() 方法。

對於其他 HTTP 動詞(例如 POST 的 @PostMapping)也有相應的註解。此外,還有一個 @RequestMapping 註解,所有這些註解都派生自它,並且可以作為同義詞使用(例如 @RequestMapping(method=GET))。

@RequestParam 將查詢字串引數 name 的值繫結到 greeting() 方法的 name 引數。如果請求中缺少 name 引數,則使用預設值 World

方法體的實現基於 counter 的下一個值建立並返回一個新的 Greeting 物件,該物件具有 idcontent 屬性,並使用問候語 template 格式化給定的 name

傳統 MVC 控制器與前面所示的 RESTful Web 服務控制器之間的一個關鍵區別在於 HTTP 響應體的建立方式。RESTful Web 服務控制器不是依靠檢視技術在伺服器端將問候語資料渲染成 HTML,而是填充並返回一個 Greeting 物件。物件資料將直接作為 JSON 寫入 HTTP 響應。

此程式碼使用了 Spring 的 @RestController 註解,它將類標記為控制器,其中每個方法都返回一個領域物件而不是檢視。它是包含 @Controller@ResponseBody 的簡寫。

Greeting 物件必須轉換為 JSON。得益於 Spring 的 HTTP 訊息轉換器支援,你無需手動執行此轉換。由於 Jackson 2 存在於類路徑中,Spring 的 MappingJackson2HttpMessageConverter 會自動選擇來將 Greeting 例項轉換為 JSON。

執行服務

Spring Initializr 會為你建立一個應用程式類。在這種情況下,你無需進一步修改該類。以下列表(來自 src/main/java/com/example/restservice/RestServiceApplication.java)顯示了該應用程式類:

package com.example.restservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RestServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(RestServiceApplication.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 的,你無需處理任何底層或基礎設施的配置。

構建可執行 JAR

你可以使用 Gradle 或 Maven 從命令列執行應用程式。你還可以構建一個包含所有必要依賴項、類和資源的獨立可執行 JAR 檔案並執行它。構建可執行 JAR 可以輕鬆地在整個開發生命週期、跨不同環境等場景中將服務作為應用程式進行交付、版本控制和部署。

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

java -jar build/libs/gs-rest-service-0.1.0.jar

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

java -jar target/gs-rest-service-0.1.0.jar
此處描述的步驟會建立一個可執行的 JAR。你也可以構建一個經典的 WAR 檔案

將顯示日誌輸出。服務應在幾秒鐘內啟動並執行。

測試服務

服務啟動後,訪問 https://:8080/greeting,你應該會看到:

{"id":1,"content":"Hello, World!"}

透過訪問 https://:8080/greeting?name=User 提供一個 name 查詢字串引數。注意 content 屬性的值如何從 Hello, World! 變為 Hello, User!,如下面列表所示:

{"id":2,"content":"Hello, User!"}

此更改表明 GreetingController 中的 @RequestParam 配置按預期工作。name 引數已指定預設值 World,但可以透過查詢字串顯式覆蓋。

同時注意 id 屬性如何從 1 變為 2。這證明你在多個請求中使用的是同一個 GreetingController 例項,並且它的 counter 欄位在每次呼叫時都按預期遞增。

總結

恭喜!你剛剛使用 Spring 開發了一個 RESTful Web 服務。

獲取程式碼

免費

在雲端工作

在 Spring Academy 雲環境中完成本指南。

前往 Spring Academy