3.消費一個RESTful Web Service
這節課我們根據官網教程學習如何去消費(調用)一個 RESTful Web Service 。 原文鏈接 https://spring.io/guides/gs/consuming-rest/
本指南將引導您完成創建使用RESTful Web服務的應用程序的過程。
我們將會創建什麽?
您將構建一個使用Spring RestTemplate的應用程序來檢索http://gturnquist-quoters.cfapps.io/api/random中的隨機Spring Boot引用。
你需要準備什麽?
-
JDK1.8 或者更高
-
Gradle 4+ 或者 Maven 3.2+
-
你也可以直接導入Code 到你的IDE中
-
Spring Tool Suite (STS)
-
IntelliJ IDEA
-
如何完成這個指南?
方法有很多種,這裏我們僅通過STS來完成這個操作。
參考鏈接 https://spring.io/guides/gs/sts/
1. 打開我們的STS,點擊左上角的File————> New ————> Import Spring Getting Started Content
2. 我們這裏輸入 rest 來搜索出“Consuming Rest”
Tips:這裏勾選構建的類型是Maven項目,Code Sets 兩個都勾選,這樣會生成兩個Project.
complete 是表示已經寫好的code,initial是初始化空的項目,我們待會就在這個空的項目中進行修改和嘗試。
3. 通過完成項目設置,您可以創建一個使用RESTful服務的簡單應用程序。
一個RESTful服務已經在http://gturnquist-quoters.cfapps.io/api/random 站起來了。 它隨機提取有關Spring Boot的引用,並將它們作為JSON文檔返回。
如果您通過網絡瀏覽器或curl請求該URL,您將收到一個如下所示的JSON文檔:
{"type":"success","value":{"id":2,"quote":"With Boot you deploy everywhere you can find a JVM basically."}}
很簡單,但通過瀏覽器獲取時不會非常有用。以編程方式更有用的方式來使用REST Web服務。
為了幫助你完成這個任務,Spring提供了一個名為RestTemplate的方便的模板類。 RestTemplate使大多數RESTful服務與單行咒語交互。 它甚至可以將該數據綁定到自定義域類型。
4. 首先我們需要創建一個Domain 實體類
package hello; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class Quote { private String type; private Value value; public Quote() { } public String getType() { return type; } public void setType(String type) { this.type = type; } public Value getValue() { return value; } public void setValue(Value value) { this.value = value; } @Override public String toString() { return "Quote{" + "type=‘" + type + ‘\‘‘ + ", value=" + value + ‘}‘; } }
正如你所看到的,這是一個簡單的Java類,它有一些屬性和匹配的getter方法。 它使用Jackson JSON處理庫中的@JsonIgnoreProperties進行了註釋,以指示任何未綁定在此類型的屬性都應該被忽略。
為了直接將數據綁定到自定義類型,您需要指定變量的名稱與從API返回的JSON文檔中的鍵完全相同。 如果JSON文檔中的變量名和鍵不匹配,則需要使用@JsonProperty 註解來指定JSON文檔的確切鍵。
Tips: 註意上面返回的JSON中字段名稱是type和value 所以這裏我們定義的也是type和value.
5. 需要額外的類來嵌入內部報價本身。
package hello; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class Value { private Long id; private String quote; public Value() { } public Long getId() { return this.id; } public String getQuote() { return this.quote; } public void setId(Long id) { this.id = id; } public void setQuote(String quote) { this.quote = quote; } @Override public String toString() { return "Value{" + "id=" + id + ", quote=‘" + quote + ‘\‘‘ + ‘}‘; } }
Tips: 由於上面返回的JSON 中value 是一個對象,包含id和quote,所以這裏我們需要一個額外的類來定義它。
6.使這個應用程序變得可執行
雖然可以將此服務作為傳統WAR文件打包以部署到外部應用程序服務器,但下面演示的更簡單的方法會創建獨立應用程序。 您將所有內容打包到一個單獨的,可執行的JAR文件中,由一個良好的舊Java main()方法驅動。 一路上,您使用Spring的支持將Tomcat servlet容器作為HTTP運行時嵌入,而不是部署到外部實例。
現在您可以編寫使用RestTemplate的Application類來從Spring Boot報價服務中獲取數據。
package hello; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.client.RestTemplate; public class Application { private static final Logger log = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { // TODO Auto-generated method stub RestTemplate restTemplate = new RestTemplate(); Quote quote = restTemplate.getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote.class); log.info(quote.toString()); } }
Tips: 這裏我們可以看到通過一個RestTemplate 對象的方法,我們消費(調用)了另外一個Restfule web service 的數據。有了這種調用方式,我們便將不再需要編寫Httpclient方法來處理調用。
由於Jackson JSON處理庫位於類路徑中,RestTemplate將使用它(通過消息轉換器)將傳入的JSON數據轉換為Quote對象。 從那裏,Quote對象的內容將被記錄到控制臺。
在這裏,您只使用RestTemplate進行HTTP GET請求。 但RestTemplate還支持其他HTTP動詞,例如POST,PUT和DELETE。
打印控制臺如圖所示:
7. 使用Spring Boot管理應用程序生命周期
到目前為止,我們還沒有在我們的應用程序中使用過Spring Boot,但這樣做有一些優點,而且這並不難。 其中一個優點是我們可能希望讓Spring Boot管理RestTemplate中的消息轉換器,以便自定義很容易以聲明方式添加。 為此,我們在主類上使用@SpringBootApplication並轉換主要方法來啟動它,就像在任何Spring Boot應用程序中一樣。 最後,我們將RestTemplate移動到一個CommandLineRunner回調函數中,以便在啟動時由Spring Boot執行:
src/main/java/hello/Application.java
package hello; 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.web.client.RestTemplate; @SpringBootApplication public class Application { private static final Logger log = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { // TODO Auto-generated method stub SpringApplication.run(Application.class); // RestTemplate restTemplate = new RestTemplate(); // Quote quote = restTemplate.getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote.class); // log.info(quote.toString()); } @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.build(); } @Bean public CommandLineRunner run(RestTemplate restTemplate) throws Exception { return args -> { Quote quote = restTemplate.getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote.class); log.info(quote.toString()); }; } }
Tips: 剛才那種方式顯然並不優雅,我們註釋掉剛才的內容更換成使用Spring Boot 的code 來看下。通過這種方式顯然更優雅地調用了 其他Restful Web service.
RestTemplateBuilder由Spring註入,如果您使用它創建RestTemplate,那麽您將受益於Spring Boot中使用消息轉換器和請求工廠進行的所有自動配置。
我們還將RestTemplate提取到@Bean中以使其更易於測試(這樣可以更輕松地進行模擬)。
8.編譯生一個可執行的Jar
您可以使用Gradle或Maven從命令行運行應用程序。 或者您可以構建一個包含所有必需的依賴項,類和資源的可執行JAR文件,並運行該文件。 這使得在整個開發生命周期內跨越不同環境等,將服務作為應用程序發布,版本化和部署變得非常容易。
這一步我們使用STS中集成的工具來操作生成一個可執行的Jar,如圖所示:
之後我們應該能看到target 文件夾下多了一個文件
如果您正在使用Gradle,則可以使用./gradlew bootRun運行該應用程序。 或者您可以使用./gradlew構建構建JAR文件。 然後你可以運行JAR文件:
java -jar build/libs/gs-consuming-rest-0.1.0.jar
如果您使用的是Maven,則可以使用./mvnw spring-boot:run來運行該應用程序。 或者,您可以使用./mvnw clean包構建JAR文件。 然後你可以運行JAR文件:
java -jar target/gs-consuming-rest-0.1.0.jar
上述過程將創建一個可運行的JAR。 您也可以選擇構建經典的WAR文件。
您應該看到如下所示的輸出,並隨機引用:
如果你看到錯誤無法提取響應:沒有找到合適的HttpMessageConverter用於響應類型[class hello.Quote],那麽你有可能處於一個無法連接到後端服務的環境中(如果可以的話,它會發送JSON)。 也許你背後是一個公司代理? 嘗試將標準系統屬性http.proxyHost和http.proxyPort設置為適合您的環境的值。
好了本節課到這裏就結束了,通過本節課我們發現Spring Boot 中服務之間相互調用時最原生的其實是通過這種方式調用的。
源碼:https://github.com/geekxingyun/JavaEE-Framework-Sample/tree/master/Spring-Consume-Restful-Web-Service-Sample
3.消費一個RESTful Web Service