實戰SpringCloud響應式微服務系列教程(第八章)構建響應式RESTful服務
本文為實戰SpringCloud響應式微服務系列教程第八章,講解構建響應式RESTful服務。建議沒有之前基礎的童鞋,先看之前的章節,章節目錄放在文末。
1.使用springboot2.1.4構建RESTful風格服務
Springboot的設計是用來簡化Spring應用程式的初始搭建和開發過程,為了實現這種簡化效果,Springboot繼承了眾多第三方庫,並大量使用約定優於配置的設計理念,通過特定的方式使得開發人員不再需要定義繁雜而且多餘的配置內容。
1.1基於Springboot的第一個RESTful服務
微服務架構推崇採用RESTful風格實現服務之間的互動。關於RESTful,很多開發人員在知識體系上的一些誤解和不足。我們先對RESTful風格做一個簡單的介紹,然後詳細闡述使用SpringBoot構建單個RESTful服務的過程。
(1)RESTful風格簡介
REST提出了一組建構約束條件和原則,滿足這些約束條件和原則的設計風格就是RESTful。
現實世界中的事物都可以被認為一種資源,我們可以根據這些約束條件和原則設計以資源為中心的服務。REST中最重要的一條原則就是客戶端和伺服器之間的互動無狀態性。
從客戶端到伺服器的每個請求都必須包含理解該請求所必需的資訊,無狀態請求可以由任何可用服務實現響應,十分適合微服務架構的執行環境。所以RESTful代表的實際上是一種風格,而不是一種設計和架構模式,更不是一種具體的技術體系。
關於RESTful另一個比較容易忽視的核心概念是HATEOAS(Hypermedia as the Engine of Application State,基於超媒體的應用狀態引擎)。要解釋HATEOAS的概念,先要解釋什麼是超媒體。
我們已經知道什麼是超連結以及什麼是超文字,其中超文字的特有優勢是擁有超連結。如果把超連結映入到多媒體中,就得到了超媒體。因此關鍵要素還是超連結。使用過超媒體作為應用引擎狀態,意思就是應用引擎的狀態變更由客戶端訪問不同的超媒體資源來驅動。
使用HATEOAS表現服務請求響應的風格如下,可以看到這裡多了_links屬性,其中有一個self.href連結指向當前user資源。
GET http://api.example.com/users/tianyalan Content-type:application/json { _links:{ self:{ href:"/users/tianyalan" } } "id":"tianyalan", "name":"tianyalan", "email":"[email protected]" }
HATEOAS在spring boot和spring cloud中應用也非常廣泛,例如springboot提供了應用監控元件Actuator,通過Actuator可以獲取springboot應用程式當前的執行狀態,我們將在後續章節中詳細介紹Actuator元件。
Actuator元件對外暴露的也是一些http端點,訪問這些端點返回的資料跟常見的RESTful風格有所不同,這就是HATEOAS風格,所以可以參考相關資料進一步瞭解。
(2)引入spring-boot-starter-web工程
spring boot提供了一系列starter工程來簡化各元件之間的依賴關係。
例如在springboot中開發基於RESTful風格的端點時,通常會引入spring-boot-starter-web這個工程,而開啟這個工程會發現裡面實際上只定義瞭如下所示的一些pom依賴,其中包括所有我們能夠預見到的元件,例如非常經典的spring-web,spring-webmvc元件,可以看到spring-boot-starter-web還是基於這兩個元件構建web請求響應流程的。
另外還包含了基於JSON序列化和反序列化的jackson-databind元件,以及啟動內建tomcat伺服器的spring-boot-starter-tomcat元件。
- org.springframework.boot:spring-boot-starter
- org.springframework.boot:spring-boot-starter-tomcat
- org.springframework.boot:spring-boot-starter-validation
- org.springframework.boot:spring-web
- org.springframework.boot:spring-webmvc
- org.fasterxml.jackson.core:jackson-databind
引入spring-boot-starter-web就像引入一個普通的maven依賴一樣,程式碼如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
一旦spring-boot-starter-web元件引入完畢,我們就可以充分利用springboot的自動裝配機制開發單個服務。
(3)Application類
使用springboot的首要條件是構建一個Application啟動類。程式碼如下:
@SpringBootApplication public class SoulApplication { public static void main(String[] args) { SpringApplication.run(SoulApplication.class, args); } }
結構比較固化。
顯然以上程式碼關鍵的是@SpringBootApplication
註解。springboot使用@SpringBootApplication
註解來告訴spring容器具備該註解的類是整個spring容器中所有javaBean物件的入口,而具備該註解的類在springboot中就是Application類。
在上面程式碼中,SoulApplication類就是整個容器的Application類。
@SpringBootApplication註解在指定Application類的同時,還會自動掃描與當前類同級以及子包下的@Component
、@Service
、@Repository
、@Controller
、@Entity
等註解,並把這些註解對應的類轉換為Bean物件全部載入到Spring容器中管理起來。
@SpringBootApplication
註解的定義如下,我們可以看到該註解實際上由三個註解組合而成,分別是@Configuration
、@EnableAutoConfigguration
和@ComponentScan
。
@Target(ElementType.TYPE) @Retenation(RetentionPolicy.PUNTIME) @Documented @Inherited @Configuration @EnableAutoConfigguration @ComponentScan public @interface SpringBootApplication
在Spring 中@Configuration
比較常見,提供javaConfig配置類實現。而@ComponentScan
則掃描@Component
等註解,幫相關的javaBean定義批量載入到IOC容器中。@EnableAutoConfigguration
最終會使用JDK提供的SPI機制來實現類的動態載入。
關於@EnableAutoConfigguration
註解更多的可以參考相關的資料。
我們還注意到在上面的程式碼示例中包含一個main函式並執行了ApplicationContext物件,我們可以根據需求對該ApplicationContext物件做響應處理。
(4)Controller類
Application類提供了Springboot程式的入口,相當於應用程式擁有了最基本的骨架。接下來我們就可以新增各種業務相關的訪問入口,表現在RESTful風格上也就是一系列的Controller類所代表的的HTTP端點。
這裡的Controller和springMvc的Controller在概念上是一致的。最簡單的Controller如下:
@RestController public class HelloController{ @GetMapping("/") public String index(){ return "Hello Spring Boot"; } }
以上程式碼包含了@RestController
和@GetMapping("/")
兩個註解。我們知道在springMvc中包含了@Controller
註解用來表示當前類是一個servlet。
而@RestController
繼承了@Controller
,它告訴Springboot這是一個基於RESTful風格的HTTP端點,並會自動使用JSON實現HTTP請求和響應的序列化和反序列化操作。至於@GetMapper
類似@RequestMapping
,指定請求方式為GET。這裡不做多餘介紹。
以下程式碼展示了一個典型的Controller,在Controller中通過靜態的業務程式碼完成了根據商品編號,獲取商品資訊的業務流程。
這裡用到了兩層Mapping註解,在服務層級定義了服務的版本和路徑,分別為v1和products;而在操作級別有定義了HTTP請求方法的具體路徑及引數資訊。
@RestController @RequestMapping("/v1/products") public class Productontroller{ @GetMapping("/{productCode}") public Product getProduct(@PathVariable String productCode){ Product product = new Product(); product .setId(1L); product .setPrice(100F); product .setProductCode("product001"); product .setProductName("product"); return product; } }
系列章節目錄
實戰SpringCloud響應式微服務系列教程(第一章)
實戰SpringCloud響應式微服務系列教程(第二章)
實戰SpringCloud響應式微服務系列教程(第三章)
實戰SpringCloud響應式微服務系列教程(第四章)
實戰SpringCloud響應式微服務系列教程(第五章)
實戰SpringCloud響應式微服務系列教程(第六章)
實戰SpringCloud響應式微服務系列教程(第七章)