Spring Framework 5.0 M5 更新

工程 | Rossen Stoyanchev | 2017 年 2 月 23 日 | ...

Spring Framework 5.0 的第五個也是最後一個里程碑的更新...

Spring MVC 與 Spring WebFlux

名稱 *Spring MVC* 廣為人知且被廣泛使用,但可能有些人會驚訝,實際上並沒有名為此名稱的專案或獨立發行版本。 相反地,它是 Spring Framework 發行版本中名為 `spring-webmvc` 的模組。 這是另一個小知識問題。您是否知道該模組中的頂層套件沒有 "mvc"? 相反地,它被稱為 `org.springframework.web.servlet`。 實際上,這些都是我們不必記住的細節。 重要的是我們有一個簡短且令人難忘的名稱來指代 *Spring 基於 Servlet 堆疊* 的 Web 框架。

Spring 的反應式堆疊 Web 框架是 5.0 中的新增功能,它具有完整的反應性和非阻塞性。 它適用於使用少量執行緒的事件迴圈樣式處理。 它在 Servlet 容器(Tomcat、Jetty、Servlet 3.1+)和非 Servlet 執行階段(Netty、Undertow)上都受支援,因為此堆疊的通用基礎不是 Servlet API,而是建立在反應式串流和 Reactor 專案上的非阻塞替代方案。 如果您想知道,Servlet 3.1 不是能夠進行非阻塞 I/O 嗎? 是的,它是,我們支援在 Servlet 3.1 容器上執行,但 Servlet API 的其餘部分是命令式樣式,無法在反應式、非阻塞堆疊中使用。

到目前為止,我們缺少反應式 Web 堆疊的專用名稱,該堆疊同時支援 Spring MVC 註釋(即 @Controller@RequestMapping)和新的函數式程式設計模型,這使得討論和清楚地區分程式設計模型和堆疊具有挑戰性。 在我們的 milestone 5 中,spring-web-reactive 模組已重新命名為 spring-webflux - 從 Spring Web Reactive API 核心的 Flux 反應式類型 中汲取靈感和簡潔性,我們較低層級的反應式 HTTP 抽象位於通用的 spring-web 模組中。 因此,我們現在有並排的 spring-webmvcspring-webflux 模組,我們將其稱為 *Spring (Web)MVC* 和 *Spring WebFlux*。 如果您想知道:新模組中的頂層套件是 org.springframework.web.reactive

現在介紹此領域中的其他一些主要更新...

WebClient

`WebClient` 是 `RestTemplate` 的反應式、非阻塞替代方案,它為 *反應式* 和 *Servlet 堆疊* 應用程式增加了價值。 它可以輕鬆處理非同步和串流案例。

在 M5 中,我們進行了重大改進,消除了使用靜態匯入來指定請求詳細資訊和執行交換的需求

WebClient webClient = WebClient.create();

Mono<Person> person = webClient.get()
        .uri("http://localhost:8080/persons/42")
        .accept(MediaType.APPLICATION_JSON)
        .exchange()
        .then(response -> response.bodyToMono(Person.class));

如果所有請求都有一個通用基本 URL,則可以預先設定一次

WebClient webClient = WebClient.create("http://localhost:8080");

Mono<Person> person = webClient.get()
        .uri("/persons/{id}", 42)
        .accept(MediaType.APPLICATION_JSON)
        .exchange()
        .then(response -> response.bodyToMono(Person.class));

也可以使用 UriBuilder 獲得程式化的控制

Mono<Person> person = webClient.get()
        .uri(builder -> builder.path("/persons/{id}").build("42"))
        .accept(MediaType.APPLICATION_JSON)
        .exchange()
        .then(response -> response.bodyToMono(Person.class));

WebTestClient

`spring-test` 模組中的新 `WebTestClient` 構成了 Spring WebFlux 整合測試支援的基礎。 它封裝了 `WebClient` 並公開了用於整合測試的 API。 與 Spring MVC Test 中的 `MockMvc` 類似,新的測試用戶端不需要實際運行的伺服器,並且可以使用模擬請求和回應直接繫結到 WebFlux 伺服器基礎結構:````java WebTestClient client = WebTestClient .bindToController(new PersonController()) .build();

client.get().uri("/persons/42") .exchange() .expectStatus().isOk() .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8) .expectBody(Person.class).value().isEqualTo(new Person("John"));


The new test client however can also run against a live server:
````java
WebTestClient client = WebTestClient
        .bindToServer().baseUrl("http://localhost:8080")
        .build();

// Same test case...

串流也很容易測試,可能使用 Reactor StepVerifier

FluxExchangeResult<Person> result = client.get().uri("/persons")
        .accept(TEXT_EVENT_STREAM)
        .exchange()
        .expectStatus().isOk()
        .expectHeader().contentType(TEXT_EVENT_STREAM)
        .expectBody(Person.class)
        .returnResult();

StepVerifier.create(result.getResponseBody())
        .expectNext(new Person("Jane"), new Person("Jason"))
        .expectNextCount(3)
        .consumeNextWith(p -> assertEquals("John", p.getName()))
        .thenCancel()
        .verify();

路徑模式剖析器

M5 版本新增了一個新的 `PathPatternParser` 來替代 `AntPathMatcher`,它可以使用更有效率的請求對應剖析模式表示法,並支援非常方便的 `"{*foo}" ` URI 變數語法來擷取模式結尾處的任意數量的區段。

作為第一步,新的 ParsingPathMatcher 實作已經允許將新的 PathPatternParser 輕鬆插入到 Spring MVC 和 Spring WebFlux 對應中。 作為邁向 RC1 的下一步,目標是擁有一個模式登錄檔,以便針對請求路徑的剖析表示法進行比對。

伺服器發送事件和 JSON 串流

使用 Spring WebFlux 可以輕鬆支援串流:````java @GetMapping(path = "/persons", produces = "text/event-stream") FluxgetPersons() { return this.repository.getPersons(); } ```` 上述程式碼會將資料以伺服器發送事件 (SSE) 的形式串流到瀏覽器:```` data: {"name":"Jane"} data: {"name":"John"} ... ````

但是對於以下情況應該怎麼辦

@GetMapping("/persons")
Flux<Person> getPersons() {
    return this.repository.getPersons();
}

我們可以串流個別的 JSON 物件,但這不會是有效的 JSON 文件,而且除了使用伺服器發送事件或 WebSocket 之外,瀏覽器用戶端沒有其他方法可以使用串流。

預設情況下,Flux<Person> 將產生 JSON 陣列

[{"name":"Jane"},{"name":"John"},...]

非瀏覽器用戶端(例如 WebClient)可以要求內容類型 application/stream+json,回應將是類似於伺服器發送事件的 JSON 物件串流,但沒有額外的格式設定

{"name":"Jane"}
{"name":"John"}
...

結論

我要感謝所有嘗試 Spring Framework 5.0 並提供回饋的人,尤其是在新的反應式功能方面。 請繼續這樣做。 與往常一樣,即使是很小的意見也可能非常寶貴,因為它們使我們從不同的角度重新審視設計選擇。

如果您本週從 DevNexus 閱讀此內容,請不要錯過 觀看令人驚嘆的 Josh Long 現場編寫反應式 Web 應用程式的機會,以及 Reactor 團隊核心成員 Simon Baslé 的 Reactor 3 演講

取得 Spring 電子報

透過 Spring 電子報保持聯繫

訂閱

搶先一步

VMware 提供培訓和認證,以加速您的進展。

瞭解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔。

瞭解更多

即將舉行的活動

查看 Spring 社群中所有即將舉行的活動。

查看全部