如何以编程方式访问Spring Boot应用程序的名称?

54

我在我的Spring Boot应用程序中使用bootstrap.yml文件定义了一个应用程序名称。

spring:
  application:
    name: abc

在运行时/以编程的方式,我如何获取此应用程序名称?

6个回答

62
你应该能够使用@Value注解来访问你在properties/YAML文件中设置的任何属性:

您应该能够使用@Value注释来访问您在属性/YAML文件中设置的任何属性:

@Value("${spring.application.name}")
private String appName;

3
这适用于application.yml/application.properties,但不适用于bootstrap.yml。是否需要配置任何东西?某些注释,某个地方? - Mubin
您可以覆盖 spring.config.name 为 "bootstrap"(默认为 "application"),或者通过使用 spring.config.location 明确指定不同的配置来进一步进行设置。 - Ophir Radnitz
值注解不再推荐使用。 - loesak
1
这完全没有回答问题。OP明确指出了“bootstrap.yaml”,而这并没有解决这个问题。 - Eugene
好的,但是如果您不显式设置属性,为什么值会为空? - Paolo Biavati

24
@Autowired
private ApplicationContext applicationContext;    
...
this.applicationContext.getId();

请找到这个:

# IDENTITY (ContextIdApplicationContextInitializer)
spring.application.name=
spring.application.index=

在Spring Boot中,参考手册请见Reference Manual

随后附上ContextIdApplicationContextInitializer类的源代码:

@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
    applicationContext.setId(getApplicationId(applicationContext.getEnvironment()));
}

默认情况下是这样的:

/**
 * Placeholder pattern to resolve for application name
 */
private static final String NAME_PATTERN = "${vcap.application.name:${spring.application.name:${spring.config.name:application}}}";

问题要求提供应用程序名称,而不是应用程序ID。 - chrylis -cautiouslyoptimistic-
2
应用程序ID是应用程序名称。对于我来说,getApplicationName()不返回任何内容,而getApplicationId()返回应用程序的名称,该名称使用spring.application.name属性设置。 - Jan Bodnar
getId() returns a combination of the value of spring.application.name and spring.application.index. if no index value is set, it is defaulted. in my case calling getId() returns my-application-1 when the value of spring.application.name is my-application - loesak

6

在Spring Boot中,当引用配置属性时,不建议使用@Value注解,并且因为applicationContext.getId();不总是返回spring.application.name的值,所以另一种方法是直接从Environment获取该值。

private final Environment environment;

...

public MyBean(final Environment environment) {
    this.environment = environment;
}

...

private getApplicationName() {
    return this.environment.get("spring.application.name");
}

另一种可能的方法是创建您自己的ConfigurationProperties类以访问该值。
我并不是说这些是最好的方法,我希望/希望有更好的方法,但这是一种方法。

你是否有权威的来源证明@Value注解是不被鼓励的?Spring Boot文档似乎并不支持这一点:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config - dschulten
1
我发现这个:"使用@Value("${property}") 注释来注入配置属性有时可能会很麻烦,特别是如果您正在处理多个属性或您的数据具有分层结构",以及关于 '@Value' 和 '@ConfigurationProperties' 之间差异的讨论 https://docs.spring.io/spring-boot/docs/2.4.x/reference/htmlsingle/#boot-features-external-config-typesafe-configuration-properties。 - dschulten
我没有权威的来源。我确实在Spring自己的文档中读到过这一点,但也许那已经改变了。这个想法是,当使用Spring Boot时,配置最好来自于配置属性的使用,这样应用程序可以验证配置,并在启动时失败,如果任何验证失败。 - loesak
我在现实世界中看到的问题是开发人员会使用@Value注解直接按名称访问属性。如果该属性未设置或类型不符合预期,则应用程序在执行运行时操作时可能会失败。这还会使查找此类配置的使用方式更加困难。 - loesak
1
我发现将所有配置定义在配置类中并从注入的bean中访问属性要安全得多。直接从类中访问并不总是显而易见,例如需要注释的情况。在这些情况下,因为它是SPEL,您可以使用SPEL语法#{myConfigProps.myConfig}从bean中访问配置属性。 - loesak
@loesak所做的方式是我在其他库中看到的Spring开发者的方式。这个结果似乎应该排名更高。 - Rick Hanton

2
注意!如果您使用SpringBootTest,需要提供属性/ yml。 否则,环境/ appcontext不会加载配置文件。 然后,您的应用程序名称未设置。 像这样:
@PropertySource("classpath:application.properties")
@RunWith(SpringRunner.class)
@SpringBootTest
....

1

这篇文章有些年头了,但我讨厌未回答的问题。因此,请使用以下代码片段:

@Value("${spring.application.name [: defaultValue]}") 
private String appName;

方括号内的内容是可选的。


0

我找到了一种非常丑陋的方法来解决这个问题,但它有效,所以我不再继续搜索。也许这会帮助到某些人。

基本原理是Spring Environment将值存储在propertySource中。似乎引导配置存储在ResourcePropertySource中,因此您可以从中获取它。对于我来说,它目前正在抛出异常,但然后我可以从异常中获取值,所以我没有进一步查看:

    try {
        this.environment.getProperty("name", ResourcePropertySource.class);
    } catch (ConversionFailedException e) {
        String res = (String)e.getValue();
    }

然后你可以对每个你感兴趣的属性都这样做。

就像我说的那样,虽然不太美观,但它能正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接