我這樣回答了Spring 5的新特性,面試官對我刮目相看 | 文末送書

2021-03-06 Hollis

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

Spring5是2017年9月發布的,現在已經將近兩年的時間了,很多人可能還不知道他到底有哪些特性,恰好最近看了一本書《Spring 5 核心原理與30個類手寫實戰》,覺得裡面的內容不錯,經坐著授權,節選其中部分內容,介紹下關於Spring 5的新特性,這本書我在文末也會送出5本。

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

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

當然,反應式編程不僅是此版本的主題,還是令許多程式設計師激動不已的重大特性。人們對能夠針對負載波動進行無縫擴展的容災和響應式服務的需求在不斷增加,Spring 5很好地滿足了這一需求。

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

升級到Java SE 8和Java EE 7

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

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的圖書。



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框架及乾淨且符合語言習慣的代碼。可以像下面代碼中這樣簡單地表達端點路由:


@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不只是一個框架,已然成了一個編程生態。

福利時間

感謝大家一直以來的支持,本次送出技術書籍5本。書籍是《Spring 5 核心原理與30個類手寫實戰》

《Spring 5核心原理與30個類手寫實戰》基於編程開發實踐,不僅深度解析Spring 5的原理與新特性,更從環境準備、頂層結構設計、數據訪問等方面一步步地推導出Spring的設計原理。在每個知識點上,均以大量的經典代碼案例輔助講解,使理論緊密聯繫實際。最後手寫30個類,以體會Spring作者的創作過程,讓每一位讀者學以致用。

對於立志成為Java架構師的技術人員,以及對以Spring為核心的Java Web開發感興趣的計算機專業高校生、在職Java開發人員來說,本書是一本具備超強實戰意義的技術升級指南。讀者通過本書可以看源碼不再「暈車」,輕鬆找到入口;系統學習設計思想,提高解決問題的效率;培養架構思維能力,以及自驅學習能力。

購買連結

參與方式:請掃描下方二維碼關注我的小號[Java之道],公眾號對話回覆:送書,即可參與抽獎。

如果你喜歡本文,

請長按二維碼,關注 Hollis.

相關焦點

  • 我這樣回答了Spring 5的新特性,面試官對我刮目相看
    最近,有一個小夥伴拿到了自己滿意的Offer,和他交談的過程中得知他面試官問他關於Spring的問題比較多,其中最讓面試官滿意的就是自己回答關於Spring 5的知識點回答的不錯。Spring5是2017年9月發布的,現在已經將近兩年的時間了,很多人可能還不知道他到底有哪些特性,恰好最近看了一本書《Spring 5 核心原理與30個類手寫實戰》,覺得裡面的內容不錯,經作者授權,節選其中部分內容,介紹下關於Spring 5的新特性,這本書我在文末也會送出5本。
  • 面試官:「口」字加兩筆,是什麼字?女博士回答「目」被淘汰
    面試官:「口」字加兩筆,是什麼字?女博士回答「目」被淘汰相信很多人都經歷過面試這個環節,面試好的話意味著能進入一家好的公司,面試不好的話又要四處奔波找工作。RH們為了在短時間內招到一名綜合型的人才,都會費盡心思出一些難題來考核求職者們,甚至還會出一些奇葩的問題,讓求職者們陷入困境,不知道該怎麼回答這樣的回答。這是一家傳媒公司招聘現場,當天來了12位求職者,經過嚴格的篩選,最終只留下的4位比較優秀的求職者。在上一輪4位都表現很出色,難以選擇,於是面試官出一個這樣的問題:「口」字加兩筆,是什麼字?」
  • 面試時,面試官問我未來5年的規劃,我該怎麼回答?
    歲了,面試時,面試官問我未來5年的規劃,我該怎麼回答?」看到這樣的問題,老王認為,在回答面試官的問題時,從來都沒有標準答案,不要試圖尋找標準答案。不過,遇到這樣的問題,老王建議,先了解面試官的問題,是想考察哪一方面?面試官提問的動機是什麼?以「面試時,面試官問我未來5年的規劃,我該怎麼回答?」
  • 面試官:把你的包銷售給我?我一回答,考試官立刻同意了我的入職
    面試官看過後,問,你應聘的職位是電話銷售?我說,是,做過一段時間。面試官問,你已經有了工作經驗,那麼關於銷售,你最喜歡和最不喜歡的是什麼?為什麼?我心裡就一撇嘴,電話銷售的面試也這麼難。我回答說, 我最喜歡的是跟客戶進行商務談判。從剛入職的1分鐘到5分鐘,再到20分鐘,在這過程中,鍛鍊、提高了自己。跟不同的人交流就等於在跟不同的人學習。最不喜歡?那就是上司叫我說一些虛假,誇張的事情,來促進銷售,我寧願拒絕。面試官點點頭,又問,為取得成功,一個好的銷售人員應該具備哪四方面的素質?你為什麼認為這些素質是十分重要的?
  • 面試官:『禾』字加一筆是什麼字?回答『殺』和『末』全被淘汰!
    導讀:面試官:『禾』字加一筆是什麼字?回答『殺』和『末』的都被淘汰現在找工作越來越難,一方面是好工作太少,優秀的人太多,另一方面就是面試官出的題目越來越變態,很多求職者哪怕提前做好了功課,卻依然解決不了面試官出的各種奇葩問題,對於參加過面試的大家想必都深有體會,比如下面這位就被面試官問到了:『禾』字加一筆是什麼字?
  • 面試官:目字加兩點,別做貝字猜,打一字?小夥機智回答
    面試官:目字加兩點,別做貝字猜,打一個字?小夥子的回答太機智了!隨著就業壓力的增大,很多大學生在畢業之前都要面臨著一個巨大的危機。想要順利進入一家好的企業,首先就要通過一場面試。在面試的時候很多,面試官都會出一些比較奇葩這問題,但是並不是一定要你說出一個百分百的標準答案,而且那個問題的答案是沒有固定的,無論你怎麼回答都可以,只要你可以用自己的想法說服面試官,讓他認同就行了,而且還是要考驗你的思維能力!
  • 面試官:希望與什麼樣的上級共事?我回答過,居然有想不到的結果
    這天,給原公司請假,找個理由去參加一個公司的面試。一切都相談甚歡。臨末,面試官突然問你的英文怎麼樣?我說還可以。又問,你有英文名字嗎?我先說沒有。然後,好奇的問,咱們是外企?面試官回答不是。是外貿?面試官回答,也不是。
  • 面試官:目字少一半,是什麼字?研究生:口,直接淘汰
    面試對於職場的老油條來說並不陌生,但對於剛畢業的大學生來說就顯得特別重要了,進入社會的職場菜鳥什麼經驗都沒有,企業招進去要培養,一張白紙面試官也看不出什麼有價值的東西,所以面試官特別注重思維和情商方面的考核,也就是說專業能力只佔一半,求職者更應該注意平時能力的積累,因為面試官問的問題千奇百怪
  • 面試技巧|面試官問我:你喜歡什麼樣的領導?該如何回答?
    如今已是11月中旬,收到面試通知的同學也已經面試得七七八八了。相信在這個過程中,同學們遇到了很多奇奇怪怪的面試題,前幾天,有個同學在後臺留言「今天去面試,面試官問我喜歡什麼樣的領導?我至今沒想出什麼好的答案,這個問題到底該怎麼回答呢?」問題來了,面試官問你喜歡什麼樣的領導,到底該怎麼回答?
  • 面試官:「我」減一筆,變成什麼字?女生高情商回答被錄用
    大家在面試的過程中總會遇到一些奇葩的面試官出的奇葩的題目,但是沒辦法,現在工作雖多,但好的工作卻太少了。一個好的工作崗位往往好幾十的求職者在競爭,面試官出各種刁難題目也是為了更好地看到一個求職者的真實水平。
  • 面試官:一個口加個二,是什麼字?回答目與旦的人,都被淘汰了
    當小雅做好心理準備好,她就向自己喜歡的公司發出了面試申請書。很快,小雅就憑藉自己自身條件的優勢收到了面試通知書。在面試前,小雅就了解了一些職場面試禮儀,並針對性地做好調整,突出自己與眾不同的優勢。機會總是留給有準備的人的。小雅一路表現突出,很得面試官的喜愛。可是,就在小雅認為自己對於這個崗位手到擒拿之時。
  • 面試官:如果我拉鏈開了,你會怎麼提醒我?這樣的回答當場被錄取
    這樣今年的競爭力就一定會大,所以面試的時候,一定要慎重回答面試官的問題。怎樣提醒面試官,有三個面試者回答1、第一位,直接和面試官說你拉鏈開了,還問用不用我幫你。2、第二位,說我眼神不太好一般情況下看不見,就算是看見了我也會裝看不見,所以面試官你放心,我不會說的。
  • 面試官問你的缺點是什麼,我教你如何回答
    面試官:可以談談你的缺點是什麼嗎?我對數據不太敏感,容易出錯。我性格比較內向,不善於表達。我看問題不全面,缺乏全局觀。當你這樣回答時,基本上可以宣告失敗。這些回答是每個崗位需要具備的能力和素質,都是大忌。你把缺點淋漓盡致地展示出來,以為這是誠實,可以得到面試官的青睞。實際上面試官聽到你的回答後,已經給你打上不合格的標籤。
  • 面試官問:「你的興趣愛好是什麼?」這樣回答,面試官最滿意
    當初我面試一個網際網路運營,說到興趣愛好,他就說喜歡看書。我接著問:「喜歡看什麼書啊?」候選人回答:「XXXX」這本書我剛好看過,於是我就問:「太好了,我一直想看,你來說說這本書主要講了什麼? 有什麼值得推薦的?」
  • 面試官:請給我推薦一本書?回答普通無所謂,別給自己挖坑
    當面試官問出向他推薦一本書的時候,可以籠統地回答某一類書,不要確切的指某一本書,因為這有利於更大的空間迴旋。一方面是面試官根本不知道到底你看的是哪幾本書,就沒辦法再繼續給你下套路,即使他問,你也可以隨便編一個市面上根本不知道的名字,這樣面試官也不好再詢問。
  • 面試官:我褲子拉鏈開了,該怎麼提醒我?應屆生高情商回答被錄用
    文/阿蒙聊教育現在大學生找工作,變得越來越難,2020年高校畢業生超過了840萬,高薪崗位有限,供大於需的局面,進入大企業越來越難。為了挑選出優秀的人才,面試官經常會出各種難題,最近,一位大學應屆生就遇到了,他高情商的回答,給面試官留下了深刻的印象,第二天就接到了錄用通知,到底是什麼樣的難題?我們一起來看看。
  • 面試官問我的缺點是什麼,我應該如何回答?
    Photo by Jan de Keijzer on Unsplash 在面試的時候,面試官讓候選人說出自己的缺點時,很多人都會這樣說:「我最大的缺點就是喜歡加班總之,給面試官的的感覺肯定是你不夠坦誠,太虛太假。這樣,你被拒絕的概率非常大,或者因為這個回答,你已經被拒絕了。如果面試官問你的優點,你又該如何回答呢?我們先看兩個真實的案例:
  • 面試的時候,面試官說:「我為什麼要僱用你」,該怎麼回答呢?
    乍一聽,這個問題有點莫名其妙,我為什麼僱用你?是啊,我怎麼知道你為什麼要僱用我?這話應該面試官問問自己才對啊!然而你仔細解讀這句話的含義,就會發現,面試官不過是換了一種口吻而已,實際上,他真正要說的意思是:你需要給我們一些理由,讓我們決定僱用你!
  • 面試官問你:「我為什麼要僱用你?」這樣回答的人才會被錄取了
    求職路上,面試時難免會被問到「我為什麼要僱用你,該怎麼回答才好?」第一次求職參加面試,總有準備不足的地方,臨場發揮更佳的人,才有更大的機會拿到錄用通知書,哪些準備充足的人,往往還會發揮失常。這跟人的心理素質和抗壓能力有很大關係。
  • 面試官:天王蓋地虎,下一句是?女孩回答笑死我了
    面試官:天王蓋地虎,下一句是?女孩回答笑死我了!女孩瞬間反應!經濟的發展與時俱進,社會的腳步永不停歇,尋找工作是我們大多數人賺取生活來源的重要手段。而求職最重要的就是面試了,許許多多的小細節無時不刻的影響著你的面試成績。