我刚刚发现 spring-devtools 在类文件更改时重新启动应用程序。
要触发重新启动,我像这样设置 IntelliJ:
属性文件
每当我更改 messages.properties 文件并保存它时,该文件都会被复制到 out/ 目录而不是 build/ 目录。在 build/ 目录中它无法被拾取。
devtools 重启机制不会拾取它(可以/可能使用 spring.devtools.restart.exclude 对这些文件禁用)
但它也没有被 ReloadableResourceBundleMessageSource 拾取,因为类路径是
-classpath [...]/build/classes/java/main:[...]/build/resources/main
方面J
compile-time-weaving
(ctw)。但是IntelliJ自动编译机制并没有考虑到我们的gradleaspectj配置。所以有时候编译就是错误的。如果您有 @Transactional 或 @Async 注释,就会发生这种情况。这很烦人。重新加载两次
如何解决这些问题?
我们希望使用 devtools(不使用 jrebel)实现正确的编译和快速的重新加载时间。正确的编译包括方面j编译时编织(ctw),这是内部IntelliJ编译无法处理的事情。
所以自动编译对我们来说不是一个选择。我们使用的是 向 build.gradle 添加连续任务
import java.time.Instant
tasks.register('compileTrigger') {
dependsOn tasks.compileJava
onlyIf {
!compileJava.state.upToDate
}
doLast {
def file = new File(projectDir, "build/classes/java/main/.reloadTrigger");
file.createNewFile();
file.setLastModified(Instant.now().toEpochMilli())
}
}
tasks.register('continuous-build') {
getProject()
.getRootProject()
.getSubprojects()
.findAll { (it.name != project.name) }
.forEach {
it.tasks.configureEach {
enabled = false
}
}
dependsOn tasks.processResources, tasks.compileTrigger, tasks.processTestResources, tasks.compileTestJava
}
我们决定使用触发器文件,因为否则如果完成更多工作,应用程序将提前重新启动。我们决定排除所有其他模块,因为这些模块有自己的重新加载机制(npm、vue、vite 等)。您的里程可能会有所不同。
我们仅在
compileJava
运行时添加触发器文件。如果配置正确,Spring boot 会自动拾取进程资源中的所有文件。添加和配置开发工具
dependencies {
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
添加到application-development.properties:
spring.devtools.restart.trigger-file=.reloadTrigger
spring.devtools.restart.poll-interval=400ms
spring.devtools.restart.quiet-period=1ms
不需要
poll-interval
和
quiet-period
,但它们可以节省一些时间(1秒)。如果 devtools 使用文件观察器而不是轮询算法,那就太好了。IntelliJ 中的设置
Spring Boot 运行配置
Gradle“运行配置”
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="continous-build" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="--continuous" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="continuous-build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
现在我们可以在 IntelliJ 中开始持续构建。复合运行配置
打开 IntelliJ,启动“构建并运行”,所有内容都会自动编译和重新加载。
通过此设置,我们节省了大量时间。