我這樣回答了Spring 5的新特性,面試官對我另眼相看

最近,有一個小夥伴拿到了本身滿意的Offer,和他交談的過程當中得知他面試官問他關於Spring的問題比較多,其中最讓面試官滿意的就是本身回答關於Spring 5的知識點回答的不錯。java

Spring5於2017年9月發佈了通用版本,它是自2013年12月以來第一個主要的Spring版本。它提供了一些人們期待已久的改進,還採用了一種全新的編程範例,以反應式原則爲基礎。程序員

這個版本是很長時間以來最使人激動的版本。Spring 5兼容Java™8和JDK 9,它集成了反應式流,以方便後續提供一種顛覆性方法來實現端點和Web應用程序開發。web

固然,反應式編程不只是此版本的主題,仍是令許多程序員激動不已的重大特性。人們對可以針對負載波動進行無縫擴展的容災和響應式服務的需求在不斷增長,Spring 5很好地知足了這一需求。面試

下面介紹Java SE 8和Java EE 7 API升級的基本內容、Spring 5的新反應式編程模型、對HTTP/2的支持,以及Spring經過Kotlin對函數式編程的全面支持。還會簡要介紹測試和性能加強,最後介紹對Spring核心和容器的通常性修訂。spring

升級到Java SE 8和Java EE 7編程

之前的Spring一直在支持一些棄用的Java版本,而Spring 5已從「舊包袱」中解放出來。爲了充分利用Java 8的特性,它的代碼庫已進行了改進,並且要求將Java 8做爲最低的JDK版本。api

Spring 5在類路徑(和模塊路徑)上徹底兼容Java 9,並且它經過了JDK 9測試套件的測試。對Java 9愛好者而言,這是一個好消息。服務器

在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基於一種反應式基礎而構建,並且是徹底異步和非阻塞的。只需少許的線程,新的事件循環執行模型就能夠垂直擴展。

Spring 5採用反應式流來提供在反應式組件中傳播負壓的機制。負壓是一個確保來自多個生產者的數據不會讓使用者不堪重負的概念。

Spring WebFlux是Spring 5的反應式核心,它爲開發人員提供了兩種爲Spring Web編程而設計的編程模型:基於註解的模型和Functional WebFramework(WebFlux.fn)。

基於註解的模型是Spring Web MVC的現代替代方案,該模型基於反應式基礎而構建,而Functional Web Framework是基於@Controller註解的編程模型的替代方案。這些模型都經過同一種反應式規則來運行,後者調整非阻塞HTTP來適應反應式流API。

使用註解進行編程

Web MVC程序員應該對Spring 5的基於註解的編程模型很是熟悉,Spring 5調整了Web MVC的@Controller編程模型,採用了相同的註解。

在下面的代碼中BookController類提供了兩個方法,分別響應針對某個圖書列表的HTTP請求,以及針對具備給定id的圖書的HTTP請求。請注意Mono和Flux等對象。這些對象是實現反應式流規範中的Publisher接口的反應式類型,它們的職責是處理數據流。Mono對象處理一個僅含1個元素的流,而Flux表示一個包含N個元素的流。

@RestController
public class BookController { //反應式控制器
@GetMapping("/book")
Flux<Book> list() {
returnthis.repository.findAll();
}
@GetMapping("/book/{id}")
Mono<Book> findById(@PathVariable String id) {
returnthis.repository.findOne(id);
}
}

以上是針對Spring Web編程的註解,下面咱們使用函數式Web框架來解決同一個問題。

函數式編程

Spring 5的函數式方法將請求委託給處理函數,這些函數接收一個服務器請求實例並返回一種反應式類型。來看一段代碼,建立BookHandler類,其中listBooks()和getBook()方法至關於Controller中的功能。

publicclassBookHandler {
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());
}
}

經過路由函數來匹配HTTP請求參數與媒體類型,將客戶端請求路由處處理函數。下面的代碼展現了圖書資源端點URI將調用委託給合適的處理函數:

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 Web MVC模型,引入了一些很不錯的新特性。

舉例來講,WebFlux模塊爲RestTemplate提供了一種徹底非阻塞、反應式的替代方案,名爲WebClient。下面建立一個WebClient,並調用books端點來請求一本給定id爲1234的圖書。

//經過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提升了傳輸性能,減小了延遲,並提升了應用程序的吞吐量,從而提供了豐富的Web體驗。

Spring 5提供專門的HTTP/2特性支持,還支持人們指望出如今JDK 9中的新HTTP客戶端。儘管HTTP/2的服務器推送功能已經過Jetty Servlet引擎的ServerPushFilter類向Spring開發人員公開很長一段時間了,但若是發現Spring 5中開箱即用地提供了HTTP/2性能加強,Web優化者們必定會爲此歡呼雀躍。

Spring 5.1提供Servlet 4.0,HTTP/2新特性將由Tomcat 9.0、Jetty9.3和Undertow 1.4原生提供。

Kotlin和Spring WebFlux

Kotlin是一種來自JetBrains的面嚮對象語言,支持函數式編程。它的主要優點之一是與Java有很是高的互操做性。經過引入對Kotlin的專門支持,Spring 5全面吸納了這一優點。它的函數式編程風格與Spring WebFlux模塊完美匹配,它的新路由DSL利用了函數式Web框架及乾淨且符合語言習慣的代碼。能夠像下面代碼中這樣簡單地表達端點路由:

//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能夠實際註冊爲提供者。下面代碼中使用Lambda表達式註冊了一個Book Bean:

GenericApplicationContext context = newGenericApplicationContext();
context.registerBean(Book.class, () ->new
Book(context.getBean(Author.class))
);

Spring Web MVC支持最新的 API

全新的WebFlux模塊提供了許多新的、使人興奮的功能,但Spring 5也迎合了願意繼續使用 Spring MVC的開發人員的需求。Spring 5中更新了「模型-視圖-控制器」框架,以兼容WebFlux和最新版的Jackson 2.9和Protobuf 3.0,甚至包括對新的Java EE 8 JSON-Binding API的支持。

除了HTTP/2特性的基礎服務器實現,Spring Web MVC還經過MVC控制器方法的一個參數來支持Servlet 4.0 的PushBuilder。最後,Web MVC全面支持Reactor 3.1的Flux和Mono對象,以及RxJava 1.3和RxJava 2.1,它們被視爲來自MVC控制器方法的返回值。這項支持的最終目的是支持Spring Data中新的反應式WebClient和反應式存儲庫。

使用JUnit 5執行條件和併發測試

1. JUnit和Spring 5

Spring5全面接納了函數式範例,並支持JUnit5及其新的函數式測試風格。還提供了對JUnit 4的向後兼容性,以確保不會破壞舊代碼。

Spring5的測試套件經過多種方式獲得了加強,但最明顯的是它對JUnit 5的支持。如今能夠在單元測試中利用Java 8中提供的函數式編程特性。如下代碼演示了這一支持:

@Test
void givenStreamOfInts_SumShouldBeMoreThanFive() {
assertTrue(Stream.of(20, 40, 50)
.stream()
.mapToInt(i -> i)
.sum() > 110, () -> "Total should be more than 100");
}

2. 遷移到JUnit 5

若是你對升級到JUnit 5持觀望態度,StevePerry的分兩部分的深刻剖析教程將說服你進行嘗試。

Spring5繼承了JUnit 5在Spring TestContext Framework內實現多個擴展API的靈活性。舉例,開發人員可使用JUnit 5的條件測試執行註解@EnabledIf和@DisabledIf來自動計算一個SpEL(Spring Expression Language)表達式,並適當地啓用或禁用測試。藉助這些註解,Spring 5支持之前很難實現的複雜的條件測試方案。SpringTextContext Framework如今可以併發執行測試。

3. 使用 Spring WebFlux 執行集成測試

Spring Test如今包含一個WebTestClient,後者支持對Spring WebFlux服務器端點執行集成測試。WebTestClient使用模擬請求和響應來避免耗盡服務器資源,並能直接綁定到WebFlux服務器的基礎架構。

WebTestClient可綁定到真實的服務器,或者使用控制器或函數。在下面的代碼中,WebTestClient被綁定到localhost:

WebTestClient testClient = WebTestClient
.bindToServer()
.baseUrl("http://localhost:8080")
.build();

下面的代碼將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();

包清理和棄用

Spring5終止了對一些過期API的支持。遭此厄運的有Hibernate 3和Hibernate 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 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 5的首要特性是新的反應式編程模型,這表明着對提供可無縫擴展、基於Spring的響應式服務的重大保障。隨着人們對Spring 5的採用,反應式編程有望成爲使用Java語言的Web和企業應用程序開發的將來。

將來的Spring將繼續體現這一承諾,由於SpringSecurity、Spring Data和Spring Integration有望採用反應式編程的特徵和優點。

總之,Spring 5表明着一次大受Spring開發人員歡迎的華麗轉變,同時也爲其餘框架指出了一條發展之路。Spring 5的升級也爲Spring Boot、Spring Cloud提供了很是豐富的經驗,Spring不僅是一個框架,已然成了一個編程生態。

相關文章
相關標籤/搜索