1. 程式人生 > 實用技巧 >老司機給我們解讀 Spring Boot 最流行的 16 條實踐

老司機給我們解讀 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萬+碼農成長充電第一站,陪有夢想的你一起成長