java 如何使用 Spring Boot 加载外部配置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43755380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 07:41:57  来源:igfitidea点击:

How to load an external configuration with Spring Boot?

javaspringspring-boot

提问by Morph

I'm currently learning how to work with Spring Boot. Until now I never used Frameworks like Spring and used files directly (FileInputStream, etc.)

我目前正在学习如何使用 Spring Boot。到目前为止,我从未使用过 Spring 之类的框架,而是直接使用文件(FileInputStream 等)

So here is the case: I have some dynamic configuration values like OAuth tokens. I want to use them inside of my application but I have no clue how to realize this with Spring.

所以情况是这样的:我有一些动态配置值,比如 OAuth 令牌。我想在我的应用程序中使用它们,但我不知道如何用 Spring 实现这一点。

Here is some code to make clear what I'm searching for:

下面是一些代码来明确我在搜索什么:

@Config("app.yaml")
public class Test {
    @Value("app.token")
    private String token;
    private IClient client;

    public Test(String token) {
        this.client = ClientFactory.build(token).login();
    }
}

Sure, this example is very plain. Here I want to get the value "token" dynamically from a YAML configuration file. This file must be accessible for the user and not included in the JAR file.

当然,这个例子很简单。在这里,我想从 YAML 配置文件中动态获取值“令牌”。该文件必须可供用户访问,并且不包含在 JAR 文件中。

I also found that doc: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.htmlbut I have now idea how to apply this to my project.

我还发现了该文档:https: //docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html但我现在知道如何将其应用于我的项目。

How can I achive this? Thank you in advance :)

我怎样才能做到这一点?先感谢您 :)

Edit:

编辑:

Here are some parts of my code:

这是我的代码的一些部分:

WatchdogBootstrap.java

看门狗引导程序

package de.onkelmorph.watchdog;

import org.springframework.boot.Banner.Mode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@ImportResource("classpath:Beans.xml")
public class WatchdogBootstrap {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(WatchdogBeans.class);
        app.setBannerMode(Mode.OFF);
        app.setWebEnvironment(false);
        app.run(args);
    }
}

Beans.xml(Located in default package)

Beans.xml(位于默认包中)

<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config></context:annotation-config>
</beans>

Watchdog.java

看门狗

package de.onkelmorph.watchdog;

// Imports ...

@Component
@PropertySource("file:/watchdog.yml")
public class Watchdog {
    // ...

    // Configuration
    @Value("${watchdog.token}")
    private String token;

    public Watchdog() {
        System.out.println(this.token);
        System.exit(0);
    }

    // ...
}

watchdog.yml(Located in src/main/resources)

watchdog.yml(位于 src/main/resources)

watchdog:
  token: fghaepoghaporghaerg

采纳答案by Tom

First of all your Testclass should be annotated with @Componentin order for it to be registered as a bean by spring (also make sure all your classes are under your main package - the main package is where a class that is annotated with @SpringBootApplicationreside).

首先,您的Test类应该被注释,@Component以便它在 spring 之前注册为 bean(还要确保您的所有类都在您的主包下 - 主包是带有注释的类@SpringBootApplication所在的位置)。

Now you should either move all your properties to application.yml(src/main/resources/application.yml), that is picked automatically by spring boot (note that it should be .ymlinstead of .yamlor register a custom PropertySourcesPlaceholderConfigurer.

现在,您应该将所有属性移动到application.yml( src/main/resources/application.yml),即由 spring boot 自动选择(请注意,它应该.yml代替.yaml或注册自定义PropertySourcesPlaceholderConfigurer.

Example for PropertySourcesPlaceholderConfigurer:

示例PropertySourcesPlaceholderConfigurer

@Bean
public static PropertySourcesPlaceholderConfigurer PropertySourcesPlaceholderConfigurer() throws IOException {
    PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    MutablePropertySources propertySources = new MutablePropertySources();
    Resource resource = new DefaultResourceLoader().getResource("classpath:application.yml");
    YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
    PropertySource<?> yamlProperties = sourceLoader.load("yamlProperties", resource, null);
    propertySources.addFirst(yamlProperties);
    configurer.setPropertySources(propertySources);
    return configurer;
}

Now your properties should be loaded to spring's environment and they will be available for injection with @Valueto your beans.

现在你的属性应该被加载到 spring 的环境中,它们将可用于注入@Value到你的 bean 中。

回答by kkflf

You basically got three easy options.

你基本上有三个简单的选择。

  1. Use application.propertieswhich is Springs internal configuration file.
  2. Load your own configuration file using --spring.config.nameas VM parameter.
  3. You can use @PropertySourceto load either an internal or external configuration. @PropertySourceonly works with .properties config files. There is currently an open Jira ticket to implement yaml support. You can follow the progress here: https://jira.spring.io/browse/SPR-13912
  1. 使用application.properties哪个是 Springs 的内部配置文件。
  2. 使用--spring.config.name作为 VM 参数加载您自己的配置文件。
  3. 您可以使用@PropertySource加载内部或外部配置。@PropertySource仅适用于 .properties 配置文件。目前有一个开放的 Jira 票来实现 yaml 支持。您可以在此处跟踪进度:https: //jira.spring.io/browse/SPR-13912

Notice, if you are using multiple yaml and/or properties files which contain common keys, the it will always use the definition of the key which was loaded last. This is why the below example uses two different keys. If it used the same key, then it would print out PROPERTIES FILEtwice.

请注意,如果您使用包含公共密钥的多个 yaml 和/或属性文件,它将始终使用最后加载的密钥的定义。这就是为什么下面的例子使用两个不同的键。如果它使用相同的密钥,那么它会打印PROPERTIES FILE两次。

Short simple code snippet:

简短的代码片段:

@Component
@PropertySource("file:/path/to/config/app.properties")
class Address{

    @Value("${addr.street}")
    private String street;

    @Value("${addr.city}")
    private String city;
}

app.properties

app.properties

addr.street=Abbey Road
addr.city=London

Extensive Example

广泛的例子

DemoApplication.java

演示应用程序.java

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(DemoApplication.class, args);

        //Call class with properties
        context.getBean(WatchdogProperties.class).test();
        //Call class with yaml
        context.getBean(WatchdogYaml.class).test();
    }

    //Define configuration file for yaml
    @Bean
    public static PropertySourcesPlaceholderConfigurer properties() {
      PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
      YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
      yaml.setResources(new ClassPathResource("watchdog.yml"));
      propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
      return propertySourcesPlaceholderConfigurer;
    }
}

WatchdogProperties.java

看门狗属性.java

@Component
//PropertySource only works for .properties files
@PropertySource("classpath:watchdog.properties")
public class WatchdogProperties{
    //Notice the key name is not the same as the yaml key
    @Value("${watchdog.prop.token}")
    private String token;

    public void test(){
        System.out.println(token);
    }
}

WatchdogYaml.java

WatchdogYaml.java

@Component
class WatchdogYaml{
    //Notice the key name is not the same as the properties key
    @Value("${watchdog.token}")
    private String token;

    public void test(){
        System.out.println(token);
    }
}

Properties and Yaml filesBoth of these files are located in src/main/resources

属性和 Yaml 文件这两个文件都位于src/main/resources

watchdog.yml:

看门狗.yml:

watchdog:
  token: YAML FILE

watchdog.properties:

watchdog.properties:

watchdog.prop.token=PROPERTIES FILE

Output

输出

PROPERTIES FILE
YAML FILE