Different property variable for Local and prod Environment (Spring)

后端 未结 5 1054
梦如初夏
梦如初夏 2020-12-08 00:44

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

相关标签:
5条回答
  • 2020-12-08 01:24

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

    0 讨论(0)
  • 2020-12-08 01:27

    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")

    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.

    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.

    0 讨论(0)
  • 2020-12-08 01:30

    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.active to the desired value e.g. development or production.

    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 PropertySourcesPlaceholderConfigurer will make it easier the access those properties through @Value annotations. Note that this examples assumes one profile is active. It may need some extra care when multiple profiles are active.

    Java based configuration

    @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 PropertySourcesPlaceholderConfigurer to the application context.

    @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 @Profile per class approach is a bit drastic for selecting a PropertySourcesPlaceholderConfigurer. Annotating a @Bean declaration would be much simpler.

    @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...
        }
    }
    
    0 讨论(0)
  • 2020-12-08 01:40

    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.

    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 profile variable. The missing file will just be ignored.

    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.

    0 讨论(0)
  • 2020-12-08 01:43

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

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

    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.

    UPDATE:

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

    @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;
    }
    
    0 讨论(0)
提交回复
热议问题