Spring Boot 无法解析字符串中的占位符

Posted

技术标签:

【中文标题】Spring Boot 无法解析字符串中的占位符【英文标题】:Spring boot could not resolve placeholder in string 【发布时间】:2018-06-17 21:37:58 【问题描述】:

我正在使用 mvn clean install spring-boot:run 的 maven 在嵌入式 tomcat 服务器上运行 spring-boot。但是每次我运行它时都会出现这个错误:

 Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'language' in string value "$language"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:831) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1086) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 35 common frames omitted

该错误与这两行代码有关:

@Value("$language")
private String language;

该语言标志在我的 application.properties 中指定,如下所示:

application.properties

language=java
logging.level.org.springframework=TRACE

这是令人困惑的部分:当我在没有 spring-boot:run 命令的情况下运行构建时,它会正确构建,我可以毫无问题地运行构建的 jar一点也不。只有当我尝试在嵌入式 tomcat 服务器上运行时,我才会遇到这个问题。

我可以通过在我的代码中这样做来绕过这个:

@Value("$language:java")
private String language;

但这对我来说没有意义,因为 spring 应该自动从 application.properties 文件中读取默认值。

编辑:正如人们所指出的,当在嵌入式 tomcat 服务器上运行时,它根本不会读取 application.properties。有什么方法可以强制它读取文件或它可能不读取文件的原因?当部署到外部应用服务器而不是嵌入式应用服务器时,它工作正常。

提前感谢您的帮助。

【问题讨论】:

您确定您的嵌入式 tomcat 会看到属性文件并加载它吗? 是的 - 看起来它没有读取属性文件。但我不确定为什么。它可以在部署在外部 tomcat 服务器上或作为 java 应用程序运行时读取它,所以这让我感到困惑。 【参考方案1】:

在我的例子中,我设置了一个操作系统环境变量spring.config.location 用于其他目的。这覆盖了eclipse中spring配置的项目路径。

在eclipse中删除环境变量,重启并重新导入项目后,上述问题得到解决

【讨论】:

【参考方案2】:

在我的情况下改变这个:

@Value("$files.root")

到这里:

@Value("$files.root:default")

工作。

请参阅以下内容了解我的解决方案:https://www.bswen.com/2019/06/springboot-How-to-resolve-IllegalArgumentException-Could-not-resolve-placeholder-when-use-@Value-in-Spring-or-SpringBoot-app.html

【讨论】:

我不明白为什么会这样,但谢谢!【参考方案3】:

在 IntelliJ 上遇到了同样的问题。来自File -> Invalidate Caches / Restart ... 的无效缓存已为我修复。

【讨论】:

【参考方案4】:

如果您已正确设置值,请检查您的资源文件夹是否充当 IDE 识别的“资源”。在 IntelliJ 中,您可以右键单击资源并选择“标记为资源根”。

【讨论】:

【参考方案5】:

这里我有最简单的解决方案,适用于我的情况。

无论是来自 Java 命令提示符,还是来自 IDE(例如 eclipse 或 IntelliJ)的 VM 选项,请尝试提供以下内容:

-Dspring.profiles.active=<env>

这是修改/触摸上述 pom 文件的替代方法。

【讨论】:

【参考方案6】:

我和你有类似的问题,我已经解决了

在您的pom.xml 如果您有多个配置文件或属性,请选择 1 个配置文件作为默认选择

<profiles>
        <profile>
            <id>dev</id>
            <properties>
                <activatedProperties>dev</activatedProperties>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <activatedProperties>prod</activatedProperties>
            </properties>
        </profile>
    </profiles>

然后转到您的application.properties 然后插入此代码

spring.profiles.active=@activatedProperties@

【讨论】:

【参考方案7】:

我缺少以下依赖项

  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

我需要读取集中化配置服务器的配置值。

【讨论】:

就我而言,当我收到消息“无法解析占位符”时,它存在于配置服务中 - 添加此依赖项可以解决问题。我还添加了 -Dspring.cloud.bootstrap.enabled=true 来运行脚本。【参考方案8】:

从 IntelliJ 运行时,我也遇到了类似的问题。 这对我有用: 构建 -> 重建项目。

【讨论】:

【参考方案9】:

就我而言,在 IntelliJ 中,我使用了不同的配置文件。 因此,在我的案例中选择开发配置文件解决了一个问题。

【讨论】:

【参考方案10】:

你是不是偶然从 Eclipse 中运行了这个?

我遇到了同样的问题,并注意到该项目不具备 Maven 特性。右键单击项目 -> 配置 -> 转换为 Maven 项目。然后右键项目->Maven->更新项目解决了这个问题。

【讨论】:

【参考方案11】:

如果pom.xml 文件中的上述更改仍未解决问题,请尝试以下选项。

在类的顶部添加 @PropertySource 注释

@PropertySource(
    
            "classpath:/application.properties",
            "classpath:/$spring.profiles.active/application-$spring.profiles.active.properties"
    

)

如果仍然无法解决,请尝试添加以下注释

@EnableAutoConfiguration

萨拉姆

【讨论】:

请在你的答案中包含正确的推理 这不是修复补丁论坛。 Stack-overflow 为您提供了一个平台,可以让您详细了解正在发生的特定问题,然后找到解决方案。【参考方案12】:

通过将这些行添加到 &lt;resources&gt; 部分下的 pom 来修复

<resource>
     <directory>src/main/resources</directory>
     <filtering>true</filtering>
     <includes>
          <include>**/*.properties</include>
     </includes>
</resource>

我不完全理解的是这样做的必要性。

a) 我可以在外部应用服务器上运行它而无需添加此行,并且应用读取 application.properties 就好了。

b) 我可以在 Eclipse 中将应用程序作为独立的 java 应用程序运行(即,无需通过 maven 构建应用程序),它的显示为 application.properties 就好了

c) 无论如何,spring-boot 不应该默认读取它吗? (如上面两个案例所示?)

感谢大家的帮助。希望这会对其他人有所帮助。

【讨论】:

我猜你没有在 pom.xml 中继承 spring-boot-starter-parent 这就是原因。 无论出于何种原因**/* 对我不起作用,所以我很难为位于配置目录下的文件添加&lt;directory&gt;src/main/resources/config&lt;/directory&gt; 这是真的,但是为了在远程服务器上将其部署为 JAR 文件,我们需要从 JAR 文件中排除属性文件。因此,像这样包含它们,破坏了拥有属性文件的目的。你能对此发表评论吗?我在 build->resources->excludes TAG 下明确

以上是关于Spring Boot 无法解析字符串中的占位符的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot 无法解析占位符 application.yml

使用 Spring Boot 进行 Maven 资源过滤:无法解析占位符

如何为具有属性依赖项的 Spring Boot Application 类编写测试用例 - 无法解析占位符

如何使用 Spring Boot 应用程序中另一个属性文件中的值解析属性文件中的占位符

Spring Boot 配置属性的未解决占位符验证

从 Spring Boot 项目部署战争