使用Spring Boot DevTools加快開發速度

2018年11月2日 上次更新時間:2019年4月28日html

Spring Boot開發者工具

DevTools 支持 自動刷新自動重啓 –自動刷新(或自動加載)是指在瀏覽器中從新加載UI,以查看靜態內容的更改。自動從新啓動是指從新加載服務器端代碼和配置,而後從新啓動服務器。

如何使用DevTools進一步加快Spring Boot開發的速度,並使之更加有趣和高效?前端

設定

像一般使用Spring Boot同樣,設置很是簡單。您須要作的就是添加正確的依賴關係,您就能夠開始工做了。Spring Boot會檢測到這一點,並相應地自動配置DevTools。java

若是您使用的是Maven:react

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

另外,在使用Gradle時:spring

configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
}
dependencies {
    developmentOnly("org.springframework.boot:spring-boot-devtools")
}

請注意,該依賴項被聲明爲可選。這個很重要。這樣能夠防止將DevTools依賴項過渡性地應用於依賴於項目的其餘模塊。瀏覽器

自動重啓

只要您的類路徑上的文件發生更改,DevTools就會在應用了新更改的狀況下自動重啓正在運行的應用程序。在本地進行開發時,這頗有用,由於您無需手動從新部署應用程序。緩存

就其自己而言,它並非那麼有用,由於從新啓動仍會花費大量時間。幸運的是,因爲DevTools使用了一個巧妙的技巧,這些重啓比常規重啓快得多。安全

您會看到,在開發應用程序時,一般會更改一個或幾個類,並但願在運行的應用程序中檢查結果以獲取反饋。您更改了應用程序的一小部分,由於大多數已加載的類來自框架和第三方庫。服務器

引擎蓋下,Spring DevTools 使用兩個類加載器—— BaseClassLoader 和 RestartClassLoader。不變的類由基本類加載器加載。正在使用的類由從新啓動類加載器加載。每當觸發從新啓動時,從新啓動類加載器都會被丟棄並從新建立。這種重啓應用程序的速度比日常快得多,而且能夠替代使用諸如 JRebel 之類的動態類來從新加載應用程序。session

在IDE中觸發重啓

只要類路徑發生更改,就會觸發從新啓動。可是,這取決於您的IDE。這意味着僅更改 .java 文件是不夠的。重要的是您的IDE實際上會更新 .class 類路徑上的文件。

使 IntelliJ IDEA 時,須要構建項目(Ctrl+ F9或Build → Build Project)。您還能夠將 IDEA 配置爲自動重建。另外,您能夠打開Spring Boot運行配置並定義觸發應用程序更新(Ctrl+ F10)時發 生的狀況:

圖片描述

Intellij IDEA Spring Boot 運行配置

在第一個組合框中,能夠選擇 Update trigger file 在調用 Update 操做時觸發 DevTools 從新啓動。或者,您甚至能夠選擇嘗試熱插拔的選項,而且僅在熱插拔失敗時才使用 DevTools 從新啓動。

在第二個組合框中,您能夠配置在 IDEA 窗口失去焦點時(例如,切換到瀏覽器窗口時)從新加載全部靜態資源和模板。

在 Eclipse 中,僅保存文件就足夠了。

僅開發

Spring Boot DevTools 的使用僅用於開發,而不用於生產。若是您的應用程序檢測到您正在生產中,則將自動禁用 DevTools。

爲此,每當您將應用程序做爲徹底打包的工件(例如帶有嵌入式應用程序服務器的jar)運行時,都將其視爲生產應用程序:

java -jar devtools-example-1.0.0.jar

經過特殊的類加載器(例如在應用程序服務器上)啓動應用程序時,一樣適用。相反,當您運行分解的工件(例如在IDE中)時,您的應用程序將被視爲處於開發模式。使用 spring-boot-plugin 運行應用程序時也是如此:

Maven:

mvn spring-boot:run

Gradle:

gradle bootRun

實時重載

LiveReload 是一個有用的工具,它使您能夠在更改 HTML,CSS,圖像等文件時當即在瀏覽器中更新頁面。它甚至能夠根據須要對文件進行預處理-這意味着會自動編譯您的 SASS 或 LESS 文件。

實時從新加載

Spring DevTools 自動啓動 LiveReload 服務器的本地實例,該實例監視您的文件。您所須要作的就是安裝瀏覽器擴展程序,一切順利。它不只對開發應用程序的前端頗有用(以防您將其做爲Spring應用程序工件的一部分進行分發),並且還能夠用於監視和從新加載REST API的輸出。
圖片描述

屬性覆蓋

在本地開發應用程序時,一般與在生產環境中運行時具備不一樣的配置需求。緩存就是一個例子。在生產中,相當重要的是依賴於各類緩存(例如,模板引擎的緩存,靜態資源的緩存頭等)。在開發中,它可能會因提供舊數據而沒有反映您的最新更改而使您感到痛苦。另外一個示例多是加強的日誌記錄,它在開發中可能有用,但對於生產而言卻過於詳細。

本身管理雙套配置沒必要要地複雜。好消息是,Spring Boot DevTools開箱即用爲您的本地開發配置了許多屬性。

spring.thymeleaf.cache=false
spring.freemarker.cache=false
spring.groovy.template.cache=false
spring.mustache.cache=false
server.servlet.session.persistent=true
spring.h2.console.enabled=true
spring.resources.cache.period=0
spring.resources.chain.cache=false
spring.template.provider.cache=false
spring.mvc.log-resolved-exception=true
server.servlet.jsp.init-parameters.development=true
spring.reactor.stacktrace-mode.enabled=true

您能夠在DevToolsPropertyDefaultsPostProcessor中檢查全部屬性的列表。

遠程鏈接

除了本地開發以外,您還能夠鏈接到運行DevTools的遠程應用程序。這不適用於生產環境,由於它可能會帶來嚴重的安全風險。可是,它在預生產環境中可能很是有用。

啓用遠程鏈接

默認狀況下不啓用遠程鏈接。您須要經過修改pom文件顯式啓用它:

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

或使用gradle,您須要設置 excludeDevtools = false:

bootWar {
    excludeDevtools = false
}

而後,您須要設置一個祕密密碼,以便在鏈接到遠程應用程序時用於身份驗證

spring.devtools.remote.secret=somesecret

鏈接到遠程應用

遠程應用程序運行後,您能夠啓動遠程鏈接會話。如今,您所須要作的就是以org.springframework.boot.devtools.RemoteSpringApplication遠程應用程序的URL做爲參數啓動。請注意,若是可能,應使用https。

圖片描述

在您的IDE中,運行遠程鏈接很是容易。在IDEA中,您只需建立一個新的運行配置。轉到Run → Edit Configurations...並使用左上角的[+]圖標建立新配置。選擇Application類型。

做爲Main類,RemoteSpringApplication從DevTools模塊中選擇,並做爲程序參數傳遞遠程應用程序的URL。

IDEA中的遠程鏈接配置

運行此配置後,若是與遠程應用程序的鏈接成功,您應該會看到相似的輸出。

.   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote ::  (v2.0.6.RELEASE)

2018-11-02 17:24:42.126  INFO 16640 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication v2.0.6.RELEASE on DESKTOP-6NJV4ON with PID 16640 (C:\Users\vojte\.m2\repository\org\springframework\boot\spring-boot-devtools\2.0.6.RELEASE\spring-boot-devtools-2.0.6.RELEASE.jar started by vojte in C:\projects\rest-docs-starter)
2018-11-02 17:24:42.130  INFO 16640 --- [           main] o.s.b.devtools.RemoteSpringApplication   : No active profile set, falling back to default profiles: default
2018-11-02 17:24:42.172  INFO 16640 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3daa422a: startup date [Fri Nov 02 17:24:42 CET 2018]; root of context hierarchy
2018-11-02 17:24:42.679  WARN 16640 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2018-11-02 17:24:42.800  WARN 16640 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : Unable to start LiveReload server
2018-11-02 17:24:42.829  INFO 16640 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 1.212 seconds (JVM running for 1.877)

鏈接到遠程應用程序後,DevTools會監視類路徑更改,就像本地開發同樣。可是,它代替本地重啓,而是將更改推送到遠程服務器並觸發那裏的重啓。這可能比構建應用程序並將其部署到遠程計算機快得多。

全局配置

您能夠像其餘任何Spring應用程序同樣使用配置屬性來配置 DevTools。這一般意味着編輯 application.properties 項目。對於每一個應用程序,此配置都是單獨的。

可是,在某些狀況下,爲在同一臺計算機上運行的全部應用程序進行全局配置可能會很方便。您能夠在 $HOME 目錄中建立一個名爲 .spring-boot-devtools.properties 的屬性文件。該文件中聲明的配置適用於全部運行DevTools的應用程序。

侷限性

實時重加載

使用 DevTools 的 Spring 應用程序會自動啓動 LiveReload 服務器。不幸的是,該服務器只能同時運行一個實例。更準確地說,只有第一個能夠工做。這不只適用於帶有 DevTools 的 Spring 應用程序的多個實例,並且還適用於任何其餘在後臺使用LiveReload 的應用程序,例如處於開發模式的Gatsby

若是您想配置 Spring 應用程序使其不啓動 LiveReload 服務器,則能夠在如下代碼中進行操做 application.properties

spring.devtools.livereload.enabled=false

關機鉤

DevTools 依賴於關閉掛鉤的 SpringApplication。若是您使用如下方式手動禁用了掛接,它將沒法正常工做:

springApplication.setRegisterShutdownHook(false);

默認狀況下,掛鉤是啓用的,所以除非明確禁用它,不然您沒必要擔憂。

與第三方庫的衝突
儘管DevTools一般應該能夠正常運行,但它可能與第三方庫有衝突。特別是,使用standard進行反序列化存在一個已知ObjectInputStream 問題

若是發生此類衝突,能夠經過設置如下方式禁用自動重啓:

spring.devtools.restart.enabled=false

從新啓動將再也不被觸發。可是,仍將使用從新啓動類加載器。若是您須要徹底禁用類加載器,則須要在啓動應用程序以前這樣作:

public static void main(String[] args) {
    System.setProperty("spring.devtools.restart.enabled", "false");
    SpringApplication.run(MyApp.class, args);
}

即便您不使用自動重啓,您仍然能夠從DevTools提供的其餘功能中受益。

啓用延遲初始化

您可使用 @Lazy 註釋將各個bean標記爲延遲初始化。這個功能在Spring已經有一段時間了。從 Spring Boot 2.2 開始,您可使用切換全部 bean 的延遲初始化spring.main.lazy-initialization=true。能夠單獨使用它,也能夠將它與 DevTools 組合使用,以更快地重啓。

DevTools能夠在同一JVM中熱重啓您的應用程序。熱重啓的一個重要好處是,它爲JIT提供了更多機會來優化啓動應用程序所涉及的代碼。重啓幾回後,原來的2500ms時間減小了近80%,接近500ms。經過延遲初始化,咱們能夠作得更好。設置 spring.main.lazy-initialization 能夠看到咱們的應用程序直接在IDE中在400毫秒內從新啓動。

在生產應用程序中對全部bean使用延遲初始化是有問題的。它爲啓動提供了出色的性能提高,但代價​​是單個 Bean 的首次請求時間較長。更重要的是,您的應用程序再也不快速失敗。它不會在啓動應用程序時當即崩潰,而只會在直接請求配置錯誤的bean以後失敗。這可能很是危險,由於直到爲時已晚,您才發現不少錯誤。儘管如此,大規模延遲初始化對於加快開發時間仍是頗有用的,由於在使用某些功能時,您一般只在應用程序的一部分上工做,而其他部分則不使用。理想的折衷方法是僅對本地開發啓用大規模延遲初始化(假設使用spring配置文件),而對於已部署的更高環境禁用它。

結論

經過提供自動重啓和 LiveReload 功能,DevTools 使您的 Spring Boot 應用程序開發更加輕鬆快捷。除此以外,它還將各類屬性設置爲更適合本地開發的值。此外,它容許您遠程鏈接到應用程序,而且仍使用其大多數功能。在生產環境中運行時,不使用 DevTools。有關詳細信息,請參閱官方文檔

相關文章
相關標籤/搜索