構建 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 開始

您可以使用這個預初始化專案,然後點選“生成”下載一個 ZIP 檔案。該專案已配置為符合本教程中的示例。

手動初始化專案

  1. 導航到 https://start.spring.io。此服務會為您拉取應用程式所需的所有依賴項,併為您完成大部分設定。

  2. 選擇 Gradle 或 Maven 以及您想要使用的語言。

  3. 在“Artifact”表單欄位中輸入“rest-service”。

  4. 點選 Dependencies 並選擇 Spring Web

  5. 單擊生成

  6. 下載生成的 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 記錄類或 Kotlin 資料類,如以下列表所示

Java
package com.example.restservice;

public record Greeting(long id, String content) { }
Kotlin
package com.example.restservice

data class Greeting(val id: Long, val content: String)
此應用程式使用 Jackson JSON 庫自動將 Greeting 型別的例項編組為 JSON。Jackson 預設包含在 Web 啟動器中。

建立資源控制器

在 Spring 構建 RESTful Web 服務的方法中,HTTP 請求由控制器處理。這些元件由 @RestController 註解標識,以下列表中所示的 GreetingController 類透過返回 Greeting 類的新例項來處理對 /greetingGET 請求

Java
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(defaultValue = "World") String name) {
		return new Greeting(counter.incrementAndGet(), template.formatted(name));
	}
}
Kotlin
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

private const val template = "Hello, %s!"

@RestController
class GreetingController {

    private val counter = AtomicLong()

    @GetMapping("/greeting")
    fun greeting(@RequestParam name: String = "World") =
        Greeting(counter.incrementAndGet(), template.format(name))

}

這個控制器簡潔而簡單,但其背後有很多事情發生。我們一步一步地進行分解。

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

還有其他 HTTP 動詞的配套註解(例如,用於 POST 的 @PostMapping)。還有一個 @RequestMapping 註解,它們都派生自該註解,並且可以作為同義詞(例如,@RequestMapping(method=GET))。

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

方法體的實現根據 counter 的下一個值建立並返回一個新的 Greeting 物件,其中包含 idcontent 屬性,並使用問候語 template 格式化給定的 name

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

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

Greeting 物件必須轉換為 JSON。多虧了 Spring 的 HTTP 訊息轉換器支援,您無需手動執行此轉換。由於 Jackson 位於類路徑上,Spring 的 JacksonJsonHttpMessageConverter 會自動選擇用於將 Greeting 例項轉換為 JSON。

執行服務

Spring Initializr 會為您建立一個應用程式類。在這種情況下,您無需進一步修改該類。以下列表顯示了 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);
	}

}
Kotlin
package com.example.restservice

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class RestServiceApplication

fun main(args: Array<String>) {
	runApplication<RestServiceApplication>(*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