本地和生产环境(Spring)的不同属性变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22757318/
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-09-08 06:38:31  来源:igfitidea点击:

Different property variable for Local and prod Environment (Spring)

springspring-mvc

提问by Tushar

I am working on an Spring web application in where I need to have variable's that will have different value in local environment and other value in production environment.

我正在开发一个 Spring Web 应用程序,其中我需要在本地环境中具有不同值的变量和在生产环境中具有其他值的变量。

For Eg (file upload directory). My file upload directory is different for local and prod environment.

例如(文件上传目录)。我的文件上传目录对于本地和生产环境是不同的。

Currently I am doing it by checking the host name (if 'localhost' then A else B) and taking this approach. By there is another way to solve this problem via property files, Does anybody provide me pointers to how to approach that?

目前我通过检查主机名(如果是'localhost'然后是A else B)并采用这种方法来做到这一点。还有另一种方法可以通过属性文件解决这个问题,有人向我提供如何解决这个问题的指针吗?

采纳答案by Bart

You can load properties based on the current spring profile or profiles. To set a spring profile I mostly set a system property named spring.profiles.activeto the desired value e.g. developmentor production.

您可以根据当前的一个或多个弹簧轮廓加载属性。要设置弹簧配置文件,我主要将系统属性设置为spring.profiles.active所需的值,例如developmentproduction

The concept is pretty simple. Read the currently active profile from the system property. Build the filename and load the properties file using a PropertySourcesPlaceholderConfigurer. Using the PropertySourcesPlaceholderConfigurerwill make it easier the access those properties through @Valueannotations. Note that this examples assumes one profile is active. It may need some extra care when multiple profiles are active.

这个概念很简单。从系统属性中读取当前活动的配置文件。构建文件名并使用PropertySourcesPlaceholderConfigurer. 使用PropertySourcesPlaceholderConfigurer将使通过@Value注释访问这些属性变得更容易。请注意,此示例假定一个配置文件处于活动状态。当多个配置文件处于活动状态时,可能需要格外小心。

Java based configuration

基于Java的配置

@Configuration
public class MyApplicationConfiguration {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        String activeProfile = System.getProperty("spring.profiles.active", "production");
        String propertiesFilename = "app-" + activeProfile + ".properties";

        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setLocation(new ClassPathResource(propertiesFilename));

        return configurer;
    }
}

You could also import multiple configuration classes annotated with @Profile. Spring would select which configuration to use based on the currently active profiles. Every class could add it's own version of PropertySourcesPlaceholderConfigurerto the application context.

您还可以导入多个用@Profile. Spring 将根据当前活动的配置文件选择要使用的配置。每个类都可以将其自己的版本添加PropertySourcesPlaceholderConfigurer到应用程序上下文中。

@Configuration
@Import({Development.class, Production.class})
public class MyApplicationConfiguration {}

@Configuration
@Profile("development")
public class Development {}

@Configuration
@Profile // The default
public class Production {}


As Emerson Farrugia stated in his comment the @Profileper class approach is a bit drastic for selecting a PropertySourcesPlaceholderConfigurer. Annotating a @Beandeclaration would be much simpler.

正如 Emerson Farrugia 在他的评论中所说的,@Profile每班方法对于选择PropertySourcesPlaceholderConfigurer. 注释@Bean声明会简单得多。

@Configuration
public class MyApplicationConfiguration {

    @Bean
    @Profile("development")
    public static PropertySourcesPlaceholderConfigurer developmentPropertyPlaceholderConfigurer() {
        // instantiate and return configurer...
    }

    @Bean
    @Profile // The default
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        // instantiate and return configurer...
    }
}

回答by geoand

One solution that does not involve Spring Profiles at all is to use something like the following:

一种完全不涉及 Spring Profiles 的解决方案是使用如下内容:

<context:property-placeholder location="classpath*:config.properties,file:/path/config/config.properties"
                              ignore-unresolvable="false" ignore-resource-not-found="true"/>

What this does is tell Spring to look for properties using two files, the file in your jar/war, and one that can be anywhere in the file system. The ignore-resource-not-found means that if one of the files is not found, Spring won't complain.

这样做是告诉 Spring 使用两个文件查找属性,一个是 jar/war 中的文件,另一个是可以位于文件系统中任何位置的文件。ignore-resource-not-found 意味着如果找不到文件之一,Spring 不会抱怨。

Using this setup the second file can be controlled by DevOps people and can contain anything of their choosing, thus overriding any properties in your classpath properties file file.

使用此设置,第二个文件可由 DevOps 人员控制,并且可以包含他们选择的任何内容,从而覆盖类路径属性文件文件中的任何属性。

UPDATE:

更新:

You could do the same with Java Config using the following bean in your configuration class

您可以在配置类中使用以下 bean 对 Java Config 执行相同的操作

@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
    final PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();

    Resource[] resources = new Resource[ ] {
            new ClassPathResource( "config.properties" ),
            new FileSystemResource("/path/config/config.properties")
    };

    pspc.setLocations( resources );
    pspc.setIgnoreResourceNotFound(true);
    pspc.setIgnoreUnresolvablePlaceholders(false);
    return pspc;
}

回答by namero999

I've been banging my head half a day on this, and the solution I've ended up with is a combination of the other answers here.

我已经在这个问题上敲了半天,我最终得到的解决方案是这里的其他答案的组合。

Bart's solution had for me the drawback of using a dynamic prop file, so that my IDE "forgot" everything about it and couldn't suggest me which properties were used and where. Geoand solution had for me the drawback that the config file "should be in place somewhere". I can see why this is convenient in certain scenarios, but I tend to prefer one single artifact deployable in any environment, so I don't have to "park" files in strategic places for the app to pick up.

Bart 的解决方案对我来说有使用动态道具文件的缺点,因此我的 IDE“忘记”了关于它的所有内容,并且无法建议我使用了哪些属性以及在哪里使用。Geoand 解决方案对我来说有一个缺点,即配置文件“应该在某个地方”。我可以理解为什么这在某些情况下很方便,但我倾向于在任何环境中部署一个单一的工件,所以我不必将文件“停放”在应用程序的战略位置以供选择。

The solution for me therefore is:

因此,我的解决方案是:

- config.properties (default properties, usually local development env)
- config.staging.properties (overrides depending on the env)
- config.prod.properties (overrides depending on the env)

<context:property-placeholder ignore-resource-not-found="true"
                              location="config.properties,
                                        config-${profile}.properties"/>

The magic is the ignore-resource-not-found="true"that allows me to fire my local development env without setting any special profilevariable. The missing file will just be ignored.

神奇的是,ignore-resource-not-found="true"它允许我在不设置任何特殊profile变量的情况下触发我的本地开发环境。丢失的文件将被忽略。

Instead, I set that variable in my various deployment environment, e.g. -Dprofile=staging, and then the file will be found and the overrides applied.

相反,我在各种部署环境中设置了该变量,例如-Dprofile=staging,然后将找到该文件并应用覆盖。

回答by iam.vikas

In my case above any solutions didn't work so I did some google from my end and finally found some working solution for it.

在我上面的情况下,任何解决方案都不起作用,所以我从我的最后做了一些谷歌,最后找到了一些可行的解决方案。

I've modified the above class as follows:

我修改了上面的类如下:

@Configuration
@PropertySource("classpath:application-${spring.profiles.active}.properties")
public class MyApplicationConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    return configurer;
}
}

Instead of defining dynamic file name inside the method. I am defining the file name as below which does the magic for me.

而不是在方法内部定义动态文件名。我正在定义文件名,如下所示,这对我来说很神奇。

@PropertySource("classpath:application-${spring.profiles.active}.properties")

@PropertySource("classpath:application-${spring.profiles.active}.properties")

at the top of the class. By following Bart's solution I was not getting any errors but I was getting all the properties to value null defined inside property files.

在班级的顶端。通过遵循 Bart 的解决方案,我没有收到任何错误,但我将所有属性都设置为在属性文件中定义的 null 值。

by using my approach spring is able to recognize properties defined in VM arguments and in environment variable both. Note: I am using a non-spring boot project.

通过使用我的方法,spring 能够识别在 VM 参数和环境变量中定义的属性。注意:我使用的是非弹簧引导项目。

回答by krmanish007

you can add -Dspring.profile.active=local in your spring boot application, when you start your server. It will pick application-local.properties

您可以在启动服务器时在 spring 启动应用程序中添加 -Dspring.profile.active=local 。它将选择 application-local.properties