Spring Dev Tools 热重载机制仅从已经构建的类文件中重新加载/重新启动项目;它不会编译/构建源文件。因此,在 docker 容器中,即使源文件发生更改,Java 类文件也不会更改。因此更改不会反映,新添加的 GET API 也不会发布。
当容器重新启动时,它会再次gradle bootRun
按照 Dockerfile 中的指定调用。这会将更改的 Java 文件构建到类文件中,并且将反映更改。
当我们在 IDE 中使用它时,IDE(默认情况下)会在源文件发生更改时构建源文件。所以 Spring hot reload 总是加载更新的类文件,但这不会在 IDE 之外发生,除非我们有一些机制来观察源代码的变化并构建它们,比如gradle build --continuous
这些是我现在的设置。
应用程序属性
# scan for trigger file from root
# trigger file should not be in classpath, or it will go to infinite build loop
spring.devtools.restart.additional-paths=.
spring.devtools.restart.trigger-file=reload-trigger.txt
Dockerfile
FROM gradle:6.7-jdk11
WORKDIR /app
COPY . /app
EXPOSE 8000
# fetch dependencies
RUN chmod +x start.sh && gradle getDeps
# script which watches source file changes in background and executes bootRun
CMD ["sh", "start.sh"]
启动.sh
这个文件应该在根目录下,因为 Dockerfile 不应该在类路径中
# buildAndReload task, running in background, watches for source changes
(sleep 60; gradle buildAndReload --continuous -PskipDownload=true -x Test)&
gradle bootRun -PskipDownload=true
构建.gradle
# -----other codes above----- #
task buildAndReload {
dependsOn build
mustRunAfter build // buildAndReload must run after the source files are built into class files using build task
doLast {
new File(".", "reload-trigger.txt").text = "${System.currentTimeMillis()}" // update trigger file in root folder for hot reload
}
}
使用这些设置,只要更改了某些源文件,就会buildAndReload
执行任务。由于此任务取决于build
任务,因此更新的源代码在此之前已内置到类文件中。这个自定义任务,然后更新触发器文件,Spring 加载更新的类文件并重新启动应用程序。