Spring Boot et plusieurs fichiers de configuration externes

J’ai plusieurs fichiers de propriétés que je souhaite charger depuis classpath. Il y a un jeu par défaut sous /src/main/resources qui fait partie de myapp.jar . Mon springcontext s’attend à springcontext que les fichiers soient sur le classpath. c’est à dire

   

J’ai également besoin de l’option pour remplacer ces propriétés avec un ensemble externe. J’ai un dossier de configuration externe dans cwd . Selon le répertoire de démarrage du spring, le dossier de configuration du document doit être sur classpath. Mais ce n’est pas clair avec doc si elle ne remplacera que l’ applicaiton.properties de là ou de toutes les propriétés de config.

Lorsque je l’ai testé, seules les application.properties sont captées et le rest des propriétés sont toujours extraites de /src/main/resources . J’ai essayé de les fournir sous forme de liste séparée par des virgules à spring.config.location mais l’ensemble par défaut n’est toujours pas remplacé.

Comment puis-je faire en sorte que plusieurs fichiers de configuration externes remplacent ceux par défaut?

Comme solution de contournement, j’utilise actuellement app.config.location (propriété spécifique à l’application) que je fournis via la ligne de commande. c’est à dire

 java -jar myapp.jar app.config.location=file:./config 

et j’ai changé mon applicationcontext en

  

Et c’est comme ça que je fais la séparation entre fichier et classpath lors du chargement de l’application.
EDITS:

 //psuedo code if (SsortingngUtils.isBlank(app.config.location)) { System.setProperty(APP_CONFIG_LOCATION, "classpath:"); } 

Je voudrais vraiment ne pas utiliser la solution de contournement ci-dessus et faire en sorte que Spring remplace tous les fichiers de configuration externes du chemin de classe, comme c’est le cas pour le fichier application.properties .

Lors de l’utilisation de Spring Boot, les propriétés sont chargées dans l’ordre suivant (voir Configuration externalisée dans le guide de référence Spring Boot).

  1. Arguments de ligne de commande.
  2. Propriétés du système Java (System.getProperties ()).
  3. Variables d’environnement OS.
  4. Atsortingbuts JNDI de Java: comp / env
  5. Un RandomValuePropertySource qui n’a que des propriétés aléatoires. *.
  6. Propriétés d’application en dehors de votre fichier jar packagé (application.properties, y compris les variantes YAML et de profil).
  7. Propriétés d’application intégrées à votre fichier jar (application.properties, y compris YAML et variantes de profil).
  8. @PropertySource annotations sur vos classes @Configuration.
  9. Propriétés par défaut (spécifiées à l’aide de SpringApplication.setDefaultProperties).

Lors de la résolution des propriétés (c’est-à-dire que @Value("${myprop}") résolution est effectuée dans l’ordre inverse (donc à partir de 9).

Pour append des fichiers différents, vous pouvez utiliser les propriétés spring.config.location qui prennent une liste de fichiers de propriétés ou de fichiers (répertoires) séparés par des virgules.

 -Dspring.config.location=your/config/dir/ 

Celui ci-dessus appenda un répertoire qui sera consulté pour application.properties fichiers application.properties .

 -Dspring.config.location=classpath:job1.properties,classpath:job2.properties 

Cela appenda le fichier de propriétés 2 aux fichiers chargés.

Les fichiers et les emplacements de configuration par défaut sont chargés avant ceux de spring.config.location spécifiés de manière spring.config.location , ce qui signifie que ce dernier remplacera toujours les propriétés définies dans les spring.config.location précédentes. (Voir aussi cette section du Guide de référence de Spring Boot).

Si spring.config.location contient des répertoires (par opposition à des fichiers), ils devraient se terminer par / (et seront ajoutés aux noms générés à partir de spring.config.name avant d’être chargés). Le chemin de recherche par défaut classpath:,classpath:/config,file:,file:config/ spring.config.location classpath:,classpath:/config,file:,file:config/ est toujours utilisé, quelle que soit la valeur de spring.config.location . De cette manière, vous pouvez définir des valeurs par défaut pour votre application dans application.properties (ou tout autre nom de base choisi avec spring.config.name ) et la remplacer à l’exécution par un fichier différent, en conservant les valeurs par défaut.

Avec le démarrage Spring, spring.config.location fonctionne, il suffit de fournir des fichiers de propriétés séparés par des virgules.

voir le code ci-dessous

 @PropertySource(ignoreResourceNotFound=true,value="classpath:jdbc-${spring.profiles.active}.properties") public class DBConfig{ @Value("${jdbc.host}") private Ssortingng jdbcHostName; } } 

on peut mettre la version par défaut de jdbc.properties dans l’application. Les versions externes peuvent être définies ici.

 java -jar target/myapp.jar --spring.config.location=classpath:file:///C:/Apps/springtest/jdbc.properties,classpath:file:///C:/Apps/springtest/jdbc-dev.properties 

Selon la valeur de profil définie à l’aide de la propriété spring.profiles.active, la valeur de jdbc.host sera récupérée. Alors quand (sur les fenêtres)

 set spring.profiles.active=dev 

jdbc.host prendra la valeur de jdbc-dev.properties.

pour

 set spring.profiles.active=default 

jdbc.host prendra la valeur de jdbc.properties.

Jetez un oeil à la PropertyPlaceholderConfigurer, je trouve plus clair à utiliser que l’annotation.

par exemple

 @Configuration public class PropertiesConfiguration { @Bean public PropertyPlaceholderConfigurer properties() { final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); // ppc.setIgnoreUnresolvablePlaceholders(true); ppc.setIgnoreResourceNotFound(true); final List resourceLst = new ArrayList(); resourceLst.add(new ClassPathResource("myapp_base.properties")); resourceLst.add(new FileSystemResource("/etc/myapp/overriding.propertie")); resourceLst.add(new ClassPathResource("myapp_test.properties")); resourceLst.add(new ClassPathResource("myapp_developer_overrides.properties")); // for Developer debugging. ppc.setLocations(resourceLst.toArray(new Resource[]{})); return ppc; } 

J’ai juste eu un problème similaire à celui-ci et j’ai finalement compris la cause: le fichier application.properties avait le mauvais propriétaire et les atsortingbuts rwx. Ainsi, lorsque Tomcat a démarré, le fichier application.properties se trouvait au bon endroit, mais il appartenait à un autre utilisateur:

 $ chmod 766 application.properties $ chown tomcat application.properties 

J’ai eu le même problème. Je voulais avoir la possibilité de remplacer un fichier de configuration interne au démarrage par un fichier externe, similaire à la détection Spring Boot application.properties. Dans mon cas, c’est un fichier user.properties où sont stockés les utilisateurs de mes applications.

Mes exigences:

Chargez le fichier à partir des emplacements suivants (dans cet ordre)

  1. Le classpath
  2. Un sous répertoire / config du répertoire en cours.
  3. Le répertoire actuel
  4. Depuis un répertoire ou un emplacement de fichier donné par un paramètre de ligne de commande au démarrage

Je suis venu avec la solution suivante:

 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.PathResource; import org.springframework.core.io.Resource; import java.io.IOException; import java.util.Properties; import static java.util.Arrays.stream; @Configuration public class PropertiesConfig { private static final Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class); private final static Ssortingng PROPERTIES_FILENAME = "user.properties"; @Value("${properties.location:}") private Ssortingng propertiesLocation; @Bean Properties userProperties() throws IOException { final Resource[] possiblePropertiesResources = { new ClassPathResource(PROPERTIES_FILENAME), new PathResource("config/" + PROPERTIES_FILENAME), new PathResource(PROPERTIES_FILENAME), new PathResource(getCustomPath()) }; // Find the last existing properties location to emulate spring boot application.properties discovery final Resource propertiesResource = stream(possiblePropertiesResources) .filter(Resource::exists) .reduce((previous, current) -> current) .get(); final Properties userProperties = new Properties(); userProperties.load(propertiesResource.getInputStream()); LOG.info("Using {} as user resource", propertiesResource); return userProperties; } private Ssortingng getCustomPath() { return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + PROPERTIES_FILENAME; } } 

Maintenant, l’application utilise la ressource classpath, mais recherche également une ressource aux autres emplacements donnés. La dernière ressource qui existe sera choisie et utilisée. Je peux lancer mon application avec java -jar myapp.jar –properties.location = / directory / myproperties.properties pour utiliser un emplacement de propriétés qui fait flotter mon bateau.

Un détail important ici: Utilisez une chaîne vide comme valeur par défaut pour le fichier properties.location dans l’annotation @Value pour éviter les erreurs lorsque la propriété n’est pas définie.

La convention pour un properties.location est la suivante: Utilisez un répertoire ou un chemin d’access à un fichier de propriétés en tant que properties.location.

Si vous ne voulez remplacer que des propriétés spécifiques, un PropertiesFactoryBean avec setIgnoreResourceNotFound (true) peut être utilisé avec le tableau de ressources défini comme emplacements.

Je suis sûr que cette solution peut être étendue pour gérer plusieurs fichiers …

MODIFIER

Voici ma solution pour plusieurs fichiers 🙂 Comme avant, cela peut être combiné avec un PropertiesFactoryBean.

 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.PathResource; import org.springframework.core.io.Resource; import java.io.IOException; import java.util.Map; import java.util.Properties; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toMap; @Configuration class PropertiesConfig { private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class); private final static Ssortingng[] PROPERTIES_FILENAMES = {"job1.properties", "job2.properties", "job3.properties"}; @Value("${properties.location:}") private Ssortingng propertiesLocation; @Bean Map myProperties() { return stream(PROPERTIES_FILENAMES) .collect(toMap(filename -> filename, this::loadProperties)); } private Properties loadProperties(final Ssortingng filename) { final Resource[] possiblePropertiesResources = { new ClassPathResource(filename), new PathResource("config/" + filename), new PathResource(filename), new PathResource(getCustomPath(filename)) }; final Resource resource = stream(possiblePropertiesResources) .filter(Resource::exists) .reduce((previous, current) -> current) .get(); final Properties properties = new Properties(); try { properties.load(resource.getInputStream()); } catch(final IOException exception) { throw new RuntimeException(exception); } LOG.info("Using {} as user resource", resource); return properties; } private Ssortingng getCustomPath(final Ssortingng filename) { return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + filename; } } 

c’est une approche simple en utilisant une botte de spring

TestClass.java

 @Configuration @Profile("one") @PropertySource("file:/{selected location}/app.properties") public class TestClass { @Autowired Environment env; @Bean public boolean test() { System.out.println(env.getProperty("test.one")); return true; } } 

le contexte app.properties , dans votre emplacement sélectionné

 test.one = 1234 

votre application de démarrage au spring

 @SpringBootApplication public class TestApplication { public static void main(Ssortingng[] args) { SpringApplication.run(testApplication.class, args); } } 

et le contexte prédéfini application.properties

 spring.profiles.active = one 

vous pouvez écrire autant de classes de configuration que vous le souhaitez et les activer / désactiver simplement en définissant spring.profiles.active = le nom / nom du profil {séparés par des virgules}

comme vous pouvez le voir, le boot de spring est génial, il suffit juste de s’y familiariser, il est utile de mentionner que vous pouvez également utiliser @Value dans vos champs

 @Value("${test.one}") Ssortingng str; 

Spring Boot nous permet d’écrire des profils différents pour écrire dans différents environnements, par exemple, nous pouvons avoir des fichiers de propriétés séparés pour la production, les environnements Qa et locaux

Le fichier application-local.properties avec des configurations en fonction de ma machine locale est

 spring.profiles.active=local spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.database=users spring.data.mongodb.username=humble_freak spring.data.mongodb.password=freakone spring.rabbitmq.host=localhost spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.port=5672 rabbitmq.publish=true 

De même, nous pouvons écrire application-prod.properties et application-qa.properties autant de fichiers de propriétés que nous le voulons

puis écrivez des scripts pour lancer l’application pour différents environnements, par exemple

 mvn spring-boot:run -Drun.profiles=local mvn spring-boot:run -Drun.profiles=qa mvn spring-boot:run -Drun.profiles=prod 

J’ai trouvé que c’était un modèle utile à suivre:

 @RunWith(SpringRunner) @SpringBootTest(classes = [ TestConfiguration, MyApplication ], properties = [ "spring.config.name=application-MyTest_LowerImportance,application-MyTest_MostImportant" ,"debug=true", "trace=true" ] ) 

Ici, nous remplaçons l’utilisation de “application.yml” pour utiliser “application-MyTest_LowerImportance.yml” et aussi “application-MyTest_MostImportant.yml”
(Spring recherchera également les fichiers .properties)

Les parameters de débogage et de suivi, sur une ligne distincte, sont également inclus en tant que bonus supplémentaire pour que vous puissiez les commenter si nécessaire;]

Le debug / trace est incroyablement utile, car Spring videra les noms de tous les fichiers qu’il charge et ceux qu’il essaie de charger.
Vous verrez des lignes comme celle-ci dans la console à l’exécution:

 TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant.properties' (file:./config/application-MyTest_MostImportant.properties) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant.xml' (file:./config/application-MyTest_MostImportant.xml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant.yml' (file:./config/application-MyTest_MostImportant.yml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant.yaml' (file:./config/application-MyTest_MostImportant.yaml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_LowerImportance.properties' (file:./config/application-MyTest_LowerImportance.properties) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_LowerImportance.xml' (file:./config/application-MyTest_LowerImportance.xml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_LowerImportance.yml' (file:./config/application-MyTest_LowerImportance.yml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_LowerImportance.yaml' (file:./config/application-MyTest_LowerImportance.yaml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_MostImportant.properties' (file:./application-MyTest_MostImportant.properties) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_MostImportant.xml' (file:./application-MyTest_MostImportant.xml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_MostImportant.yml' (file:./application-MyTest_MostImportant.yml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_MostImportant.yaml' (file:./application-MyTest_MostImportant.yaml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_LowerImportance.properties' (file:./application-MyTest_LowerImportance.properties) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_LowerImportance.xml' (file:./application-MyTest_LowerImportance.xml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_LowerImportance.yml' (file:./application-MyTest_LowerImportance.yml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./application-MyTest_LowerImportance.yaml' (file:./application-MyTest_LowerImportance.yaml) resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_MostImportant.properties' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_MostImportant.xml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yaml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.properties' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.xml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yaml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_MostImportant.properties' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_MostImportant.xml' resource not found DEBUG 93941 --- [ main] osbccConfigFileApplicationListener : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_MostImportant.yml' (classpath:/application-MyTest_MostImportant.yml) TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_MostImportant.yaml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_LowerImportance.properties' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_LowerImportance.xml' resource not found DEBUG 93941 --- [ main] osbccConfigFileApplicationListener : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_LowerImportance.yml' (classpath:/application-MyTest_LowerImportance.yml) TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'classpath:/application-MyTest_LowerImportance.yaml' resource not found TRACE 93941 --- [ main] osbccConfigFileApplicationListener : Skipped config file 'file:./config/application-MyTest_MostImportant-test.properties' (file:./config/application-MyTest_MostImportant-test.properties) resource not found 

Spring boot 1.X et Spring Boot 2.X n’offrent pas les mêmes options et comportements concernant la Externalized Configuration .

La très bonne réponse de M. Deinum fait référence aux spécificités de Spring Boot 1.
Je vais mettre à jour pour Spring Boot 2 ici.

Propriétés de l’environnement sources et ordre

Spring Boot 2 utilise un ordre PropertySource très particulier conçu pour permettre une substitution sensible des valeurs. Les propriétés sont considérées dans l’ordre suivant:

  • Propriétés des parameters globaux de Devtools sur votre répertoire personnel (~ / .spring-boot-devtools.properties lorsque devtools est actif).

  • @TestPropertySource annotations sur vos tests.

  • @SpringBootTest#properties Atsortingbut d’annotation des @SpringBootTest#properties sur vos tests. Arguments de ligne de commande.

  • Propriétés de SPRING_APPLICATION_JSON (JSON intégré incorporé dans une variable d’environnement ou une propriété système).

  • ServletConfig initialisation ServletConfig .

  • ServletContext initialisation ServletContext .

  • Atsortingbuts JNDI de java:comp/env .

  • Propriétés du système Java ( System.getProperties() ).

  • Variables d’environnement OS.

  • Un RandomValuePropertySource qui a uniquement des propriétés aléatoires. *.

  • Propriétés d’application spécifiques à un profil en dehors de votre jar packagé (variantes application-{profile}.properties et YAML).

  • Propriétés d’application spécifiques à un profil, intégrées à votre jar (variantes application-{profile}.properties et YAML).

  • Propriétés d’application en dehors de votre jar empaqueté (variantes application.properties et YAML).

  • Propriétés d’ application.properties à votre jar (variantes application.properties et YAML).

  • @PropertySource annotations sur vos classes @Configuration . Propriétés par défaut (spécifiées en définissant SpringApplication.setDefaultProperties ).

Pour spécifier des fichiers de propriétés externes, ces options doivent vous intéresser:

  • Propriétés d’application spécifiques à un profil en dehors de votre jar packagé (variantes application-{profile}.properties et YAML).

  • Propriétés d’application en dehors de votre jar empaqueté (variantes application.properties et YAML).

  • @PropertySource annotations sur vos classes @Configuration . Propriétés par défaut (spécifiées en définissant SpringApplication.setDefaultProperties ).

Vous ne pouvez utiliser qu’une seule de ces trois options ou les combiner selon vos besoins.
Par exemple, pour des cas très simples, l’utilisation de propriétés spécifiques à un profil suffit, mais dans d’autres cas, vous souhaiterez peut-être utiliser à la fois les propriétés spécifiques au profil, les propriétés par défaut et @PropertySource .

Emplacements par défaut des fichiers application.properties

A propos application.properties fichiers application.properties (et des variantes), Spring les charge par défaut et ajoute leurs propriétés dans l’environnement dans l’ordre suivant:

  • Un sous-répertoire / config du répertoire en cours

  • Le répertoire actuel

  • Un package classpath / config

  • La racine du classpath

Les priorités les plus élevées sont littéralement:
classpath:/,classpath:/config/,file:./,file:./config/ .

Comment utiliser les fichiers de propriétés avec des noms spécifiques?

Les emplacements par défaut ne sont pas toujours suffisants: les emplacements par défaut tels que le nom de fichier par défaut ( application.properties ) peuvent ne pas convenir. De plus, comme dans la question OP, vous devrez peut-être spécifier plusieurs fichiers de configuration autres que application.properties (et variant).
Donc, spring.config.name ne sera pas suffisant.

Dans ce cas, vous devez fournir un emplacement explicite à l’aide de la propriété d’environnement spring.config.location (qui est une liste d’emplacements de répertoires ou de chemins de fichiers séparés par des virgules).
Pour être libre sur le modèle des noms de fichiers, privilégiez la liste des chemins de fichiers sur la liste des répertoires. De cette façon, c’est le plus bavard mais c’est aussi la manière de spécifier très finement nos fichiers de configuration.

spring.config.location remplace désormais les emplacements par défaut au lieu de les append

De plus, dans Spring Boot 1, l’argument spring.config.location ajoute des emplacements spécifiés dans l’environnement Spring.
Mais depuis Spring Boot 2, spring.config.location remplace les emplacements par défaut utilisés par Spring par les emplacements spécifiés dans l’environnement Spring, comme indiqué dans la documentation .

Lorsque des emplacements de configuration personnalisés sont configurés à l’aide de spring.config.location , ils remplacent les emplacements par défaut. Par exemple, si spring.config.location est configuré avec la valeur classpath:/custom-config/ , file:./custom-config/ , l’ordre de recherche devient le suivant:

  1. file:./custom-config/

  2. classpath:custom-config/

spring.config.location est maintenant un moyen de s’assurer que tout fichier application.properties doit être explicitement spécifié.
Pour les JARs Uber qui ne sont pas censés emballer application.properties fichiers application.properties , c’est plutôt bien.

Pour conserver l’ancien comportement de spring.config.location lors de l’utilisation de Spring Boot 2, vous pouvez utiliser la nouvelle propriété spring.config.additional-location au lieu de spring.config.location qui ajoute toujours les emplacements indiqués par la documentation :

De même, lorsque des emplacements de configuration personnalisés sont configurés à l’aide de spring.config.additional-location , ils sont utilisés en plus des emplacements par défaut.


En pratique

Donc, en supposant que, comme dans la question OP, vous avez 2 fichiers de propriétés externes à spécifier et 1 fichier de propriétés inclus dans le fichier uber jar.

Pour utiliser uniquement les fichiers de configuration que vous avez spécifiés:

 -Dspring.config.location=classpath:job1.properties,classpath:job2.properties,classpath:/applications.properties 

Pour append des fichiers de configuration à ces emplacements par défaut:

 -Dspring.config.additional-location=classpath:job1.properties,classpath:job2.properties 

classpath:/applications.properties n’est pas requirejs car les emplacements par défaut ont cela.

Une version modifiée de la solution @mxsb qui nous permet de définir plusieurs fichiers et dans mon cas, ce sont des fichiers yml.

Dans mon application-dev.yml, j’ai ajouté cette configuration qui me permet d’injecter tous les yml contenant -dev.yml. Cela peut être une liste de fichiers spécifiques également. “classpath: /test/test.yml,classpath: /test2/test.yml”

 application: properties: locations: "classpath*:/**/*-dev.yml" 

Cela aide à obtenir une carte de propriétés.

 @Configuration public class PropertiesConfig { private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class); @Value("${application.properties.locations}") private Ssortingng[] locations; @Autowired private ResourceLoader rl; @Bean Map myProperties() { return stream(locations) .collect(toMap(filename -> filename, this::loadProperties)); } private Properties loadProperties(final Ssortingng filename) { YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); try { final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename); final Properties properties = new Properties(); stream(possiblePropertiesResources) .filter(Resource::exists) .map(resource1 -> { try { return loader.load(resource1.getFilename(), resource1); } catch (IOException e) { throw new RuntimeException(e); } }).flatMap(l -> l.stream()) .forEach(propertySource -> { Map source = ((MapPropertySource) propertySource).getSource(); properties.putAll(source); }); return properties; } catch (IOException e) { throw new RuntimeException(e); } } } 

Cependant, si comme dans mon cas, je voulais séparer les fichiers yml pour chaque profil et les charger et les injecter directement dans la configuration du spring avant l’initialisation des beans.

 config - application.yml - application-dev.yml - application-prod.yml management - management-dev.yml - management-prod.yml 

… vous avez eu l’idée

Le composant est légèrement différent

 @Component public class PropertiesConfigurer extends PropertySourcesPlaceholderConfigurer implements EnvironmentAware, InitializingBean { private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfigurer.class); private Ssortingng[] locations; @Autowired private ResourceLoader rl; private Environment environment; @Override public void setEnvironment(Environment environment) { // save off Environment for later use this.environment = environment; super.setEnvironment(environment); } @Override public void afterPropertiesSet() throws Exception { // Copy property sources to Environment MutablePropertySources envPropSources = ((ConfigurableEnvironment) environment).getPropertySources(); envPropSources.forEach(propertySource -> { if (propertySource.containsProperty("application.properties.locations")) { locations = ((Ssortingng) propertySource.getProperty("application.properties.locations")).split(","); stream(locations).forEach(filename -> loadProperties(filename).forEach(source ->{ envPropSources.addFirst(source); })); } }); } private List loadProperties(final Ssortingng filename) { YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); try { final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename); final Properties properties = new Properties(); return stream(possiblePropertiesResources) .filter(Resource::exists) .map(resource1 -> { try { return loader.load(resource1.getFilename(), resource1); } catch (IOException e) { throw new RuntimeException(e); } }).flatMap(l -> l.stream()) .collect(Collectors.toList()); } catch (IOException e) { throw new RuntimeException(e); } } 

}

J’ai rencontré beaucoup de problèmes en essayant de comprendre cela. Voici ma configuration,

Dev Env: Windows 10, Java: 1.8.0_25, Spring Boot: 2.0.3.RELEASE, Printemps: 5.0.7.RELEASE

Ce que j’ai trouvé, c’est que le spring est fidèle au concept “Sensible defaults for configuration”. Cela signifie que vous devez avoir tous vos fichiers de propriétés dans votre fichier de guerre. Une fois là-bas, vous pouvez les remplacer à l’aide de la propriété de ligne de commande “–spring.config.additional-location” pour pointer vers des fichiers de propriétés externes. Mais cela ne fonctionnera pas si les fichiers de propriétés ne font pas partie du fichier de guerre d’origine.

Code de démonstration: https://github.com/gselvara/spring-boot-property-demo/tree/master