Spring Boot 的那些事兒

Spring Boot 是個什么東西?官方給出的解釋是Spring Boot is designed to get you up and running as quickly as possible, with minimal upfront configuration of Spring. Spring Boot takes an opinionated view of building production-ready applications. 解釋下來就是Spring Boot 是為了快速的啟動且最小化配置Spring應用而設計的。Spring Boot 采用固化視圖來構建生產級別應用。 這是官網首頁最顯眼的地方擺出的兩句話,當然官網推崇Spring Boot 遠不止這兩句話,下面還來了句更狠的Spring Boot is the starting point for building all Spring-based applications. 這句話有多狠呢?Spring Boot 是都有基于Spring 構建的應用的起點,可見Spring 官方為了推出Spring Boot的決心。

Spring Boot 的特點

下面是官網列出的9個特點,我們逐一了解下

  • Get started in seconds using Spring Initializr
    使用Spring Initializr 幾秒的時間就可以啟動。我個人的理解是在https://start.spring.io/網址花幾秒鐘的時間就可以構建一個Spring Boot 項目,剛好這個網頁的title就叫Spring Initializr。

    Spring Initializr

  • Build anything: REST API, WebSocket, web, streaming, tasks, and more
    可以用來構建任何東西如: REST API,WebSocket, web, streaming, tasks 這個我們以后探討。

  • Simplified security
    簡化了安全框架,這個比較明確了,需要實踐發現如何簡化。

  • Rich support for SQL and NoSQL
    良好的支持了SQL和NoSQL

  • Embedded runtime support: Tomcat, Jetty, and Undertow
    嵌入式運行時容器:Tomcat, Jetty, and Undertow,實際上Spring Boot2.0 加入的Web Flux 默認采用的是Netty容器,當然這個后面討論吧。

  • Developer productivity tools such as LiveReload and Auto Restart
    開發者的生產工具如LiveReload 和 Auto Restart

  • Curated dependencies that just work
    更加精簡的依賴

  • Production-ready features such as tracing, metrics, and health status
    提供為生產環境準備的功能如:跟蹤、度量和運行狀態

  • Works in your favorite IDE: Spring Tool Suite, IntelliJ IDEA, and NetBeans
    可以在你喜歡的IDE上工作如Spring Tool Suite, IntelliJ IDEA, and NetBeans,好吧,我現在用得就是IntelliJ IDEA

說了那么多特點,直接開干就知道了

Spring Initializr直接點generate project 生成項目,存放到本地,解壓,目錄如下

demo
    │  .gitignore
    │  HELP.md
    │  mvnw
    │  mvnw.cmd
    │  pom.xml
    │  
    ├─.mvn
    │  └─wrapper
    │          maven-wrapper.jar
    │          maven-wrapper.properties
    │          MavenWrapperDownloader.java
    │          
    └─src
        ├─main
        │  ├─java
        │  │  └─com
        │  │      └─example
        │  │          └─demo
        │  │                  DemoApplication.java
        │  │                  
        │  └─resources
        │          application.properties
        │          
        └─test
            └─java
                └─com
                    └─example
                        └─demo
                                DemoApplicationTests.java

windows 下面列出文件目錄的指令時tree,將文件和目錄一起列出是tree /f ,輸出到文件中使用tree /f > list.txt

.gitignore 文件存放的是一些流行的IDE的元信息如STS,IntelliJ IDEA,NetBeans,VS Code
mvnw.cmd 文件配置的是一些maven信息,我們知道Spring Boot 要求使用Maven3.0以上的版本構建,但是有了這個文件后,我們甚至在本機中沒有安裝Maven也能采Maven來構建項目
pom.xml文件,依賴配置文件,這里我們采用的Spring Boot 版本是org.springframework.boot:spring-boot-starter-parent:2.2.0.M2
DemoApplication.java 啟動類

  • 編譯啟動項目
    進入到pom.xml同級目錄使用mvn spring-boot:run 或者mvnw.cmd spring-boot:run啟動項目,程序就會自動去下載依賴包和編譯,是不是很方便。

由于國內環境下載速度太慢,推薦使用mvn spring-boot:run ,然后我們對本地的maven配置上阿里云鏡像 修改settings.xml文件修改
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

編譯啟動

這個時候,程序直接退出了,主要原因是沒有嵌入式web容器,就是說剛才啟動的就是一個普通的Java項目,執行完后就退出了。我們添加依賴org.springframework.boot:spring-boot-starter-web 再啟動,這個時候我們就可以去訪問http://localhost:8080/ 返回404,當然,我們沒有配置信息,至少可以確定,服務器已經啟動了。

  • 打包
    剛才已經說過了,我們可以采用mvn spring-boot:run 指令來啟動項目,而我們線上環境當然不能那么草率的啟動,還是需要jar包或者war包的形式的。我們知道maven的打包指令時mvn package 。那么我們直接試試吧。


    打包

    打包成功,生成了兩個文件16.3M的demo-0.0.1-SNAPSHOT.jar和2.75K的demo-0.0.1-SNAPSHOT.jar.original。
    我們再試試打war包,修改pom的packaging為war。執行mvn clean package。如果嫌測試麻煩加上-Dmaven.test.skip=true,打包成功,同樣生成demo-0.0.1-SNAPSHOT.war和demo-0.0.1-SNAPSHOT.war.original,這樣我們就可以用java -jar 的指令來啟動了。

  • 分析包
    解壓下demo-0.0.1-SNAPSHOT.jar ,包的目錄如下
├─BOOT-INF
│  ├─classes
│  │  └─com
│  │      └─example
│  │          └─demo
│  └─lib
├─META-INF
│  └─maven
│      └─com.example
│          └─demo
└─org
    └─springframework
        └─boot
            └─loader
                ├─archive
                ├─data
                ├─jar
                └─util

我們發現BOOT-INF目錄下面有classes目錄和lib目錄,這個是不是感覺似曾相識?沒錯,就是WEB-INF目錄嘛,當然,web.xml是不存在的。這么看來,classes我們理解成我們寫的Java代碼編譯目錄,lib為依賴jar包,這就是個web項目嘛。我們大膽猜測下,Spring Boot其實就是模擬的一個JavaEE項目。
我們再看下jar包的元信息,META-INF/MANIFEST.MF

Manifest-Version: 1.0
Implementation-Title: demo
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: DELL
Implementation-Vendor-Id: com.example
Spring-Boot-Version: 2.2.0.M2
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.demo.DemoApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.5.2
Build-Jdk: 1.8.0_141
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
 ot-starter-parent/demo

我們知道java -jar 指令程序的入口是Main-Class。這個文件中的Main-Class 是JarLauncher,并不是我們的啟動類DemoApplication,我們猜想下,使用java JarLauncher 命令是不是也能啟動項目。驗證了下,發現真的可以啟動項目。


image.png

我們假設下jar包里面org目錄下為Tomcat容器,那么通過啟動Tomcat容器來啟動我們的Spring Boot 項目,那么這一切就解釋的通了(ps 個人看法)

理解嵌入式Web容器

首先我們將demo項目導入到IDEA中,然后查看下IDEA下的maven依賴如下圖:


image.png

我們看到spring-boot-starter-web下面有spring-boot-stater-tomcat的依賴,所以容器默認使用tomcat。如果我們要用Jetty或者Undertow呢?我們以Undertow為例,修改pom.xml文件

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

再次啟動項目


image.png

什么鬼,不生效。
根據上面的依賴關系,我們知道spring-boot-starter-web內部有了tomcat的依賴,如果我們不移出的話,依舊會使用tomcat作為容器,那么我們就需要修改spring-boot-satrter-web依賴了

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

重啟下項目


image.png

這個時候就使用了Undertow作為web容器了。

從pom.xml為入口再談編譯

首先,Spring 文檔中提到了一個Executable Jar的概念,也稱為fat jars。就是說將我們的Spring Boot 項目打成一個可執行的jar包,那么如何打包呢?

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

我們可以通過spring-boot-maven-plugin插件將我們的項目打成可執行jar包。這就完事了?當然不可能,我們看下這句話If you do not use the parent POM, you need to declare this configuration yourself. 就是說,我們不是以spring-boot-starter-parent 作為parent的話,需要自己聲明配置。
那么問題來了,如何不以spring-boot-starter-parent為parent構建Spring Boot 項目呢?

  • 搭建不以spring-boot-starter-parent為parent 的Spring Boot 項目
    為了演示方便,我們修改下啟動類DemoApplication.java,將訪問http://localhost:8080/ 返回字符串,而不再是報404錯誤。
@RestController
@SpringBootApplication
public class DemoApplication {
    @RequestMapping("/")
    public String hello(){
        return "hello spring boot";
    }
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

我們再將pom.xml的parent注釋掉,然后修改spring-boot-starter-web的依賴,添加版本號

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

我們執行下mvn spring-boot:run 我們發現,啟動時成功的,訪問下http://localhost:8080/

image.png

返回也沒有問題,那么說是不是我們的項目搭建成功了呢?別急,打包試試。篇幅有限,我這里不截圖了,打包也是成功的,包是demo-0.0.1-SNAPSHOT.jar,但是我們發現一個問題,這個包只有3K,肯定不是fat jars。
我們翻看下官方文檔的 Using Spring Boot without the Parent POM章節,說的是需要添加dependencyManagement依賴,好吧,我們試試。再次maven clean package 發現沒什么卵用,還是打的3K的jar包,看來問題不是這個,我們再試試其他辦法。(其實dependencyManagement是為了約定spring boot 的版本,我們使用了spring-boot-starter-web:2.1.4.RELEASE 指定好了版本號加不加入影響不大)
我們猜想應該是maven插件的問題了,修改下pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.1.4.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

repackage描述: create a jar or war file that is auto-executable. It can replace the regular artifact or can be attached to the build lifecycle with a separate classifier. 好吧,這句話就是說創建fat jars,我們加入后,發現打包后和parent效果是一樣的。至于為什么使用parent后不需要repackage就能生成fat jars,這個我就不知道了,希望大家幫忙解答下。

之前的依賴發現使用的是2.2.0.M2版本,由于這個是里程碑版本,pom中需要加入一些依賴信息,我們為了方便閱讀,之后采取2.1.4.RELEASE版本。剛好,官方的最新文檔也是這個版本。

未完,待續

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375