Spring Boot為什麼不需要額外安裝Tomcat?

2022-01-01 22:00:06

首次接觸 Spring Boot 的時候,絕大多數小夥伴應該和我一樣好奇:

為什麼 Spring Boot 不需要額外安裝 Tomcat 啊?

到底為什麼呢?讓我們帶著好奇心開始今天的旅程吧。

開啟上一節我們搭建好的 tobebetterjavaer 專案,找到 pom.xml 檔案,可以在裡面看到一個 parent 屬性,程式碼如下:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.6.1</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

什麼意思呢?

意思是我們當前的 Spring Boot 專案依賴於 spring-boot-starter-parent 這個父專案。有點 Java 中的繼承(extends)的味道。

怎麼檢視 spring-boot-starter-parent.pom 檔案的內容呢?

如果你不確定自己的 Maven 本地倉庫在哪裡,可以在終端執行 mvn help:effective-settings 命令。

順藤摸瓜,根據 parent 的 groupId、artifactId、version 可以鎖定 spring-boot-starter-parent.pom 檔案的位置。

使用文字編輯器開啟以後大致可以看到以下內容:

  • 定義了 JDK 的版本為 1.8
  • 專案預設的編碼方式為 UTF-8
  • Maven 的編譯環境
  • 以及父依賴 spring-boot-dependencies

照葫蘆畫瓢,我們按照同樣的方法找到 spring-boot-dependencies.pom 檔案。可以看到這裡面定義了一系列的屬性和依賴,差不多 2800 行。

有訊息佇列依賴、commons 工具包依賴、資料庫連結依賴、HTTP 連結依賴、Spring 家族依賴、Web 伺服器依賴等等。

可以說這裡是 Spring Boot 專案依賴的版本管理中心。

版本管理中心預設設定了專案所需的所有基礎環境的版本,這些版本會隨著 Spring Boot 版本的升級而不斷變化,也就是說,開發人員不需要再關心這些瑣碎依賴的版本了,交給大管家 Spring Boot 就可以了。

Spring Boot 會幫我們選好最穩定的新版本,這體現出了 Spring Boot 專案的靈魂:「約定優於設定」,你想設定當然可以,但沒必要,按照約定俗成的來就行。

理解了這一點,我們再來繼續看 pom.xml 檔案,裡面有一個 spring-boot-starter-web 依賴。這一次,我們直接按住 Ctrl 鍵(macOS 是 Command 鍵),點選滑鼠左鍵就可以跳轉到 spring-boot-starter-web.pom 的原始檔了。

部分原始碼如下:

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.6.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>2.6.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.6.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.3.13</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.13</version>
      <scope>compile</scope>
    </dependency>

spring-web 提供了核心 HTTP 整合,包括一些便捷的 servlet 過濾器, Spring HTTP 呼叫,用於整合其它 web 框架的基礎結構以及技術(Hessian,Burlap)。

spring-webmvc 是 Spring MVC 的一個實現。spring-webmvc 依賴於 spring-web,這樣包含它就會間接地新增 spring-web,不必顯示新增 spring-web。

看一下 spring-boot-starter-tomcat 的 pom 檔案:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-tomcat</artifactId>
  <version>2.6.1</version>
  <name>spring-boot-starter-tomcat</name>
  <dependencies>
    <dependency>
      <groupId>jakarta.annotation</groupId>
      <artifactId>jakarta.annotation-api</artifactId>
      <version>1.3.5</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-core</artifactId>
      <version>9.0.55</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>tomcat-annotations-api</artifactId>
          <groupId>org.apache.tomcat</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-el</artifactId>
      <version>9.0.55</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-websocket</artifactId>
      <version>9.0.55</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>tomcat-annotations-api</artifactId>
          <groupId>org.apache.tomcat</groupId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
</project>

從這裡可以看出來SpringBoot預設的啟動容器是Tomcat,Tomcat 的組成核心 jakarta.annotation、tomcat-embed-core、tomcat-annotations-api、org.apache.tomcat.embed 全部都通過 Maven 引入過來了。

core 的版本是 9.0.55,Tomcat 官網上最新的 9.0.x 版本是 9.0.56,高了一個版本。

不過無所謂,直接下載 9.0.56 的 src,對比看一下,是否大致相同。

對比之下可以看得出,Spring Boot 引入的 Tomcat 更精簡一點,大體上都是相同的,這也就是為什麼Spring Boot 不需要額外安裝 Tomcat 的根本原因了

Spring Boot 的 starter 已經幫我們搞定過了。這也是Spring Boot 大行其道的重要原因,省去了開發人員設定的時間,更專注於業務邏輯的實現、效能的優化,至於那些繁雜的設定嘛,交給 Spring Boot 這個大管家就可以了,他約定好的東西,只要沒問題,不需要特殊化客製化,用就對了。


本篇已收錄至 GitHub 上星標 1.0k+ star 的開源專欄《Java 程式設計師進階之路》,該專欄風趣幽默、通俗易懂,對 Java 愛好者極度友好和舒適😄,內容包括但不限於 Java 基礎、Java 集合框架、Java IO、Java 並行程式設計、Java 虛擬機器器、Java 企業級開發(Git、SSM、Spring Boot)等核心知識點。

star 了這個倉庫就等於成為了一名更優秀的 Java 程式設計師。可以點選下面的連結跳轉過去 star 見證一下這個令人激動的時刻。

https://github.com/itwanger/toBeBetterJavaer

該專欄目前仍然排在 GitHub Trending 榜單(Java 類的日榜)上,這讓二哥終於體會到了霸榜的快樂!

沒有什麼使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧靜的港灣,我是不繫之舟