呼叫 RESTful Web Service

本指南將引導您完成建立一個呼叫 RESTful web service 的應用的過程。

您將構建什麼

您將構建一個應用,該應用使用 Spring 的 RestTemplatehttps://:8080/api/random 獲取一個隨機的 Spring Boot 引用。

您需要什麼

如何完成本指南

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

從頭開始,請轉到從 Spring Initializr 開始

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

完成後,您可以將您的結果與 gs-consuming-rest/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 或其他編輯器中開啟它。

獲取 REST 資源

專案設定完成後,您可以建立一個呼叫 RESTful service 的簡單應用。

在此之前,您需要一個 REST 資源的來源。我們提供了一個此類服務的示例,地址是https://github.com/spring-guides/quoters。您可以在單獨的終端中執行該應用,並透過https://:8080/api/random訪問結果。該地址會隨機獲取一個關於 Spring Boot 的引用,並將其作為 JSON 文件返回。其他有效的地址包括https://:8080/api/(用於所有引用)和https://:8080/api/1(用於第一個引用)、https://:8080/api/2(用於第二個引用),依此類推(目前最多 10 個)。

如果您透過 web 瀏覽器或 curl 請求該 URL,您將收到一個類似如下的 JSON 文件

{
   type: "success",
   value: {
      id: 10,
      quote: "Really loving Spring Boot, makes stand alone Spring apps easy."
   }
}

這足夠簡單,但透過瀏覽器或 curl 獲取時並不是特別有用。

更實用的呼叫 REST web service 的方法是程式設計方式。為了幫助您完成此任務,Spring 提供了一個方便的模板類,稱為 RestTemplateRestTemplate 使得與大多數 RESTful 服務互動變得非常簡單(通常只需一行程式碼)。它甚至可以將資料繫結到自定義的領域型別。

首先,您需要建立一個領域類來包含所需的資料。以下清單顯示了 Quote 記錄類,您可以將其用作您的領域類

src/main/java/com/example/consumingrest/Quote.java

package com.example.consumingrest;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public record Quote(String type, Value value) { }

這個簡單的 Java 記錄類使用 Jackson JSON 處理庫的 @JsonIgnoreProperties 註解,表明應該忽略此型別中未繫結的任何屬性。

要將資料直接繫結到自定義型別,您需要指定變數名與 API 返回的 JSON 文件中的 key 完全相同。如果您的變數名與 JSON 文件中的 key 不匹配,可以使用 @JsonProperty 註解指定 JSON 文件的確切 key。(此示例中的每個變數名都與 JSON key 匹配,因此此處不需要該註解。)

您還需要一個額外的類,用於嵌入內部引用本身。Value 記錄類滿足了這一需求,並在以下清單中顯示(位於 src/main/java/com/example/consumingrest/Value.java

package com.example.consumingrest;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public record Value(Long id, String quote) { }

這使用了相同的註解,但對映到其他資料欄位。

完成應用

Initializr 會建立一個包含 main() 方法的類。以下清單顯示了 Initializr 建立的類(位於 src/main/java/com/example/consumingrest/ConsumingRestApplication.java

package com.example.consumingrest;

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

@SpringBootApplication
public class ConsumingRestApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumingRestApplication.class, args);
	}

}

現在您需要向 ConsumingRestApplication 類新增一些其他內容,以便它能夠顯示來自我們的 RESTful 來源的引用。您需要新增:

  • 一個 logger,用於將輸出傳送到日誌(在本示例中為控制檯)。

  • 一個 RestTemplate,它使用 Jackson JSON 處理庫來處理傳入的資料。

  • 一個 CommandLineRunner,它在啟動時執行 RestTemplate(並因此獲取我們的引用)。

以下清單顯示了最終完成的 ConsumingRestApplication 類(位於 src/main/java/com/example/consumingrest/ConsumingRestApplication.java

package com.example.consumingrest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class ConsumingRestApplication {

	private static final Logger log = LoggerFactory.getLogger(ConsumingRestApplication.class);

	public static void main(String[] args) {
		SpringApplication.run(ConsumingRestApplication.class, args);
	}

	@Bean
	public RestTemplate restTemplate(RestTemplateBuilder builder) {
		return builder.build();
	}

	@Bean
	@Profile("!test")
	public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
		return args -> {
			Quote quote = restTemplate.getForObject(
					"https://:8080/api/random", Quote.class);
			log.info(quote.toString());
		};
	}
}

最後,您需要設定伺服器埠。quoter 應用使用了預設的伺服器埠 8080,因此本應用不能再使用同一個埠。您可以透過在應用屬性檔案(Initializr 為您建立的)中新增以下行將伺服器埠設定為 8081

server.port=8081

執行應用

您可以從命令列使用 Gradle 或 Maven 執行該應用。您也可以構建一個包含所有必需依賴項、類和資源的單個可執行 JAR 檔案,並執行它。構建可執行 JAR 可以輕鬆地在整個開發生命週期、跨不同環境等階段,將服務作為應用進行分發、版本管理和部署。

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

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

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

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

您應該看到類似於以下的輸出,但引用是隨機的

2019-08-22 14:06:46.506  INFO 42940 --- [           main] c.e.c.ConsumingRestApplication           : Quote{type='success', value=Value{id=1, quote='Working with Spring Boot is like pair-programming with the Spring developers.'}}
如果您看到類似這樣的錯誤:Could not extract response: no suitable HttpMessageConverter found for response type [class com.example.consumingrest.Quote],則可能是您所處的環境無法連線到後端服務(如果您能連線到它,它會發送 JSON)。也許您在公司代理後面。請嘗試將 http.proxyHosthttp.proxyPort 系統屬性設定為適合您環境的值。

總結

恭喜!您剛剛使用 Spring Boot 開發了一個簡單的 REST 客戶端。

獲取程式碼