# 20\. 開發工具
Spring Boot包括一組額外的工具,可以使應用程序開發體驗更加愉快。 spring-boot-devtools模塊可以包含在任何項目中,以提供額外的[開發時](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/development-time)功能。 要包含devtools支持,只需將模塊依賴關系添加到您的構建中:
Maven:
```
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
```
Gradle:
```
dependencies {
compile("org.springframework.boot:spring-boot-devtools")
}
```
> 當運行完全打包的應用程序時,開發人員工具將自動禁用。 如果您的應用程序是使用java -jar啟動的,或者是使用特殊的類加載器啟動,那么它將會被認為是“生產環境的應用程序”。 將開發工具依賴關系標記為可選(optional)是一種最佳做法,可以防止使用項目將devtools傳遞性地應用于其他模塊。 Gradle不支持開箱即用的可選依賴項,因此您可能希望在此期間查看[propdeps-plugin](https://github.com/spring-projects/gradle-plugins/tree/master/propdeps-plugin)。
> 重新打包的jar包默認情況下不包含devtools。 如果要使用某些[遠程devtools功能](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-remote),您需要禁用excludeDevtools 構建下的屬性以包含devtools。 該屬性支持Maven和Gradle插件。
### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#201-屬性默認值)20.1 屬性默認值
Spring Boots支持的幾個庫使用緩存來提高性能。 例如,[模板引擎](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-template-engines)將緩存編譯的模板,以避免重復解析模板文件。 此外,Spring MVC可以在返回靜態資源時向響應中添加HTTP緩存頭。
雖然緩存在生產中非常有益,但它在開發過程中可能會產生反效果,從而阻止您看到剛剛在應用程序中進行的更改。 因此,spring-boot-devtools將默認禁用這些緩存選項。
緩存選項通常由您的application.properties文件中的設置配置。 例如,Thymeleaf提供了spring.thymeleaf.cache屬性。 spring-boot-devtools模塊不需要手動設置這些屬性,而是自動應用更加合理的開發時(development-time)配置。
> 有關應用的屬性的完整列表,請參閱?[DevToolsPropertyDefaultsPostProcessor](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsPropertyDefaultsPostProcessor.java)。
### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#202-自動重啟)20.2 自動重啟
使用spring-boot-devtools的應用程序將在類路徑上的文件發生更改時自動重新啟動。 這在IDE中開發時可能是一個有用的功能,因為它為代碼更改提供了非常快的反饋循環。 默認情況下,將監視指向文件夾的類路徑上的任何條目。 請注意,某些資源(如靜態資源和視圖模板)不需要重新啟動應用程序。
觸發重啟
當DevTools監視類路徑資源時,觸發重新啟動的唯一方法是更新類路徑中的文件時。 導致類路徑更新的方式取決于您正在使用的IDE。 在Eclipse中,保存修改的文件將導致類路徑被更新并觸發重新啟動。 在IntelliJ IDEA中,構建項目(Build→Make Project)將具有相同的效果。
> 只要 forking 被啟用,您也可以通過支持的構建插件(即Maven和Gradle)啟動應用程序,因為DevTools需要一個單獨的應用程序類加載器才能正常運行。Gradle和Maven默認情況下在類路徑上檢DevTools。
> 自動重啟當與LiveReload一起使用時工作非常好。 詳見[下文](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-livereload)。 如果您使用JRebel,自動重啟將被禁用,有利于動態類重新加載。 其他devtools功能仍然可以使用(如LiveReload和屬性覆蓋)。
> DevTools依賴于應用程序上下文的關閉鉤子,以在重新啟動期間關閉它。 如果禁用了關閉掛鉤(SpringApplication.setRegisterShutdownHook(false)),DevTools將無法正常工作。
> 當判斷類路徑中的項目是否會在更改時觸發重新啟動時,DevTools會自動忽略名為spring-boot,spring-boot-devtools,spring-boot-autoconfigure,spring-boot-actuator和spring-boot-start的項目。
重新啟動(Restart) vs 重新加載(Reload)
Spring Boot提供的重新啟動技術使用兩個類加載器。 不會改的類(例如,來自第三方的jar)被加載到基類加載器中。 您正在開發的類被加載到重新啟動(restart)類加載器中。 當應用程序重新啟動時,重新啟動類加載器將被丟棄,并創建一個新的類加載器。 這種方法意味著應用程序重新啟動通常比“冷啟動”快得多,因為基類加載器已經可以使用。
如果發現重新啟動對應用程序不夠快,或遇到類加載問題,您可以考慮來自ZeroTurnaround的JRebel等重新加載技術。 這些工作通過在加載類時重寫(rewriting)類,使其更適合重新加載。 Spring Loaded提供了另一個選項,但是它在很多框架上不支持,并且不支持商用。
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2021-排除資源)20.2.1 排除資源
在類路徑下,某些資源在更改時不一定需要觸發重新啟動。 例如,Thymeleaf模板可以直接編輯不需重啟。 默認情況下,有一些排除項,更改 /META-INF/maven,/META-INF/resources,/resources,/static,/public或/templates中的資源不會觸發重新啟動,但會觸發[實時重新加載](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-livereload)。 如果要自定義這些排除項,可以使用spring.devtools.restart.exclude屬性。 例如,要僅排除 /static和 /public,您可以設置:
```
spring.devtools.restart.exclude=static/**,public/**
```
> 如果要保留這些默認值并添加其他排除項,請改用spring.devtools.restart.additional-exclude屬性。
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2022-監視額外的路徑)20.2.2 監視額外的路徑
有時當您對不在類路徑中的文件進行更改時,需要重新啟動或重新加載應用程序。為此,請使用spring.devtools.restart.additional-paths屬性來配置其他路徑以監視更改。 您可以使用[上述](described above)的spring.devtools.restart.exclude屬性來控制附加路徑下的更改是否會觸發完全重新啟動或只是[實時重新加載](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-livereload)。
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2023-禁用重啟)20.2.3 禁用重啟
如果不想使用重新啟動功能,可以使用spring.devtools.restart.enabled屬性來禁用它。 在大多數情況下,您可以在application.properties中設置此項(這仍將初始化重新啟動類加載器,但不會監視文件更改)。
例如,如果您需要完全禁用重新啟動支持,因為它在一些特定庫中不能正常運行,則需要在調用SpringApplication.run(...)之前設置System屬性。 例如:
```
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}
```
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2024-使用觸發文件)20.2.4 使用觸發文件
如果您使用IDE工具編寫代碼,更改文件,則您可能希望僅在特定時間觸發重新啟動。 為此,您可以使用“觸發文件”,這是一個特殊文件,當您要實際觸發重新啟動檢查時,必須修改它。 更改文件只會觸發檢查,只有在Devtools檢測到它必須執行某些操作時才會重新啟動。 觸發文件可以手動更新,也可以通過IDE插件更新。
要使用觸發器文件,請使用spring.devtools.restart.trigger-file屬性。
> 您可能希望將spring.devtools.restart.trigger-file設置為[全局設置](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-boot-devtools-globalsettings),以使所有項目的行為方式相同。
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2025-自定義重新啟動類加載器)20.2.5 自定義重新啟動類加載器
如上面的?[Restart vs Reload](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#using-spring-boot-restart-vs-reload)?部分所述,重新啟動功能是通過使用兩個類加載器實現的。 對于大多數應用程序,此方法運行良好,但有時可能會導致類加載問題。
默認情況下,IDE中的任何打開的項目將使用“重新啟動”類加載器加載,任何常規.jar文件將使用“base”類加載器加載。 如果您在多模塊項目上工作,而不是每個模塊都導入到IDE中,則可能需要自定義事件。 為此,您可以創建一個META-INF / spring-devtools.properties文件。
spring-devtools.properties文件可以包含restart.exclude 和 restart.include.prefixed屬性。 include元素是應該被拉入“重新啟動(restart)”類加載器的項目,排除元素是應該向下推入“基本(base)”類加載器的項目。 屬性的值是將應用于類路徑的正則表達式模式。
例如:
```
restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar
```
> 所有屬性鍵必須是唯一的。 只要一個屬性從restart.include. 或restart.exclude. 開始,將被考慮。
> 將加載類路徑中的所有META-INF/spring-devtools.properties。 您可以在項目中打包文件,或者在項目所使用的庫中打包文件。
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2026-已知的限制)20.2.6 已知的限制
重新啟動功能對于使用標準ObjectInputStream反序列化的對象無效。 如果需要反序列化數據,可能需要使用Spring的ConfigurableObjectInputStream與Thread.currentThread()。getContextClassLoader()組合使用。
不幸的是,幾個第三方庫在不考慮上下文類加載器的情況下反序列化。 如果您發現這樣的問題,您需要向原始作者請求修復。
### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#203-livereload)20.3 LiveReload
spring-boot-devtools模塊包括一個嵌入式LiveReload服務器,可以在資源更改時用于觸發瀏覽器刷新。 LiveReload瀏覽器擴展程序可以從?[http://livereload.com](http://livereload.com/)免費獲取Chrome,Firefox和Safari的插件。
如果您不想在應用程序運行時啟動LiveReload服務器,則可以將spring.devtools.livereload.enabled屬性設置為false。
> 一次只能運行一個LiveReload服務器。 開始應用程序之前,請確保沒有其他LiveReload服務器正在運行。 如果從IDE啟動多個應用程序,則只有第一個應用程序將支持LiveReload。
### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#204-全局設置)20.4 全局設置
您可以通過向 $HOME 文件夾添加名為.spring-boot-devtools.properties的文件來配置全局devtools設置(請注意文件名以“.”開頭)。 添加到此文件的任何屬性將適用于您的計算機上使用devtools的所有Spring Boot應用程序。 例如,要配置重新啟動以始終使用觸發器文件,您可以添加以下內容:
~/.spring-boot-devtools.properties.
```
spring.devtools.reload.trigger-file=.reloadtrigger
```
### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#205遠程應用)20.5遠程應用
Spring Boot開發工具不僅限于本地開發。 遠程運行應用程序時也可以使用多種功能。 遠程支持是可選擇的,要使其能夠確保重新打包的存檔中包含devtools:
```
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>
```
那么你需要設置一個spring.devtools.remote.secret屬性,例如:
```
spring.devtools.remote.secret=mysecret
```
> 在遠程應用程序上啟用spring-boot-devtools是一種安全隱患。 您不應該在生產部署中啟用該支持。
遠程devtools支持分為兩部分: 有一個接受連接的服務器端和您在IDE中運行的客戶端應用程序。 當spring.devtools.remote.secret屬性設置時,服務器組件將自動啟用。 客戶端組件必須手動啟動。
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2051-運行遠程客戶端應用程序)20.5.1 運行遠程客戶端應用程序
遠程客戶端應用程序旨在從IDE中運行。 您需要使用與要連接的遠程項目相同的類路徑運行org.springframework.boot.devtools.RemoteSpringApplication。 傳遞給應用程序的必選參數應該是您要連接到的遠程URL。
例如,如果您使用Eclipse或STS,并且有一個名為my-app的項目已部署到Cloud Foundry,則可以執行以下操作:
* 從Run 菜單中選擇Run Configurations…。
* 創建一個新的Java Application “launch configuration”。
* 瀏覽my-app項目。
* 使用org.springframework.boot.devtools.RemoteSpringApplication作為主類。
* 將
運行的遠程客戶端將如下所示:
```
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: 1.5.2.RELEASE
2015-06-10 18:25:06.632 INFO 14938 --- [ main] o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-boot-samples/spring-boot-sample-devtools)
2015-06-10 18:25:06.671 INFO 14938 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043 WARN 14938 --- [ main] o.s.b.d.r.c.RemoteClientConfiguration : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074 INFO 14938 --- [ main] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2015-06-10 18:25:07.130 INFO 14938 --- [ main] o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)
```
> 由于遠程客戶端正在使用與實際應用程序相同的類路徑,因此可以直接讀取應用程序屬性。 這是spring.devtools.remote.secret屬性如何讀取并傳遞到服務器進行身份驗證。
> 建議使用https//作為連接協議,以便流量被加密,防止密碼被攔截。
> 如果需要使用代理訪問遠程應用程序,請配置spring.devtools.remote.proxy.host和spring.devtools.remote.proxy.port屬性。
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2052-遠程更新)20.5.2 遠程更新
遠程客戶端將以與本地相同的方式監視應用程序類路徑的更改。 任何更新的資源將被推送到遠程應用程序,并且(如果需要的話)觸發重新啟動。 如果您正在迭代使用您當地沒有的云服務的功能,這可能會非常有用。 通常,遠程更新和重新啟動比完全重建和部署周期要快得多。
> 僅在遠程客戶端運行時才監視文件。 如果在啟動遠程客戶端之前更改文件,則不會將其推送到遠程服務器。
#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2053-遠程調試隧道)20.5.3 遠程調試隧道
在遠程應用程序診斷問題時,Java遠程調試非常有用。 不幸的是,當您的應用程序部署在數據中心之外時,并不總是能夠進行遠程調試。 如果您正在使用基于容器的技術(如Docker),遠程調試也可能難以設置。
為了幫助解決這些限制,devtools支持基于HTTP隧道的傳輸遠程調試傳輸。 遠程客戶端在端口8000上提供本地服務器,您可以連接遠程調試器。 建立連接后,通過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"
```
> 請注意,您不需要將 address=NNNN 選項傳遞給-Xrunjdwp。 如果省略Java將隨機選擇一個的空閑端口。
> 通過網絡調試遠程服務可能很慢,您可能需要在IDE中增加超時時間。 例如,在Eclipse中,您可以從Preferences...中選擇Java→Debug ,并將Debugger timeout (ms)更改為更合適的值(大多數情況下,60000可以正常工作)。
> 當使用IntelliJ IDEA的遠程調試隧道時,必須將所有調試斷點配置為掛起線程而不是掛起VM。 默認情況下,IntelliJ IDEA中的斷點會掛起整個VM,而不是僅掛起觸發斷點的線程。 這會導致掛起管理遠程調試通道的線程等不必要的副作用,導致調試會話凍結。 當使用IntelliJ IDEA的遠程調試隧道時,應將所有斷點配置為掛起線程而不是VM。 有關詳細信息,請參閱[IDEA-165769](https://youtrack.jetbrains.com/issue/IDEA-165769)。
- Part I. Spring Boot 文檔
- Part II. 入門指南
- 8. Spring Boot 介紹
- 9. 系統要求
- 10. 安裝 Spring Boot
- 11. 開發您的第一個Spring Boot應用程序
- 12. 接下來應該讀什么
- Part III. 使用 Spring Boot
- 13. 構建系統
- 14. 構建代碼
- 15. 配置類
- 16. 自動配置
- 17. Spring Beans 和 依賴注入
- 18. 使用@SpringBootApplication注解
- 19. 運行你的應用程序
- 20. 開發工具
- 21. 包裝您的應用程序到生產環境
- 22. 接下來應該讀什么
- Part IV. Spring Boot 功能
- 23. SpringApplication
- 24. 外部配置
- 25. 配置文件(Profiles)
- 26. 日志
- 27. 開發Web應用程序
- 28. Security
- 29. 使用SQL數據庫