SpringBoot 使用 devtools、aspectj、gradle 和 IntelliJ 重启应用程序

问题描述 投票:0回答:1

我刚刚发现 spring-devtools 在类文件更改时重新启动应用程序。

要触发重新启动,我像这样设置 IntelliJ:

    在“编译器”中激活“自动构建项目”
  • 在“保存操作”中激活“构建项目”
  • 在“高级设置”中激活“即使应用程序当前正在运行也允许自动制作”
  • 在“构建工具/Gradle”中激活“使用 Gradle 构建并运行”
每当我更改 .java 文件并按 Strg-S 进行保存时,该文件就会由 IntelliJ 编译,并且 Spring Boot 会在几秒钟内重新启动。 .class 文件被编译到 build/ 目录,而不是 IntelliJ 的默认 out/ 目录。由于 gradle,这是正确的。很好,它按预期工作。

属性文件

但它不适用于属性文件。我的 Spring Boot 应用程序中有一个 message.properties 文件和一个 ReloadableResourceBundleMessageSource 。我也希望重新加载该文件。

每当我更改 messages.properties 文件并保存它时,该文件都会被复制到 out/ 目录而不是 build/ 目录。在 build/ 目录中它无法被拾取。

devtools 重启机制不会拾取它(可以/可能使用 spring.devtools.restart.exclude 对这些文件禁用)

但它也没有被 ReloadableResourceBundleMessageSource 拾取,因为类路径是

-classpath [...]/build/classes/java/main:[...]/build/resources/main


如何告诉 IntelliJ 尊重资源文件的 gradle build 目录?

方面J

我们正在使用 AspectJ

compile-time-weaving

 (ctw)。但是IntelliJ自动编译机制并没有考虑到我们的gradleaspectj配置。所以有时候编译就是错误的。如果您有 @Transactional 或 @Async 注释,就会发生这种情况。这很烦人。

重新加载两次

如果编译需要更多时间,应用程序已经重新启动,并在检测到新更改后再次重新启动。这可以通过带有 devtools 的触发器文件来解决。但是您无法配置 IntelliJ 在编译后触摸触发文件。

如何解决这些问题?

spring-boot gradle intellij-idea aspectj spring-boot-devtools
1个回答
0
投票
我找到了一个很好的解决方案来解决这个问题,我想分享:

我们希望使用 devtools(不使用 jrebel)实现正确的编译和快速的重新加载时间。正确的编译包括方面j编译时编织(ctw),这是内部IntelliJ编译无法处理的事情。

所以自动编译对我们来说不是一个选择。我们使用的是

gradle Continuous build

向 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 会自动拾取进程资源中的所有文件。

添加和配置开发工具

添加到build.gradle

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 中的设置

    设置/编译器/
  • 禁用“自动构建项目”
  • 设置/高级设置/
  • 禁用“允许自动制作”
  • 设置/Gradle/使用“IntelliJ”运行测试
  • 运行/调试配置/编辑配置模板/Junit/运行前不要构建
因此我们禁用所有自动构建(无论如何这是 IntelliJ 中的默认设置)。但请检查此选项,否则 gradle 和 IntelliJ 会同时构建。

Spring Boot 运行配置

编辑 Spring Boot 运行配置并转到“修改选项”并激活“运行前不要构建”。由于构建是通过连续的 gradle 完成的,因此在这里禁用它很重要。

Gradle“运行配置”

我们在 IntelliJ 中添加 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 中开始持续构建。

复合运行配置

添加复合运行配置,添加 gradle 和 spring-boot 运行配置,将其命名为“build-and-run”

打开 IntelliJ,启动“构建并运行”,所有内容都会自动编译和重新加载。

通过此设置,我们节省了大量时间。

© www.soinside.com 2019 - 2024. All rights reserved.