1. 程式人生 > >實戰SpringCloud響應式微服務系列教程(第九章)使用Spring WebFlux構建響應式RESTful服務

實戰SpringCloud響應式微服務系列教程(第九章)使用Spring WebFlux構建響應式RESTful服務

本文為實戰SpringCloud響應式微服務系列教程第九章,講解使用Spring WebFlux構建響應式RESTful服務。建議沒有之前基礎的童鞋,先看之前的章節,章節目錄放在文末。

從本節開始我們將正式進入構建響應式服務的世界。在Spring boot的基礎上,我們將引入全新的Spring WebFlux框架。

WebFlux名稱中的Flux來源於上章節介紹的來自Reactor框架中的Flux元件。該框架中包含了對響應式HTTP、伺服器推送事件以及Websocket的客戶端和服務端的支援。

在構架響應式服務上,WebFlux支援兩種不同的程式設計模型:

  • 第一種是與SpringMvc中同樣使用的基於java註解的方式;
  • 第二種是基於java8中提供的lambda表示式的函數語言程式設計模型。

1.1使用 Spring Initializer初始化響應式web應用

建立WebFlux應用最簡單的方式便是使用Spring boot提供的Spring Initializer初始化模板。

直接訪問Spring Initializer網站(http://start.spring.io),選擇建立一個maven或者Gradle專案並制定相應的Group和Artifact,然後在新增依賴中選擇maven進行程式碼依賴管理。

開啟所下載專案中的pom檔案,會找到如下依賴。

  • spring-boot-starter-webflux構成響應式web程式開發的基礎;
  • spring-boot-starter-test是包含JUnit、Spring boot Test、Mockito、AssertJ、JSONAssert以及Hamcerst等工具在內的測試元件庫;
  • reactor-test則是用來測試Reactor框架的測試元件;
  • spring-boot-starter-data-mongodb-reactive和spring-boot-starter-data-redis-reactive則是響應式資料訪問元件。

 

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <!--Lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
            <version>1.16.22</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
        </dependency>
        <!--  redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

 

至此,使用Spring WebFlux構架響應式服務的基礎環境已經準備完畢。

關於Spring WebFlux和傳統的SpringMvc的關係可以自行百度瞭解,這裡不做過多介紹。

1.2使用註解程式設計模型建立響應式RESTful服務

基於註解程式設計模型來建立響應式RESTful服務與使用傳統SpringMvc非常類似。通過掌握響應式程式設計的基本概念和技巧,在webflux中使用這種程式設計模型幾乎沒有任何學習成本。

構建第一個響應式RESTful服務

第一個響應式RESTful服務來自於對之前HelloController示例進行改造,改造之後的程式碼如下:

 

@RestController
public class Helloontroller{
     @GetMapping("/")
     public Mono<String> index(){
           return Mono.just("Hello Spring Boot");
     }
}

 

以上程式碼只有一個地方值得注意,即index()方法的返回值型別是Mono<String>型別,其中包含的字串"Hello Spring Boot"或作為HTTP的響應內容。

在瀏覽器中訪問會得到如下結果:

從以上程式碼可以看到使用Spring WebFlux和使用 Spring Mvc的不同在於,WebFlux所使用的型別是與響應式程式設計相對應的Flux和Mono物件,而不是簡單的POJO,對於簡單的Hello Word實力來說,這兩個之間並沒有什麼太大的差別。

但是對於複雜的應用來說,響應式程式設計的背壓機制就會體現出來,可以帶來整體效能的提升。在後續講解中會有完整示例程式碼。

1.3使用函式式模型建立響應式RESTful服務

這部分內容與傳統的SpringMvc構建RESTful服務有較大的差別。

(1)函數語言程式設計模型

在Spring WebFlux中,函數語言程式設計模型的核心概念是Router Functions,對標@Controller@RequestMapping等標準的Spring Mvc註解。

Router Functions提供一套函式式的API,用於建立Router和Handler物件。其中我們可以簡單的把Handler對應為Controller,把Router對應為RequestMapping。

當我們發起一個遠端呼叫時,傳入的HTTP請求由HandlerFunction處理,HandlerFunction本質上是一個接收ServerRequest並返回一個Mono<ServerResponse>的函式。ServerRequest和ServerResponse是一個不可變的介面,用來提供對底層HTTTP訊息的友好訪問。

具體程式碼示例如下:

 

public class HelloWordHandlerFunction impllements HandlerFunction<ServerResponse>{
    @Override
    public Mono<ServerResponse> handle(ServerRequest request){
         return ServerResponse.ok().body(BodyInserters.fromObject("Hello Word"))
    }
}

 

關於ServerRequest和ServerResponse我們在這裡不做過多介紹,詳細瞭解可查閱相關資料。

以上程式碼將ServerRequest和ServerResponse組合到一起建立了HandlerFunction。HandlerFunction是一個介面,可以通過實現該介面中的handl()方法來建立定製化的請求響應處理機制。

通常我們會針對某個領域實體物件編寫多個處理函式,所以推薦將多個處理函式分組到一個專門的Handler類中。例如我們編寫一個PersonHandler專門實現各種針對Person領域物件的處理函式。

程式碼如下:

 

public class PersonHandler{
    @Autowired
    private PersonService personService;
    public Mono<ServerResponse> getPersons(ServerRequest request){
        return ServerResponse.ok().body(this.personService.getPersons(),Person.class)
   }
}

 

(2)RouterFunction

上面我們已經通過HandlerFunction建立了請求的邏輯處理,接下來需要把具體的邏輯關聯起來,RouterFunction可以幫助我們實現這一個目標。RouterFunction將傳入的請求路由傳入到具體的函式,它接收ServerRequest 並返回一個Mono<ServerResponse>

如果請求與特定路由匹配則返回處理函式的結果,否則返回一個空的Mono物件。RouterFunction與@ReuestMapping類似。程式碼如下:

 

public class personRouter{
@Bean
public RouterFunction<ServerResponse> routerPerson(PersonHandler personHandler){
      return RouterFunctions.route(RequestPredicates.GET("/person")
      .add(RequestPredicates.accept(MediaType.APPLICATION_JSON)),
      personHandler::getPersons)
}
}

 

本章節完

系列章節目錄

實戰SpringCloud響應式微服務系列教程(第一章)

實戰SpringCloud響應式微服務系列教程(第二章)

實戰SpringCloud響應式微服務系列教程(第三章)

實戰SpringCloud響應式微服務系列教程(第四章)

實戰SpringCloud響應式微服務系列教程(第五章)

實戰SpringCloud響應式微服務系列教程(第六章)

實戰SpringCloud響應式微服務系列教程(第七章)

實戰SpringCloud響應式微服務系列教程(第八