Spring Boot 官方文檔學(xué)習(xí)(一)入門及使用
個(gè)人說(shuō)明:本文內(nèi)容都是從為知筆記上復(fù)制過來(lái)的,樣式難免走樣,以后再修改吧。另外,本文可以看作官方文檔的選擇性的翻譯(大部分),以及個(gè)人使用經(jīng)驗(yàn)及問題。
其他說(shuō)明:如果對(duì)Spring Boot沒有概念,請(qǐng)先移步上一篇文章 Spring Boot 學(xué)習(xí)。本篇原本是為了深入了解下Spring Boot而出現(xiàn)的。
另外,Spring Boot 仍然是基于Spring的,建議在趕完工之后深入學(xué)習(xí)下Spring,有興趣可以看看我的 Spring 4 官方文檔學(xué)習(xí)(十一)Web MVC 框架 。歡迎探討,笑~
目錄:
- 內(nèi)置Servlet Container
- 使用Spring Boot
- 安裝Spring Boot CLI
- 開發(fā)一個(gè)簡(jiǎn)單的Spring Boot應(yīng)用--使用最原始的方式
- Dependency Management
- Starters
- 自動(dòng)配置
- Spring Beans 和 依賴注入(略)
- @SpringBootApplication
- 運(yùn)行Spring Boot Application
- Developer tools
- 生產(chǎn)打包
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項(xiàng)目到任何兼容Servlet3.0+的容器。
你可以像使用標(biāo)準(zhǔn)的Java庫(kù)文件一樣使用Spring Boot。簡(jiǎn)單的將需要的 spring-boot-*.jar 添加到classpath即可。
Spring Boot不要求任何特殊的工具集成,所以可以使用任何IDE,甚至文本編輯器。
只是,仍然建議使用build工具:Maven 或 Gradle。
Spring Boot依賴 使用
org.springframework.boot groupId 。 通常,讓你的Maven POM文件繼承 spring-boot-starter-parent,并聲明一個(gè)或多個(gè) Starter POMs依賴即可。Spring Boot也提供了一個(gè)可選的 Maven Plugin來(lái)創(chuàng)建可執(zhí)行的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 是一個(gè)非常好的方法,但并不適用于所有情況。有時(shí)你需要繼承其他的POM,或者你不喜歡默認(rèn)的設(shè)置。-- 辦法見后面。
這是一個(gè)命令行工具,可以執(zhí)行Groove腳本。是執(zhí)行一個(gè)Spring Boot的最快途徑。
-- 好吧,Linux下無(wú)敵,Win下還是休息吧。
務(wù)必注意:前提是maven + jdk。
2、新建一個(gè)pom.xml文件。內(nèi)容如下:
<?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>
當(dāng)然,你也可以使用IDE,不過使用文本編輯器會(huì)讓我們對(duì)它更理解。

由于我們已經(jīng)繼承了 spring-boot-starter-parent ,而 spring-boot-starter-parent 又提供了 dependency-management ,所以我們可以忽略被選中依賴的版本。
在添加依賴之前,我們先看一下現(xiàn)在已有什么:mvn dependency:tree。該命令會(huì)打印一個(gè)當(dāng)前項(xiàng)目的依賴樹。
結(jié)果表明,當(dāng)前沒有任何依賴。

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

可以看出,spring-boot-starter-web 包含了很多內(nèi)容,spring-webmvc、spring-web、jackson、validation、tomcat、starter。
由于Maven默認(rèn)編譯路徑為 src/main/java 下面的源碼,所以,默認(rèn)設(shè)置下,需要?jiǎng)?chuàng)建這些文件夾。
然后,編寫文件 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); } }
這里我們只需要關(guān)心 @EnableAutoConfiguration 即可。這個(gè)注解是讓Spring Boot猜測(cè) 你想怎么配置Spring,但實(shí)際上,它是根據(jù)你添加到classpath中的依賴來(lái)判斷的。
注意,自動(dòng)配置 可以配合 Starter POMs 一起工作,但二者不是捆綁到一起的。你仍然可以將Starter POMs中的依賴單獨(dú)揀出使用,Spring Boot還是會(huì)自動(dòng)配置。
6、啟動(dòng)項(xiàng)目。由于我們使用了 spring-boot-starter-parent POM,所以可以使用 mvn spring-boot:run來(lái)啟動(dòng)項(xiàng)目(根路徑)。
啟動(dòng)之后就可以訪問了,默認(rèn)地址: 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,你需要自己來(lái)聲明這個(gè)配置信息。
現(xiàn)在,可以打包了: mvn package 。

現(xiàn)在,你可以在/target目錄下看到 myproject-0.0.1-SNAPSHOT.jar ,大約10 Mb左右??梢酝ㄟ^ jar tvf target/myproject-0.0.1-SNAPSHOT.jar 來(lái)查看其中的內(nèi)容。
此外,在/target目錄下,還可以看到 myproject-0.0.1-SNAPSHOT.jar.original ,這是Maven打包出來(lái)的---在Spring Boot repackage 之前。

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


代理訪問遠(yuǎn)程的設(shè)置方法(略)。p47(60/346)
遠(yuǎn)程方式下,客戶端的任何更新都會(huì)被push到服務(wù)器端,并按設(shè)置觸發(fā)restart。比較快。
并不總是能開啟Java遠(yuǎn)程調(diào)試功能。(直接翻譯的,略拗口。其實(shí)就是有時(shí)候能開啟,有時(shí)候不能)
為了改進(jìn)這些限制,devtools支持Http協(xié)議的遠(yuǎn)程調(diào)試通道。遠(yuǎn)程客戶端提供了一個(gè)本地服務(wù)器(默認(rèn)8000端口,可修改),用于綁定遠(yuǎn)程調(diào)試器。當(dāng)一個(gè)連接被創(chuàng)建時(shí),debug信息就會(huì)通過HTTP發(fā)送到遠(yuǎn)程應(yīng)用。
修改默認(rèn)端口: spring.devtools.remote.debug.local-port 。
但是,首先,你需要確認(rèn)遠(yuǎn)程應(yīng)用以遠(yuǎn)程調(diào)試方式啟動(dòng)。通常,配置JAVA_OPTS即可達(dá)到目的。例如,在Cloud Foundry上,你可以在 manifest.yml 中添加如下信息:
---
env:
JAVA_OPTS: "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n"
注意,通過網(wǎng)絡(luò)進(jìn)行遠(yuǎn)程調(diào)試,可能很慢,所以你需要增加超時(shí)時(shí)間。Eclipse中:Java -> Debug -> Debugger timeout (ms),設(shè)成60000很不錯(cuò)。
Executable jars可以直接在生產(chǎn)環(huán)境下使用。
其他的生產(chǎn)就緒功能,例如監(jiān)控等,可以考慮 spring-boot-actuator 。后面會(huì)有介紹。
posted on 2016-08-23 14:26 LarryZeal 閱讀(588569) 評(píng)論(8) 收藏 舉報(bào)
浙公網(wǎng)安備 33010602011771號(hào)