個人說明:本文內容都是從為知筆記上復制過來的,樣式難免走樣,以后再修改吧。另外,本文可以看作官方文檔的選擇性的翻譯(大部分),以及個人使用經驗及問題。
其他說明:
如果對Spring Boot沒有概念,請先移步上一篇文章 Spring Boot 學習。本篇原本是為了深入了解下Spring Boot而出現的。
另外,Spring Boot 仍然是基於Spring的,建議在趕完工之后深入學習下Spring,有興趣可以看看我的
Spring 4 官方文檔學習(十一)Web MVC 框架 。歡迎探討,笑~
目錄:
- 內置Servlet Container
- 使用Spring Boot
- 安裝Spring Boot CLI
- 開發一個簡單的Spring Boot應用--使用最原始的方式
- Dependency Management
- Starters
- 自動配置
- Spring Beans 和 依賴注入(略)
- @SpringBootApplication
- 運行Spring Boot Application
- Developer tools
- 生產打包
Name Servlet Version Java Version Tomcat 8
3.1
Java 7+
Tomcat 7
3.0
Java 6+
Jetty 9.3
3.1
Java 8+
Jetty 9.2
3.1
Java 7+
Jetty 8
3.0
Java 6+
Undertow 1.3
3.1
Java 7+
此外,你仍然可以部署Spring Boot項目到任何兼容Servlet3.0+的容器。
你可以像使用標准的Java庫文件一樣使用Spring Boot。簡單的將需要的
spring-boot-*.jar 添加到classpath即可。
Spring Boot不要求任何特殊的工具集成,所以可以使用任何IDE,甚至文本編輯器。
只是,仍然建議使用build工具:Maven 或 Gradle。
Spring Boot依賴 使用
org.springframework.boot
groupId
。
通常,讓你的Maven POM文件繼承 spring-boot-starter-parent,並聲明一個或多個 Starter POMs依賴即可。Spring Boot也提供了一個可選的 Maven Plugin來創建可執行的jars。 如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>myproject</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- Inherit defaults from Spring Boot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.0.RELEASE</version> </parent> <!-- Add typical dependencies for a web application --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <!-- Package as an executable jar --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
需要注意的是, spring-boot-starter-parent 是一個非常好的方法,但並不適用於所有情況。有時你需要繼承其他的POM,或者你不喜歡默認的設置。-- 辦法見后面。
這是一個命令行工具,可以執行Groove腳本。是執行一個Spring Boot的最快途徑。
-- 好吧,Linux下無敵,Win下還是休息吧。
務必注意:前提是maven + jdk。
2、新建一個pom.xml文件。內容如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>myproject</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.0.RELEASE</version> </parent> <!-- Additional lines to be added here... --> </project>
當然,你也可以使用IDE,不過使用文本編輯器會讓我們對它更理解。

由於我們已經繼承了 spring-boot-starter-parent ,而 spring-boot-starter-parent 又提供了 dependency-management ,所以我們可以忽略被選中依賴的版本。
在添加依賴之前,我們先看一下現在已有什么:mvn dependency:tree。該命令會打印一個當前項目的依賴樹。
結果表明,當前沒有任何依賴。

OK,現在我們添加一個Starter 模塊。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
現在再次查看一下依賴樹。

可以看出,spring-boot-starter-web 包含了很多內容,spring-webmvc、spring-web、jackson、validation、tomcat、starter。
由於Maven默認編譯路徑為 src/main/java 下面的源碼,所以,默認設置下,需要創建這些文件夾。
然后,編寫文件 src/main/java/Example.java:
import org.springframework.boot.*; import org.springframework.boot.autoconfigure.*; import org.springframework.stereotype.*; import org.springframework.web.bind.annotation.*; @RestController @EnableAutoConfiguration public class Example { @RequestMapping("/") String home() { return "Hello World!"; } public static void main(String[] args) throws Exception { SpringApplication.run(Example.class, args); } }
這里我們只需要關心 @EnableAutoConfiguration 即可。這個注解是讓Spring Boot
猜測 你想怎么配置Spring,但實際上,它是根據你添加到classpath中的依賴來判斷的。
注意,自動配置 可以配合 Starter POMs 一起工作,但二者不是捆綁到一起的。你仍然可以將Starter POMs中的依賴單獨揀出使用,Spring Boot還是會自動配置。
啟動之后就可以訪問了,默認地址:
http://localhost:8080/
注意,Spring Boot的這種打包方式需要使用Spring Boot提供的 spring-boot-maven-plugin 。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
注意,spring-boot-starter-parent POM中包含了 <executions> 的配置信息,綁定了 repackage goal (maven)。如果你不使用parent POM,你需要自己來聲明這個配置信息。
現在,可以打包了: mvn package 。

現在,你可以在/target目錄下看到 myproject-0.0.1-SNAPSHOT.jar ,大約10 Mb左右。可以通過 jar tvf target/myproject-0.0.1-SNAPSHOT.jar 來查看其中的內容。
此外,在/target目錄下,還可以看到 myproject-0.0.1-SNAPSHOT.jar.original ,這是Maven打包出來的---在Spring Boot repackage 之前。

執行 ctrl+c,退出。
每個版本的Spring Boot都提供了一個依賴列表。這個列表包含了你可能通過Spring Boot用到的所有的Spring模塊以及第三方庫。該列表可以以
BOM(Bills of Material)的形式支持Maven。 ---
怎么理解BOM和Starter?什么區別??
spring-boot-starter-parent project
默認是 Java 1.6。 Resource filtering。exec plugin、surefire、Git commit ID、shade。
Resource filtering for application.properties 和 application.yml,以及,profile-specific file,如application-foo.properties 或 application-foo.yml。
-- 注意Maven filtering使用
@..@ 占位符,你可以在Maven property中覆蓋:resource.delimiter。
如果不想使用Spring Boot中的默認版本,可以在<properties>覆蓋相應的版本,如,想使用不同版本的Spring Data,具體如下:
<properties> <spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version> </properties>
想使用不同版本的JDK:
<!-- 使用 java 1.8 --> <java.version>1.8</java.version>
這種情況下,仍然可以使用dependency management,但不能使用plugin management啦。方式如下:
<dependencyManagement> <dependencies> <dependency> <!-- Import dependency management from Spring Boot --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.4.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
注意,scope是
import 。而且,這種情況下,不再允許在<properties>覆蓋相應的版本。如果要使用其他版本,需要在上面的前面添加一個完整的dependency。如下:
<dependencyManagement> <dependencies> <!-- Override Spring Data release train provided by Spring Boot --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-releasetrain</artifactId> <version>Fowler-SR2</version> <scope>import</scope> <type>pom</type> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.4.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
另外,Spring Boot還提供了一個Maven Plugin:spring-boot-maven-plugin,用於將項目打包成fat jar(executable jar)。
繼承時只需要
聲明一下即可使用:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
可以創建自己的Starter,但名字格式不能是 spring-boot-starter-*,而是 *-spring-boot-starter。類似Maven插件的規則。
@Import 和 @ComponentScan 類似;
@EnableAutoConfiguration 和 @SpringBootApplication 類似;---注意,只能使用一次,建議用在primary @Configuration class上。
注意,自動配置永遠是第二位的,一旦你配置自己的東西,那自動配置的就會被覆蓋。
查看自動配置都配置了什么,以及為什么,啟動應用的時候加上 --debug即可。
禁用特定的自動配置:
import org.springframework.boot.autoconfigure.*; import org.springframework.boot.autoconfigure.jdbc.*; import org.springframework.context.annotation.*; @Configuration @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class MyConfiguration { }
如果class不在classpath中,可以使用
excludeName,然后使用全路徑即可。
@SpringBootApplication 等同於默認的屬性的
@Configuration
,
@EnableAutoConfiguration
and @ComponentScan
。
-- 注意,@ComponentScan 不能憑空使用。
需要導入現有Maven項目。
如果不小心運行了兩次,出現端口占用問題,STS(Spring Tools Suite)使用Relaunch即可。
java -jar target/xxxx.jar 注意,是在項目路徑下執行。
開啟
遠程調試支持:
java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n -jar target/myproject-0.0.1-SNAPSHOT.jar
因為Spring Boot應用都是簡單的Java應用,所以JVM Hot-swapping可以直接使用。但是,JVM Hot-swapping對於能夠替換的字節碼有些限制,所以建議使用JRebel或者Spring Loaded??
spring-boot-devtools 模塊同樣包含了快速重啟應用的支持。
另外,貌似JVM Hot-swapping 只能在debug期間修改方法體??
Spring Boot包含一組附加的開發期工具。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies>
注意,生產環境下(java -jar或者通過特定的類加載器啟動),這些開發工具自動被禁止。
上面的
<optional>true</optional> 是一個最佳實踐,可以有效阻止用於其他模塊。
如果想確保生產Build中不包含devtools,可以使用excludeDevtools build property。
一些Spring Boot支持的庫使用了cache增進性能。但是cache,在開發過程中可能會是一個阻礙。例如你無法立即更新一個模板(thymeleaf的)。
cache設置通常在 application.properties 中。但是,比起手動設置這些,spring-boot-devtools模塊會自動應用這些開發期的設置。
使用spring-boot-devtools模塊的應用,當classpath中的文件有改變時,會自動重啟! -- 就是說,默認會監視classpath入口。
靜態資源和視圖模板不需要重啟!
注意,不同的IDE有不同的表現,例如Eclipse中只要改變了文件並保存,那就會導致classpath中的內容改變。而Intellij IDEA則需要 Build #Make Project。
可以通過build plugin啟動應用,只要開啟了forking支持,因為Devtools需要一個隔離的classloader才能運行正常。Maven下要這樣開啟:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> </build>
注意:在使用LiveReload(熱加載)時,自動重啟仍然可以正常工作。如果你使用了JRebel,自動重啟會被禁用以支持動態類加載。此時,devtools其他方面仍然可以使用。
注意:DevTools在重啟過程中依賴應用上下文的shutdown hook來關掉它(應用)。所以如果禁用了shutdown hook,它就無法正常工作了:SpringApplication.setRegisterShutdownHook(false)。
Spring Boot使用的重啟技術,實際上是使用了兩個類加載器:不變的base類加載器、可變的restart類加載器。前者加載第三方jar之類的。后者加載項目代碼。重啟的時候,只是丟棄可變的restart類加載器,然后重新創建一個,所以速度比較快。
如果你覺得這樣仍然不夠快,或者遇到了類加載器問題,那你可以考慮JRebel之類的重加載技術。(重寫了類??)
Spring Loaded項目提供了另一個選擇,但是支持的框架不夠多,且沒有商業支持。
一些特定的資源改變時沒有必要引起重啟。有一些不會引起重啟,但是會重加載。如果你想自定義的設置一下,可以使用
spring.devtools.restart.exclude 屬性。如下:
spring.devtools.restart.exclude=static/**,public/**
如果想在默認的設置之外
再添加新的排除選項,可以使用
spring.devtools.restart.additional-exclude 屬性。
如果想在修改classpath之外的文件時也讓應用重啟,可以使用 spring.devtools.restart.additional-paths 屬性。還可以配合上面提到的
spring.devtools.restart.exclude 屬性,來控制是重啟還是重加載。
如果不想使用自動重啟功能,可以使用
spring.devtools.restart.enabled 屬性。多數情況下,可以在 application.properties 中設置,這樣
仍然會創建一個restart類加載器,但不再監視改變。
如果想完全禁止自動重啟,需要在調用
SpringApplication.run(..) 之前設置一個System屬性。如下:
public static void main(String[] args) { System.setProperty("spring.devtools.restart.enabled", "false"); SpringApplication.run(MyApp.class, args); }
如果你的IDE會隨改隨編譯,你可能會傾向於只在特定時刻引發重啟(否則會很煩人,而且性能下降)。這時,你可以使用“trigger file”,就是一個特定的文件,只有修改這個文件時才會觸發重啟。使用
spring.devtools.restart.trigger-file 屬性即可。(還可以設置為全局屬性,這樣所有的項目都可以使用了!見十八。)
自定義restart類加載器。
如果有一個多模塊項目,只有部分導入到你的IDE中,你可能需要自定義一下。首先創建一個文件:META-INF/spring-devtools.properties。該文件中,可以有以前綴
restart.exclude. 和
restart.include. 開頭的屬性。前者會被放入base類加載器,后者則被放入restart類加載器。
該屬性的value,是正則表達式。例如:
restart.include.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar
注意,key只要是前綴 restart.exclude. 和 restart.include. 開頭即可,
后綴任意。
已知限制:
自動重啟,在使用 ObjectInputStream 反序列化時,會出問題。如果你想使用反序列化,應該使用Spring的 ConfigurableObjectInputStream 配合 Thread.currentThread().getContextClassLoader() 使用。
可惜的是,一些第三方jars中沒有考慮到這個問題,無解。
spring-boot-devtools 模塊內置了一個 LiveReload Server,可以保證在改變資源時 瀏覽的刷新。LiveReload的瀏覽器擴展,免費支持Chrome、Firefox、Safari。
如果想禁用:
spring.devtools.livereload.enabled=false 。
注意:只能運行
一個LiveReload Server。如果同時開啟多個項目,那只有第一個。
$HOME 文件夾下添加一個文件
.spring-boot-devtools.properties ,該文件中的內容會被作用於所有的Spring Boot項目。例如設置
觸發文件:
spring.devtools.reload.trigger-file=.reloadtrigger
Spring Boot 的developer tools也可以在遠程使用(應該是使用一部分)。需要開啟支持。例如:
spring.devtools.remote.secret=mysecret
問題:值是什么意思?
注意:不要在生產環境下開啟!!
遠程devtools支持是成對出現的。服務器端+客戶端。當設置了上面的屬性時,服務器端會自動開啟。
運行遠程客戶端應用:
運行 org.springframework.boot.devtools.RemoteSpringApplication ,需要使用和遠程項目相同的classpath!
傳遞給應用的non-option參數應該是你要連接到的URL。(
問題,什么是non-option參數?)
例如,你在使用Eclipse或者STS,有一個項目 my-app ,部署到了Cloud Foundry,那你需要進行如下操作:
Select Run -> Run Configurations...
Create a new Java Application "launch configuration"
Browse for the my-app project
Use org.springframework.boot.devtools.RemoteSpringApplication as the main class.
Add https://myapp.cfapps.io to the Program arguments (or whatever your remote URL is).


代理訪問遠程的設置方法(略)。p47(60/346)
遠程方式下,客戶端的任何更新都會被push到服務器端,並按設置觸發restart。比較快。
並不總是能開啟Java遠程調試功能。(直接翻譯的,略拗口。其實就是有時候能開啟,有時候不能)
為了改進這些限制,devtools支持Http協議的遠程調試通道。遠程客戶端提供了一個本地服務器(默認8000端口,可修改),用於綁定遠程調試器。當一個連接被創建時,debug信息就會通過HTTP發送到遠程應用。
修改默認端口:
spring.devtools.remote.debug.local-port 。
但是,首先,你需要確認遠程應用以遠程調試方式啟動。通常,配置JAVA_OPTS即可達到目的。例如,在Cloud Foundry上,你可以在 manifest.yml 中添加如下信息:
---
env:
JAVA_OPTS: "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n"
注意,通過網絡進行遠程調試,可能很慢,所以你需要增加超時時間。Eclipse中:Java -> Debug -> Debugger timeout (ms),設成60000很不錯。
Executable jars可以直接在生產環境下使用。
其他的生產就緒功能,例如監控等,可以考慮
spring-boot-actuator 。后面會有介紹。