老司機給我們解讀 Spring Boot 最流行的 16 條實踐

Spring Boot 是最流行的用於開發微服務的 Java 框架。在本文中,我將與你分享自 2016 年以來我在專業開發中使用 Spring Boot 所採用的最佳實踐。這些內容是基於我的個人經驗和一些熟知的 Spring Boot 專家的文章。

在本文中,我將重點介紹 Spring Boot 特有的實踐(大多數時候,也適用於 Spring 項目)。以下依次列出了最佳實踐,排名不分先後。

1、使用自定義 BOM 來維護第三方依賴

這條實踐是我根據實際項目中的經歷總結出的。

Spring Boot 項目本身使用和集成了大量的開源項目,它幫助我們維護了這些第三方依賴。但是也有一部分在實際項目使用中並沒有包括進來,這就需要我們在項目中自己維護版本。如果在一個大型的項目中,包括了很多未開發模塊,那麼維護起來就非常的繁瑣。

怎麼辦呢?事實上,Spring IO Platform 就是做的這個事情,它本身就是 Spring Boot 的子項目,同時維護了其他第三方開源庫。我們可以借鑑 Spring IO Platform 來編寫自己的基礎項目 platform-bom,所有的業務模塊項目應該以 BOM 的方式引入。這樣在升級第三方依賴時,就只需要升級這一個依賴的版本而已。

<dependencyManagement>
   <dependencies>
       <dependency>
           <groupId>io.spring.platform</groupId>
           <artifactId>platform-bom</artifactId>
           <version>Cairo-SR3</version>
           <type>pom</type>
           <scope>import</scope>
       </dependency>
   </dependencies>
</dependencyManagement>

2、使用自動配置

Spring Boot 的一個主要特性是使用自動配置。這是 Spring Boot 的一部分,它可以簡化你的代碼並使之工作。當在類路徑上檢測到特定的 jar 文件時,自動配置就會被激活。

使用它的最簡單方法是依賴 Spring Boot Starters。因此,如果你想與 Redis 進行集成,你可以首先包括:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

如果你想與 MongoDB 進行集成,需要這樣:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

藉助於這些 starters,這些繁瑣的配置就可以很好地集成起來並協同工作,而且它們都是經過測試和驗證的。這非常有助於避免可怕的 Jar 地獄。

https://dzone.com/articles/what-is-jar-hell

通過使用以下註解屬性,可以從自動配置中排除某些配置類:

@EnableAutoConfiguration(exclude = {ClassNotToAutoconfigure.class})

但只有在絕對必要時才應該這樣做。

有關自動配置的官方文檔可在此處找到:

https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html。

3、使用 Spring Initializr 來開始一個新的 Spring Boot 項目

這一條最佳實踐來自 Josh Long (Spring Advocate,@starbuxman)。

Spring Initializr 提供了一個超級簡單的方法來創建一個新的 Spring Boot 項目,並根據你的需要來加載可能使用到的依賴。

https://start.spring.io/

使用 Initializr 創建應用程序可確保你獲得經過測試和驗證的依賴項,這些依賴項適用於 Spring 自動配置。你甚至可能會發現一些新的集成,但你可能並沒有意識到這些。

4、考慮爲常見的組織問題創建自己的自動配置

這一條也來自 Josh Long(Spring Advocate,@starbuxman)——這個實踐是針對高級用戶的。

如果你在一個嚴重依賴 Spring Boot 的公司或團隊中工作,並且有共同的問題需要解決,那麼你可以創建自己的自動配置。

這項任務涉及較多工作,因此你需要考慮何時獲益是值得投入的。與多個略有不同的定製配置相比,維護單個自動配置更容易。

如果將這個提供 Spring Boot 配置以開源庫的形式發佈出去,那麼將極大地簡化數千個用戶的配置工作。

5、正確設計代碼目錄結構

儘管允許你有很大的自由,但是有一些基本規則值得遵守來設計你的源代碼結構。

避免使用默認包。確保所有內容(包括你的入口點)都位於一個名稱很好的包中,這樣就可以避免與裝配和組件掃描相關的意外情況;

將 Application.java(應用的入口類)保留在頂級源代碼目錄中;

我建議將控制器和服務放在以功能爲導向的模塊中,但這是可選的。一些非常好的開發人員建議將所有控制器放在一起。不論怎樣,堅持一種風格!

6、保持 @Controller 的簡潔和專注

Controller 應該非常簡單。你可以在此處閱讀有關 GRASP 中有關控制器模式部分的說明。你希望控制器作爲協調和委派的角色,而不是執行實際的業務邏輯。以下是主要做法:

https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Controller

控制器應該是無狀態的!默認情況下,控制器是單例,並且任何狀態都可能導致大量問題;

控制器不應該執行業務邏輯,而是依賴委託;

控制器應該處理應用程序的 HTTP 層,這不應該傳遞給服務;

控制器應該圍繞用例 / 業務能力來設計。

要深入這個內容,需要進一步地瞭解設計 REST API 的最佳實踐。無論你是否想要使用 Spring Boot,都是值得學習的。

7、圍繞業務功能構建 @Service

Service 是 Spring Boot 的另一個核心概念。我發現最好圍繞業務功能 / 領域 / 用例(無論你怎麼稱呼都行)來構建服務。

在應用中設計名稱類似AccountService, UserService, PaymentService這樣的服務,比起像DatabaseService、ValidationService、CalculationService這樣的會更合適一些。

你可以決定使用 Controler 和 Service 之間的一對一映射,那將是理想的情況。但這並不意味着,Service 之間不能互相調用!

8、使數據庫獨立於核心業務邏輯之外

我之前還不確定如何在 Spring Boot 中最好地處理數據庫交互。在閱讀了羅伯特 ·C· 馬丁的 “Clear Architecture” 之後,對我來說就清晰多了。

你希望你的數據庫邏輯於服務分離出來。理想情況下,你不希望服務知道它正在與哪個數據庫通信,這需要一些抽象來封裝對象的持久性。

羅伯特 C. 馬丁強烈地說明,你的數據庫是一個 “細節”,這意味着不將你的應用程序與特定數據庫耦合。過去很少有人會切換數據庫,我注意到,使用 Spring Boot 和現代微服務開發會讓事情變得更快。

9、保持業務邏輯不受 Spring Boot 代碼的影響

考慮到 “Clear Architecture” 的教訓,你還應該保護你的業務邏輯。將各種 Spring Boot 代碼混合在一起是非常誘人的…… 不要這樣做。如果你能抵制誘惑,你將保持你的業務邏輯可重用。

部分服務通常成爲庫。如果不從代碼中刪除大量 Spring 註解,則更容易創建。

10、推薦使用構造函數注入

這一條實踐來自 Phil Webb(Spring Boot 的項目負責人, @phillip_webb)。

保持業務邏輯免受 Spring Boot 代碼侵入的一種方法是使用構造函數注入。不僅是因爲@Autowired註解在構造函數上是可選的,而且還可以在沒有 Spring 的情況下輕鬆實例化 bean。

11、熟悉併發模型

我寫過的最受歡迎的文章之一是 “介紹 Spring Boot 中的併發”。我認爲這樣做的原因是這個領域經常被誤解和忽視。如果使用不當,就會出現問題。

https://www.e4developer.com/2018/03/30/introduction-to-concurrency-in-spring-boot/

在 Spring Boot 中,Controller 和 Service 是默認是單例。如果你不小心,這會引入可能的併發問題。你通常也在處理有限的線程池。請熟悉這些概念。

如果你正在使用新的 WebFlux 風格的 Spring Boot 應用程序,我已經解釋了它在 “Spring’s WebFlux/Reactor Parallelism and Backpressure” 中是如何工作的。

12、加強配置管理的外部化

這一點超出了 Spring Boot,雖然這是人們開始創建多個類似服務時常見的問題……

你可以手動處理 Spring 應用程序的配置。如果你正在處理多個 Spring Boot 應用程序,則需要使配置管理能力更加強大。

我推薦兩種主要方法:

使用配置服務器,例如 Spring Cloud Config;

將所有配置存儲在環境變量中(可以基於 git 倉庫進行配置)。

這些選項中的任何一個(第二個選項多一些)都要求你在 DevOps 更少工作量,但這在微服務領域是很常見的。

13、提供全局異常處理

你真的需要一種處理異常的一致方法。Spring Boot 提供了兩種主要方法:

你應該使用 HandlerExceptionResolver 定義全局異常處理策略;

你也可以在控制器上添加 @ExceptionHandler 註解,這在某些特定場景下使用可能會很有用。

這與 Spring 中的幾乎相同,並且 Baeldung 有一篇關於 REST 與 Spring 的錯誤處理的詳細文章,非常值得一讀。

https://www.baeldung.com/exception-handling-for-rest-with-spring

14、使用日誌框架

你可能已經意識到這一點,但你應該使用 Logger 進行日誌記錄,而不是使用 System.out.println() 手動執行。這很容易在 Spring Boot 中完成,幾乎沒有配置。只需獲取該類的記錄器實例:

Logger logger = LoggerFactory.getLogger(MyClass.class);

這很重要,因爲它可以讓你根據需要設置不同的日誌記錄級別。

15、測試你的代碼

這不是 Spring Boot 特有的,但它需要提醒——測試你的代碼!如果你沒有編寫測試,那麼你將從一開始就編寫遺留代碼。

如果有其他人使用你的代碼庫,那邊改變任何東西將會變得危險。當你有多個服務相互依賴時,這甚至可能更具風險。

由於存在 Spring Boot 最佳實踐,因此你應該考慮將 Spring Cloud Contract 用於你的消費者驅動契約,它將使你與其他服務的集成更容易使用。

16、使用測試切片讓測試更容易,並且更專注

這一條實踐來自 Madhura Bhave(Spring 開發者,@madhurabhave23)。

使用 Spring Boot 測試代碼可能很棘手——你需要初始化數據層,連接大量服務,模擬事物…… 實際上並不是那麼難!答案是使用測試切片。

使用測試切片,你可以根據需要僅連接部分應用程序。這可以爲你節省大量時間,並確保你的測試不會與未使用的內容相關聯。

https://spring.io/blog/2016/08/30/custom-test-slice-with-spring-boot-1-4

總結

感謝 Spring Boot,編寫基於 Spring 的微服務正變得前所未有的簡單。我希望通過這些最佳實踐,你的實施過程不僅會變得很快,而且從長遠來看也會更加強大和成功。

來源 | http://e4developer.com/2018/08/06/
在這裏插入圖片描述

歡迎關注我的微信公衆號「碼農突圍」,分享Python、Java、大數據、機器學習、人工智能等技術,關注碼農技術提升•職場突圍•思維躍遷,20萬+碼農成長充電第一站,陪有夢想的你一起成長

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章