2017-08-16 123 views
0

我使用SpringBoot应用程序,该应用程序必须在不同的环境下运行。属性文件是创建的,一旦我修改了环境,默认值就被适当的值覆盖。没关系。Spring Boot覆盖来自用户特定文件的属性

在下一步我想检查登录用户System.getProperty("user.name")是否有一个自定义属性文件。如果是这样,这些属性必须用他的属性重写。所以步骤应该是(假设当前情景模式为开发):

  1. 负载的application.properties
  2. 负载和application-dev.properties覆盖性能
  3. 如果用户有一个自定义属性文件(user.properties),加载并覆盖属性

我读了很多topcis,发现了两种可能的解决方案,但都没有成功。

  1. 将注释@PropertySource("user.properties")添加到配置类,该类应加载用户特定的属性文件并覆盖值。出于测试目的,我将server.port=1234添加到user.properties,但是这被忽略了。
  2. 创建一个自定义PropertyPlaceholderConfigurer。尽管此bean已成功创建,但服务器端口未更改。

`

@Bean 
public PropertyPlaceholderConfigurer propertyPlaceholder() { 
    PropertyPlaceholderConfigurer propertyPlaceholder = new PropertyPlaceholderConfigurer(); 
    propertyPlaceholder.setLocations(
      new ClassPathResource("application.properties"), 
      new ClassPathResource("application-dev.properties"), 
      new ClassPathResource("user.properties")); 

    propertyPlaceholder.setIgnoreResourceNotFound(true); 
    propertyPlaceholder.setIgnoreUnresolvablePlaceholders(true); 
    return propertyPlaceholder; 
} 

我不知道如何前进。所以任何想法都非常受欢迎。

更新:我已经justed推演示代码到GitHub。也许有助于找到解决方案:https://github.com/aszidien/springboot

+0

'System.getProperty(“user.name”)''不会查找当前登录的用户,这将查找'user.name'键当前激活的配置文件。因此请首先清除您的问题。 – TheCurious

+0

至于我的理解你在找什么,说约翰目前登录的用户,所以你想'john.properties'覆盖'application-profile.property'中的键'if john.properties' exists?这是你的要求吗? – TheCurious

+0

抱歉误会,你的推测是正确的。这是要求。 – aszidien

回答

0

在Spring Boot中正确定制环境的方法是使用EnvironmentPostProcessor,它将在ApplicationContext启动时很早运行并允许您管理属性源。

步骤1.具有以下创建文件src/main/resources/META-INF/spring.factories

org.springframework.boot.env.EnvironmentPostProcessor=\ 
com.example.YourEnvironmentPostProcessor 

步骤2.作为示例创建一个文件src/main/resources/custom.properties用:

server.port=8081 

步骤3.现在创建你的后期处理器类

package com.example; 

public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor { 

    private final PropertiesPropertySourceLoader loader = new PropertiesPropertySourceLoader(); 

    @Override 
    public void postProcessEnvironment(ConfigurableEnvironment environment, 
            SpringApplication application) { 
    Resource path = new ClassPathResource("custom.properties"); 
    // ^^^ here you can create the resource however you want 
    // construct the name from a user name, use FileSystemResource, anything 
    // for example you can ask users to place a file in their home 
    // directory named "my-application.properties" and load it like so 

    // Resource path = new FileSystemResource(Paths.get(System.getProperty("user.home"),"my-application.properties").toString()); 

    PropertySource<?> propertySource = loadProps(path); 
    environment.getPropertySources().addFirst(propertySource); 
    } 

    private PropertySource<?> loadProps(Resource path) { 
    if (!path.exists()) { 
     throw new IllegalArgumentException("Resource " + path + " does not exist"); 
    } 
    try { 
     return this.loader.load("custom-resource", path, null); 
    } 
    catch (IOException ex) { 
     throw new IllegalStateException(
      "Failed to load props configuration from " + path, ex); 
    } 
    } 

} 

现在,当您运行应用程序时,端口将更改为8081,其他任何属性都将覆盖主属性中提供的默认值。

+0

谢谢你的详细解答。我创建了spring.factories和CustomEnvironmentPostProcessor。我看到postProcessEnvironment方法被执行并加载了属性,但由于某种原因,server.port仍未被覆盖。我更新了[GitHub回购](https://github.com/aszidien/springboot)。你可以看看这个吗? – aszidien

+0

@aszidien但你命名了你的文件'user.properties',你不应该把它命名为'your-actual-username.properties'吗?由于您使用'user.name'系统prop来构建文件名? – Strelok

+0

我在本地修改了'user.properties'到'my-current-username.properties'。如果我调试'postProcessEnvironment',我可以看到值为'6789'的关键'server.port'。所以这部分代码似乎工作正常。我认为'server.port'不能用这种方法重写。不知何故,我应该将此属性添加到'applicationConfigurationProperties - environment.getPropertySources()。get(“applicationConfigurationProperties”)',而不是'custom-resource'。由于此列表包含Spring配置文件(默认和开发)。但我不知道如何去做。 – aszidien