點擊上方“芋道源碼”,選擇“設爲星標”
做積極的人,而不是積極廢人!
源碼精品專欄
摘要: 原創出處 http://www.iocoder.cn/Spring-Boot/hot-swap/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!
1. 概述
2. spring-boot-devtools
3. IDEA 熱部署
4. Jrebel
666. 彩蛋
1. 概述
在日常開發中,我們需要經常修改 Java 代碼,手動重啓項目,查看修改後的效果。如果在項目小時,重啓速度比較快,等待的時間是較短的。但是隨着項目逐漸變大,重啓的速度變慢,等待時間 1-2 min 是比較常見的。
這樣就導致我們開發效率降低,影響我們的下班時間,哈哈哈~那麼是否有方式能夠實現,在我們修改完 Java 代碼之後,能夠不重啓項目呢?
答案是有的,通過熱部署的方式。並且實現的方式還是非常多,艿艿在本文就會爲胖友一一展示。
旁白君:嚴格來說,應該叫 HotSwap 的方式,翻譯成中文會有熱部署、熱更新、熱替換、熱加載等等多種。這裏,我們就採用大家可能說的比較多的翻譯,熱部署。
爲了演示方便,胖友可以參考 lab-48-demo 項目,搭建一個簡單的 Spring Boot 項目,提供了一個簡單的 HTTP API。如下圖所示:
友情提示:不要直接通過克隆 https://github.com/YunaiV/SpringBoot-Labs 來使用該項目,實在太大了!
並且,我們下面我們所有的演示,都是在宇宙無敵 Java 開發工具 IDEA 中進行。
2. spring-boot-devtools
spring-boot-devtools
是 Spring Boot 提供的開發者工具,它會監控當前應用所在的 classpath 下的文件發生變化,進行自動重啓。
注意,spring-boot-devtools
並沒有採用熱部署的方式,而是一種較快的重啓方式。其官方文檔解釋如下:
FROM 《Spring Boot 2.X 中文文檔 —— 開發者工具》
Spring Boot 通過使用兩個類加載器來提供了重啓技術。
不改變的類(例如,第三方 jar)被加載到 base 類加載器中。
經常處於開發狀態的類被加載到 restart 類加載器中。
當應用重啓時,restart 類加載器將被丟棄,並重新創建一個新的。這種方式意味着應用重啓比冷啓動要快得多,因爲省去 base 類加載器的處理步驟,並且可以直接使用。
如果您覺得重啓還不夠快,或者遇到類加載問題,您可以考慮如 ZeroTurnaround 的 JRebel 等工具。他們是通過在加載類時重寫類來加快重新加載。
在項目中,我們需要在 pom.xml
中,引入 spring-boot-devtools
依賴如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 可選 -->
</dependency>
2.1 演示
下面,我們來演示下 spring-boot-devtools
的使用。
① Run 或者 Debug 運行 Spring Boot 應用。
使用瀏覽器,訪問 http://127.0.0.1:8080/demo/echo 接口,返回結果爲 "echo"
。
② 修改 DemoController 的 #echo()
方法,設置返回值爲 "none"
。
【關鍵】 我們現在僅僅需要修改了 Java 代碼,需要重新編譯下代碼。點擊 IDEA 的菜單 Build
-> Build Project
,手動進行編譯。如下圖所示:
友情提示:如果胖友嫌棄鼠標操作太慢,可以使用
Build Project
的快捷鍵:
Mac:Command + F9
Windows:Ctrl + F9
此時,IDEA 控制檯會看到 Spring Boot 重新啓動的日誌如下:
2020-02-09 09:22:52.082 INFO 36495 --- [ Thread-10] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.4.RELEASE)
2020-02-09 09:22:52.195 INFO 36495 --- [ restartedMain] cn.iocoder.demo03.Demo03Application : Starting Demo03Application on MacBook-Pro-8 with PID 36495 (/Users/yunai/Downloads/demo03/target/classes started by yunai in /Users/yunai/Downloads/demo03)
2020-02-09 09:22:52.195 INFO 36495 --- [ restartedMain] cn.iocoder.demo03.Demo03Application : No active profile set, falling back to default profiles: default
2020-02-09 09:22:52.335 INFO 36495 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-02-09 09:22:52.336 INFO 36495 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-02-09 09:22:52.336 INFO 36495 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.30]
2020-02-09 09:22:52.342 INFO 36495 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-02-09 09:22:52.342 INFO 36495 --- [ restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 145 ms
2020-02-09 09:22:52.382 INFO 36495 --- [ restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-02-09 09:22:52.409 INFO 36495 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2020-02-09 09:22:52.418 INFO 36495 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-02-09 09:22:52.419 INFO 36495 --- [ restartedMain] cn.iocoder.demo03.Demo03Application : Started Demo03Application in 0.244 seconds (JVM running for 169.162)
2020-02-09 09:22:52.420 INFO 36495 --- [ restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged
???? 所以
spring-boot-devtools
真的不是熱部署,而是更快的重啓方式。
使用瀏覽器,再次訪問 http://127.0.0.1:8080/demo/echo
接口,返回結果爲 "none"
,成功!
咳咳咳,下面我們來講解下自動編譯。艿艿自己嘗試了,親測失敗。例如說 《IDEA 配置 Spring Boot 熱更新,無需手動按 ctrl+F9》 文章。看了下評論,貌似其它人也存在失敗的情況。
反正這裏也寫下步驟,胖友可以自己嘗試一波~萬一成功了,請一定留言,我好找找具體原因。
③ 可能有胖友會覺得手動 Build Project
有點麻煩,IDEA 還提供的自動編譯的選項。設置方式,點擊 IDEA 的菜單 IntelliJ IDEA
-> Preference...
,然後選擇 Compiler
選項卡,將 Build project automatically
勾選上。如下圖所示:
友情提示:注意,
Build project automatically
後面的一行提示,自動編譯僅在項目不處於運行,或者處於 Debug 運行中時,纔會自動生效。
所以一定要 Debug 運行 Spring Boot 項目。具體的效果,胖友自己重複 ① ② 兩個步驟,自己嘗試下。
另外,網上我們會看到教程,建議將 compiler.automake.allow.when.app.running
勾選上。
原因是,自動編譯在 Running 運行中默認是不生效的,通過勾選上
compiler.automake.allow.when.app.running
,允許在 Running 運行中也生效。個人建議的話,不要勾選。如果 Running 運行中修改了代碼,也會導致熱部署,不太合適。如果真要熱部署,使用 Debug 運行項目更合理。
2.2 結論
因爲 spring-boot-devtools
提供的本質是重啓的方式,所以還是會存在我們在文章開頭所提到的問題。不過不要慌,實際上 IDEA 自帶了熱部署的方式,畢竟是宇宙第一 Java 開發工具,吹爆就完事了。
3. IDEA 熱部署
友情提示:如果胖友看了「2. spring-boot-devtools」小節,並進行了相關操作,請全部復原,特別是去掉
spring-boot-devtools
依賴。
IDEA 提供了 HotSwap 插件,可以實現真正的熱部署。如下圖所示:
3.1 演示
下面,我們來演示下 HotSwap 插件的使用。
① Run 或者 Debug 運行 Spring Boot 應用。
使用瀏覽器,訪問 http://127.0.0.1:8080/demo/echo 接口,返回結果爲 "echo"
。
② 修改 DemoController 的 #echo()
方法,設置返回值爲 "none"
。
【關鍵】 我們現在僅僅需要修改了 Java 代碼,需要重新編譯下代碼。點擊 IDEA 的菜單 Build
-> Build Project
,手動進行編譯。如下圖所示:
友情提示:如果胖友嫌棄鼠標操作太慢,可以使用
Build Project
的快捷鍵:
Mac:Command + F9
Windows:Ctrl + F9
此時,我們在 IDEA 中可以看修改的類被重載的提示。如下圖所示:
使用瀏覽器,再次訪問 http://127.0.0.1:8080/demo/echo
接口,返回結果爲 "none"
,成功!
③ 嘗試將 Build project automatically
勾選上,希望實現自動編譯,再搭配上 HotSwap 插件的熱部署,豈不是更香?!
結果失敗,和「2.1 演示」出現一樣的問題,略微蛋疼。
這裏我們來換一種方式,也能實現自動編譯。操作步驟如下圖:
要注意,需要焦點從 IDEA 離開。例如說,在我們修改完接口的代碼之後,可能會切換到瀏覽器或者 Postman 對該接口進行測試,此時 IDEA 就會自動更新代碼和資源,進行熱部署。
現在,我們來 修改 DemoController 的 #echo()
方法,設置返回值爲 "todo"
。
切換到瀏覽器再趕緊切換到 IDEA 中,以達到 IDEA 失去焦點的效果。我們在 IDEA 中可以看修改的類被重載的提示。如下圖所示:
使用瀏覽器,再次訪問 http://127.0.0.1:8080/demo/echo
接口,返回結果爲 "todo"
,成功!
3.2 結論
艿艿個人的喜好的話,使用 IDEA 熱部署爲主,通過快捷鍵來手動編譯。畢竟,我是一個“主動”的人,默默開一波車,哈哈哈。
當然,不是說自動編譯有什麼不好,只是每個人的選擇。具體的,胖友可以都試試,尋找一個自己喜歡的方式。
4. Jrebel
Jrebel 是比較有名的一款 Java 熱部署插件。
因爲 IDEA 自帶的 HotSwap 插件已經能夠滿足我們的熱部署的訴求,所以本文也不多嗶嗶啥了。真的感興趣的胖友,可以看看《IDEA JRebel 插件熱部署(史上最全)》文章。不過,必要性不大,嘿嘿。
666. 彩蛋
至此,我們已經完成了 Spring Boot 熱部署的入門。咳咳咳,相信胖友們通過使用熱部署,一定能提高開發效率,寫更多的代碼,出更多的 BUG,加更多的班。
沒毛病,奧利給,幹就完事了!
歡迎加入我的知識星球,一起探討架構,交流源碼。加入方式,長按下方二維碼噢:
已在知識星球更新源碼解析如下:
最近更新《芋道 SpringBoot 2.X 入門》系列,已經 20 餘篇,覆蓋了 MyBatis、Redis、MongoDB、ES、分庫分表、讀寫分離、SpringMVC、Webflux、權限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能測試等等內容。
提供近 3W 行代碼的 SpringBoot 示例,以及超 4W 行代碼的電商微服務項目。
獲取方式:點“在看”,關注公衆號並回復 666 領取,更多內容陸續奉上。