spring5新特性全面介紹
前方:對於很多開發人員來說,目前大都還在使用spring4的時候,而spring5早已經發布。雖然你可能暫時還沒有使用到spring5,但還是需要對其有個大概的瞭解。
Spring 5 於 2017 年 9 月釋出了通用版本 (GA),它標誌著自 2013 年 12 月以來第一個主要 Spring Framework 版本。它提供了一些人們期待已久的改進,還採用了一種全新的程式設計範例,以反應式宣言中陳述的反應式原則為基礎。
這個版本是很長時間以來最令人興奮的 Spring Framework 版本。Spring 5 相容 Java?8 和 JDK 9,它集成了反應式流,以便提供一種顛覆性方法來實現端點和 Web 應用程式開發。
誠然,反應式程式設計不僅是此版本的主題,還是令許多開發人員激動不已的重大特性。人們對能夠針對負載波動進行無縫擴充套件的災備和響應式服務的需求在不斷增加,Spring 5 很好地滿足了這一需求。
我還會簡要介紹測試和效能增強,最後介紹對 Spring 核心和容器的一般性修訂。
升級到 Java SE 8 和 Java EE 7
直到現在,Spring Framework 仍支援一些棄用的 Java 版本,但 Spring 5 已從舊包袱中解放出來。為了充分利用 Java 8 特性,它的程式碼庫已進行了改進,而且該框架要求將 Java 8 作為最低的 JDK 版本。
Spring 5 在類路徑(和模組路徑)上完全相容 Java 9,而且它通過了 JDK 9 測試套件的測試。對 Java 9 愛好者而言,這是一條好訊息,因為在 Java 9 釋出後,Spring 能立即使用它。
在 API 級別上,Spring 5 相容 Java EE 8 技術,滿足對 Servlet 4.0、Bean Validation 2.0 和全新的 JSON Binding API 的需求。對 Java EE API 的最低要求為 V7,該版本引入了針對 Servlet、JPA 和 Bean Validation API 的次要版本。
反應式程式設計模型
Spring 5 最令人興奮的新特性是它的反應式程式設計模型。Spring 5 Framework 基於一種反應式基礎而構建,而且是完全非同步和非阻塞的。只需少量的執行緒,新的事件迴圈執行模型就可以垂直擴充套件。
該框架採用反應式流來提供在反應式元件中傳播負壓的機制。負壓是一個確保來自多個生產者的資料不會讓使用者不堪重負的概念。
Spring WebFlux 是 Spring 5 的反應式核心,它為開發人員提供了兩種為 Spring Web 程式設計而設計的程式設計模型:一種基於註解的模型和 Functional Web Framework (WebFlux.fn)。
基於註解的模型是 Spring WebMVC 的現代替代方案,該模型基於反應式基礎而構建,而 Functional Web Framework 是基於 @Controller 註解的程式設計模型的替代方案。這些模型都通過同一種反應式基礎來執行,後者調整非阻塞 HTTP 來適應反應式流 API。
使用註解進行程式設計
WebMVC 程式設計師應該對 Spring 5 的基於註解的程式設計模型非常熟悉。Spring 5 調整了 WebMVC 的@Controller 程式設計模型,採用了相同的註解。
在清單 1 中,BookController 類提供了兩個方法,分別響應針對某個圖書列表的 HTTP 請求,以及針對具有給定 id 的圖書的 HTTP 請求。請注意 resource 方法返回的物件(Mono 和 Flux)。這些物件是實現反應式流規範中的 Publisher 介面的反應式型別。它們的職責是處理資料流。Mono 物件處理一個僅含 1 個元素的流,而 Flux 表示一個包含 N 個元素的流。
清單 1. 反應式控制器
@RestController public class BookController { @GetMapping("/book") Flux<Book> list() { return this.repository.findAll(); } @GetMapping("/book/{id}") Mono<Book> findById(@PathVariable String id) { return this.repository.findOne(id); } // Plumbing code omitted for brevity }
這是針對 Spring Web 程式設計的註解。現在我們使用函式式 Web 框架來解決同一個問題。
函數語言程式設計
Spring 5 的新函式式方法將請求委託給處理函式,這些函式接受一個伺服器請求例項並返回一種反應式型別。清單 2 演示了這一過程,其中 listBook 和 getBook 方法類似於清單 1 中的功能。
清單 2. 清單 2.BookHandler 函式類
public class BookHandler { public Mono<ServerResponse> listBooks(ServerRequest request) { return ServerResponse.ok() .contentType(APPLICATION_JSON) .body(repository.allPeople(),Book.class); } public Mono<ServerResponse> getBook(ServerRequest request) { return repository.getBook(request.pathVariable("id")) .then(book -> ServerResponse.ok() .contentType(APPLICATION_JSON) .body(fromObject(book))) .otherwiseIfEmpty(ServerResponse.notFound().build()); } // Plumbing code omitted for brevity }
通過路由函式來匹配 HTTP 請求謂詞與媒體型別,將客戶端請求路由到處理函式。清單 3 展示了圖書資源端點 URI 將呼叫委託給合適的處理函式:
清單 3. Router 函式
BookHandler handler = new BookHandler(); RouterFunction<ServerResponse> personRoute = route( GET("/books/{id}") .and(accept(APPLICATION_JSON)),handler::getBook) .andRoute( GET("/books") .and(accept(APPLICATION_JSON)),handler::listBooks);
這些示例背後的資料儲存庫也支援完整的反應式體驗,該體驗是通過 Spring Data 對反應式 Couchbase、Reactive MongoDB 和 Cassandra 的支援來實現的。
使用 REST 端點執行反應式程式設計
新的程式設計模型脫離了傳統的 Spring WebMVC 模型,引入了一些很不錯的新特性。
舉例來說,WebFlux 模組為 RestTemplate 提供了一種完全非阻塞、反應式的替代方案,名為WebClient。清單 4 建立了一個 WebClient,並呼叫 books 端點來請求一本給定 id 為 1234 的圖書。
清單 4. 通過 WebClient 呼叫 REST 端點
Mono<Book> book = WebClient.create("http://localhost:8080") .get() .url("/books/{id}",1234) .accept(APPLICATION_JSON) .exchange(request) .then(response -> response.bodyToMono(Book.class));
HTTP/2 支援
HTTP/2 幕後原理:要了解 HTTP/2 如何提高傳輸效能,減少延遲,並幫助提高應用程式吞吐量,從而提供經過改進的豐富 Web 體驗,請查閱我的有關這項期待已久的升級的文章。
Spring Framework 5.0 將提供專門的 HTTP/2 特性支援,還支援人們期望出現在 JDK 9 中的新 HTTP 客戶端。儘管 HTTP/2 的伺服器推送功能已通過 Jetty servlet 引擎的 ServerPushFilter 類向 Spring 開發人員公開了很長一段時間,但如果發現 Spring 5 中開箱即用地提供了 HTTP/2效能增強,Web 優化者們一定會為此歡呼雀躍。
Java EE Servlet 規範預計將於 2017 年第 4 季度釋出,Servlet 4.0 支援將在 Spring 5.1 中提供。到那時,HTTP/2 特性將由 Tomcat 9.0、Jetty 9.3 和 Undertow 1.4 原生提供。
Kotlin 和 Spring WebFlux
Kotlin 是一種來自 JetBrains 的面向物件的語言,它支援函數語言程式設計。它的主要優勢之一是與 Java 有非常高的互操作性。通過引入對 Kotlin 的專門支援,Spring 在 V5 中全面吸納了這一優勢。它的函數語言程式設計風格與 Spring WebFlux 模組完美匹配,它的新路由 DSL 利用了函式式 Web 框架以及乾淨且符合語言習慣的程式碼。可以像清單 5 中這樣簡單地表達端點路由:
清單 5. Kotlin 的用於定義端點的路由 DSL
@Bean fun apiRouter() = router { (accept(APPLICATION_JSON) and "/api").nest { "/book".nest { GET("/",bookHandler::findAll) GET("/{id}",bookHandler::findOne) } "/video".nest { GET("/",videoHandler::findAll) GET("/{genre}",videoHandler::findByGenre) } } }
使用 Kotlin 1.1.4+ 時,還添加了對 Kotlin 的不可變類的支援(通過帶預設值的可選引數),以及對完全支援 null 的 API 的支援。
使用 Lambda 表示式註冊 bean
作為傳統 XML 和 JavaConfig 的替代方案,現在可以使用 lambda 表示式註冊 Spring bean,使 bean 可以實際註冊為提供者。清單 6 使用 lambda 表示式註冊了一個 Book bean。
清單 6. 將 Bean 註冊為提供者
GenericApplicationContext context = new GenericApplicationContext(); context.registerBean(Book.class,() -> new Book(context.getBean(Author.class)) );
Spring WebMVC 支援最新的 API
全新的 WebFlux 模組提供了許多新的、令人興奮的功能,但 Spring 5 也迎合了願意繼續使用 Spring MVC 的開發人員的需求。Spring 5 中更新了模型-檢視-控制器框架,以相容 WebFlux 和最新版的Jackson 2.9 和 Protobuf 3.0,甚至包括對新的 Java EE 8 JSON-Binding API 的支援。
除了 HTTP/2 特性的基礎伺服器實現之外,Spring WebMVC 還通過 MVC 控制器方法的一個引數來支援 Servlet 4.0 的 PushBuilder。最後,WebMVC 全面支援 Reactor 3.1 的 Flux 和 Mono 物件,以及 RxJava1.3 和 2.1,它們被視為來自 MVC 控制器方法的返回值。這項支援的最終目的是支援 Spring Data 中的新的反應式 WebClient 和反應式儲存庫。
使用 JUnit 5 執行條件和併發測試
JUnit 和 Spring 5:Spring 5 全面接納了函式式範例,並支援 JUnit 5 及其新的函式式測試風格。還提供了對 JUnit 4 的向後相容性,以確保不會破壞舊程式碼。
Spring 5 的測試套件通過多種方式得到了增強,但最明顯的是它對JUnit 5 的支援。現在可以在您的單元測試中利用 Java 8 中提供的函數語言程式設計特性。清單 7 演示了這一支援:
清單 7. 清單 7.JUnit 5 全面接納了 Java 8 流和 lambda 表示式
@Test void givenStreamOfInts_SumShouldBeMoreThanFive() { assertTrue(Stream.of(20,40,50) .stream() .mapToInt(i -> i) .sum() > 110,() -> "Total should be more than 100"); }
遷移到 JUnit 5:如果您對升級到 JUnit 5 持觀望態度,Steve Perry 的分兩部分的深入剖析教程將說服您冒險嘗試。
Spring 5 繼承了 JUnit 5 在 Spring TestContext Framework 內實現多個擴充套件 API 的靈活性。舉例而言,開發人員可以使用 JUnit 5 的條件測試執行註解 @EnabledIf 和 @DisabledIf 來自動計算一個 SpEL (Spring Expression Language) 表示式,並適當地啟用或禁用測試。藉助這些註解,Spring 5 支援以前很難實現的複雜的條件測試方案。Spring TextContext Framework 現在能夠併發執行測試。
使用 Spring WebFlux 執行整合測試
Spring Test 現在包含一個 WebTestClient,後者支援對 Spring WebFlux 伺服器端點執行整合測試。WebTestClient 使用模擬請求和響應來避免耗盡伺服器資源,並能直接繫結到 WebFlux 伺服器基礎架構。
WebTestClient 可繫結到真實的伺服器,或者使用控制器或函式。在清單 8 中,WebTestClient 被繫結到 localhost:
清單 8. 繫結到 localhost 的 WebTestClient
WebTestClient testClient = WebTestClient .bindToServer() .baseUrl("http://localhost:8080") .build();
在清單 9 中,測試了 RouterFunction:
清單 9. 將 WebTestClient 繫結到 RouterFunction
RouterFunction bookRouter = RouterFunctions.route( RequestPredicates.GET("/books"),request -> ServerResponse.ok().build() ); WebTestClient .bindToRouterFunction(bookRouter) .build().get().uri("/books") .exchange() .expectStatus().isOk() .expectBody().isEmpty();
包清理和棄用
Spring 5 中止了對一些過時 API 的支援。遭此厄運的還有 Hibernate 3 和 4,為了支援 Hibernate 5,它們遭到了棄用。另外,對 Portlet、Velocity、JasperReports、XMLBeans、JDO 和 Guava 的支援也已中止。
包級別上的清理工作仍在繼續:Spring 5 不再支援beans.factory.access、jdbc.support.nativejdbc、mock.staticmock(來自 spring-aspects 模組)或 web.view.tiles2M。Tiles 3 現在是 Spring 的最低要求。
對 Spring 核心和容器的一般更新
Spring Framework 5 改進了掃描和識別元件的方法,使大型專案的效能得到提升。目前,掃描是在編譯時執行的,而且向 META-INF/spring.components 檔案中的索引檔案添加了元件座標。該索引是通過一個為專案定義的特定於平臺的應用程式構建任務來生成的。
標有來自 javax 包的註解的元件會新增到索引中,任何帶 @Index 註解的類或介面都會新增到索引中。Spring 的傳統類路徑掃描方式沒有刪除,而是保留為一種後備選擇。有許多針對大型程式碼庫的明顯效能優勢,而託管許多 Spring 專案的伺服器也會縮短啟動時間。
Spring 5 還添加了對 @Nullable 的支援,後者可用於指示可選的注入點。使用者現在必須準備接受 null 值。此外,還可以使用此註解來標記可以為 null 的引數、欄位和返回值。@Nullable 主要用於 IntelliJ IDEA 等 IDE,但也可用於 Eclipse 和 FindBugs,它使得在編譯時處理 null 值變得更方便,而無需在執行時傳送 NullPointerExceptions。
Spring Logging 還提升了效能,自帶開箱即用的 Commons Logging 橋接器。現在已通過資源抽象支援防禦性程式設計,為 getFile 訪問提供了 isFile 指示器。
結束語
Spring 5 的首要特性是新的反應式程式設計模型,這代表著對提供可無縫擴充套件、基於 Spring 的響應式服務的重大保障。隨著人們對 Spring 5 的採用,開發人員有望看到反應式程式設計將會成為使用 Java 語言的 Web 和企業應用程式開發的未來發展道路。
未來的 Spring Framework 版本將繼續反映這一承諾,因為 Spring Security、Spring Data 和 Spring Integration 有望採用反應式程式設計的特徵和優勢。
總之,Spring 5 代表著一次大受 Spring 開發人員歡迎的範例轉變,同時也為其他框架指出了一條發展之路。
以上就是spring5新特性全面介紹的詳細內容,更多關於spring5新特性的資料請關注我們其它相關文章!