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

时间:2017-05-03 08:51:19

标签: java spring spring-boot

我目前正在学习如何使用Spring Boot。到目前为止,我从未使用像Spring这样的Frameworks并直接使用文件(FileInputStream等)

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

以下是一些代码,用于说明我正在搜索的内容:

@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();
    }
}

当然,这个例子很简单。在这里,我想得到价值"令牌"从YAML配置文件动态生成。该文件必须可供用户访问,且不包含在JAR文件中。

我还发现了doc:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html但我现在已经知道如何将它应用到我的项目中。

我怎么能做到这一点?提前谢谢你:)

修改

以下是我的代码的一些部分:

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 (位于默认包中)

<?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 (位于src / main / resources中)

watchdog:
  token: fghaepoghaporghaerg

2 个答案:

答案 0 :(得分:5)

首先,您的Test类应使用@Component进行注释,以便在春季之前将其注册为bean(同时确保所有类都在主包下 - 主包是用@SpringBootApplication注释的类所在的位置。

现在您应该将所有属性移动到application.ymlsrc/main/resources/application.yml),这是由春季启动自动选取的(请注意它应该是.yml而不是.yaml或注册自定义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;
}

现在您的属性应该加载到spring的环境中,并且它们可以通过@Value注入到您的bean中。

答案 1 :(得分:3)

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

  1. 使用application.properties弹簧内部配置文件。
  2. 使用--spring.config.name作为VM参数加载您自己的配置文件。
  3. 您可以使用@PropertySource加载内部或外部配置。 @PropertySource仅适用于.properties配置文件。目前有一个开放的Jira票证来实现yaml支持。您可以点击此处的进度:https://jira.spring.io/browse/SPR-13912
  4. 注意,如果您使用包含公共密钥的多个yaml和/或属性文件,它将始终使用最后加载的密钥的定义。这就是下面的示例使用两个不同的键的原因。如果它使用相同的密钥,那么它将打印出PROPERTIES FILE两次。

    简短的简单代码段:

    @Component
    @PropertySource("file:/path/to/config/app.properties")
    class Address{
    
        @Value("${addr.street}")
        private String street;
    
        @Value("${addr.city}")
        private String city;
    }
    

    <强> app.properties

    addr.street=Abbey Road
    addr.city=London
    

    广泛示例

    <强> DemoApplication.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

    @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

    @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);
        }
    }
    

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

    watchdog.yml:

    watchdog:
      token: YAML FILE
    

    watchdog.properties:

    watchdog.prop.token=PROPERTIES FILE
    

    <强>输出

    PROPERTIES FILE
    YAML FILE