Win10下VSCode Spring Boot扩展无法加载gradle.properties至application.properties
在Windows 10系统上使用VSCode的Spring Tool Suite,基于Gradle构建Spring Boot Java项目。执行gradle build或gradlew build时构建正常,gradle.properties中的配置能被注入到application.properties中;但通过Spring Boot扩展包运行项目时,bin目录下的application.properties未正确加载gradle.properties配置,启动报错,错误信息显示无法解析postgresqlHost等占位符。
报错日志
. ____ _ __ _ _ /\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.2.5) 2024-05-11T13:55:15.300+02:00 INFO 28648 --- [person] [ restartedMain] c.s.erp.person.api.PersonApplication : Starting PersonApplication using Java 21.0.3 with PID 28648 (D:\SoftwareSprouting-code\ERP\personApi\bin\main started by ezequ in D:\SoftwareSprouting-code\ERP\personApi) 2024-05-11T13:55:15.304+02:00 INFO 28648 --- [person] [ restartedMain] c.s.erp.person.api.PersonApplication : No active profile set, falling back to 1 default profile: "default" 2024-05-11T13:55:15.398+02:00 INFO 28648 --- [person] [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2024-05-11T13:55:15.399+02:00 INFO 28648 --- [person] [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2024-05-11T13:55:16.257+02:00 WARN 28648 --- [person] [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration]: Error processing condition on org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryConfigurations$PoolConfiguration 2024-05-11T13:55:16.270+02:00 INFO 28648 --- [person] [ restartedMain] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2024-05-11T13:55:16.313+02:00 ERROR 28648 --- [person] [ restartedMain] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration]: Error processing condition on org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryConfigurations$PoolConfiguration at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:544) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:321) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:246) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:534) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.lambda$processGroupImports$1(ConfigurationClassParser.java:746) ~[spring-context-6.1.6.jar:6.1.6] at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na] at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:743) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:714) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:183) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:416) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:289) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:788) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:606) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.5.jar:3.2.5] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.5.jar:3.2.5] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.5.jar:3.2.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.5.jar:3.2.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.5.jar:3.2.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.5.jar:3.2.5] at com.softwaresprouting.erp.person.api.PersonApplication.main(PersonApplication.java:10) ~[main/:na] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.2.5.jar:3.2.5] Caused by: java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryConfigurations$PoolConfiguration at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60) ~[spring-boot-autoconfigure-3.2.5.jar:3.2.5] at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:220) ~[spring-context-6.1.6.jar:6.1.6] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:534) ~[spring-context-6.1.6.jar:6.1.6] ... 24 common frames omitted Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'postgresqlHost' in value "r2dbc:postgresql://${postgresqlHost}:${postgresqlPort}/${postgresqlDatabase}" at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180) ~[spring-core-6.1.6.jar:6.1.6] at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) ~[spring-core-6.1.6.jar:6.1.6] at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239) ~[spring-core-6.1.6.jar:6.1.6] at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) ~[spring-core-6.1.6.jar:6.1.6] at org.springframework.core.env.AbstractPropertyResolver.resolveNestedPlaceholders(AbstractPropertyResolver.java:230) ~[spring-core-6.1.6.jar:6.1.6] at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:80) ~[spring-boot-3.2.5.jar:3.2.5] at org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.getProperty(ConfigurationPropertySourcesPropertyResolver.java:61) ~[spring-boot-3.2.5.jar:3.2.5] at org.springframework.core.env.AbstractEnvironment.getProperty(AbstractEnvironment.java:552) ~[spring-core-6.1.6.jar:6.1.6] at org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryConfigurations$PooledConnectionFactoryCondition.hasPoolUrl(ConnectionFactoryConfigurations.java:172) ~[spring-boot-autoconfigure-3.2.5.jar:3.2.5] at org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryConfigurations$PooledConnectionFactoryCondition.getMatchOutcome(ConnectionFactoryConfigurations.java:156) ~[spring-boot-autoconfigure-3.2.5.jar:3.2.5] at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-3.2.5.jar:3.2.5] ... 27 common frames omitted
相关配置文件
application.properties
spring.application.name=person spring.r2dbc.url=r2dbc:postgresql://${postgresqlHost}:${postgresqlPort}/${postgresqlDatabase} spring.r2dbc.username=${postgresqlUsername} spring.r2dbc.password=${postgresqlPassword}
gradle.properties
#postgresql postgresqlHost=127.0.0.1 postgresqlPort=5432 postgresqlDatabase=person postgresqlUsername=person postgresqlPassword=person123
build.gradle
plugins { id 'java' id 'org.springframework.boot' version '3.2.5' id 'io.spring.dependency-management' version '1.1.4' } group = 'com.softwaresprouting.erp' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '21' } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc' implementation 'org.springframework.boot:spring-boot-starter-hateoas' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' runtimeOnly 'org.postgresql:r2dbc-postgresql' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.projectreactor:reactor-test' testImplementation 'org.springframework.security:spring-security-test' } tasks.named('test') { useJUnitPlatform() } processResources { expand(project.properties) }
解决方案
原因分析
Spring Boot扩展包直接启动项目时,不会触发Gradle的processResources任务——这个任务负责将gradle.properties中的值替换到application.properties的占位符中。扩展包会直接读取编译后的bin目录文件,若未执行processResources,bin目录下的application.properties仍保留原始占位符,导致Spring无法解析。
方案1:启动前手动执行processResources任务
在VSCode终端运行以下命令,执行完成后再用Spring Boot扩展包启动项目:
gradlew processResources
方案2:让Spring Boot直接加载gradle.properties
修改application.properties,添加配置让Spring Boot启动时直接读取gradle.properties作为外部配置源:
spring.config.import=optional:gradle.properties
optional:表示如果文件不存在也不会报错,默认读取项目根目录下的gradle.properties。
方案3:配置VSCode扩展自动执行前置任务
修改VSCode的settings.json,添加以下配置,让Spring Boot扩展启动项目前自动执行processResources任务:
"spring-boot.ls.java.gradle.tasks": ["processResources"]
内容的提问来源于stack exchange,提问作者Software Sprouting

