web-dev-qa-db-fra.com

Spring Boot: Est-il possible d'utiliser des fichiers externes application.properties dans des répertoires arbitraires avec un gros fichier jar?

Est-il possible d'avoir plusieurs fichiers application.properties? (EDIT: notez que cette question a évolué vers celle du titre.)

J'ai essayé d'avoir 2 fichiers.

  • Le premier se trouve dans le dossier racine du fichier Jar de l’application.
  • Le second est sur le répertoire spécifié dans classpath.

2 fichiers sont nommés 'application.properties'.

Est-il possible de "fusionner" le contenu des deux fichiers? (et les valeurs de propriété du second remplacent celles du premier) Ou, si j'ai un fichier, l'autre fichier est ignoré?

UPDATE 1: il est possible de "fusionner" le contenu. Hier, il semblait que le premier avait été ignoré, mais apparemment parce que quelque chose avait été cassé. Maintenant ça marche bien.

UPDATE 2: C'est de retour! Encore une fois, un seul des deux fichiers est appliqué. C'est étrange ... Cela a commencé après la création du fichier jar de l'application à l'aide de Spring Tool Suite. Et il semble que la version Jar ignore toujours la seconde version (dans classpath), alors que le comportement de la version développée qui s'exécute sur STS varie. D'où puis-je commencer à enquêter?

UPDATE 3:

Le comportement de la version Jar était en fait correct. Il s'agit de la spécification de Java.exe . Lorsque l'option -jar est spécifiée, Java.exe ignore à la fois l'option -classpath et la variable d'environnement CLASSPATH, et le chemin d'accès aux classes ne contiendra que le fichier jar. Ainsi, le deuxième fichier application.properties sur le chemin de classe est ignoré.

Maintenant, comment puis-je laisser le second application.properties sur le classpath être chargé?

UPDATE 4:

J'ai réussi à charger un fichier application.properties dans un chemin externe en utilisant l'option -jar.

La clé était PropertiesLauncher.

Pour utiliser PropertiesLauncher, le fichier pom.xml doit être modifié comme suit:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>  <!-- added -->
                <layout>Zip</layout> <!-- to use PropertiesLaunchar -->
            </configuration>
        </plugin>
    </plugins>
</build>

Pour cela, j'ai référencé la question suivante de StackOverflow: lanceur de propriétés de démarrage à ressort incapable d'utiliser . BTW, dans le document Spring Boot Maven Plugin ( http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html ), il n'y a pas de mention que la spécification de Zip déclenche l'utilisation de PropertiesLauncher. (Peut-être dans un autre document?)

Une fois le fichier jar créé, je pouvais constater que PropertiesLauncher était utilisé en inspectant la propriété Main-Class dans META-INF/MENIFEST.MF dans le fichier jar.

Maintenant, je peux exécuter le fichier jar comme suit (sous Windows):

Java -Dloader.path=file:///C:/My/External/Dir,MyApp-0.0.1-SNAPSHOT.jar -jar MyApp-0.0.1-SNAPSHOT.jar

Notez que le fichier jar de l'application est inclus dans loader.path.

Un fichier application.properties est maintenant chargé dans C:\My\External\Dir\config.

En prime, tous les fichiers (par exemple, les fichiers HTML statiques) de ce répertoire sont également accessibles par le fichier jar car ils se trouvent dans le chemin du chargeur.

En ce qui concerne la version non-jar (développée) mentionnée dans UPDATE 2, il y avait peut-être un problème d'ordre de classpath.

(BTW, j'ai changé le titre de la question pour être plus spécifique à cette question.)

48
zeodtr

J'ai réussi à charger un fichier application.properties dans un chemin externe en utilisant l'option -jar.

La clé était PropertiesLauncher.

Pour utiliser PropertiesLauncher, le fichier pom.xml doit être modifié comme suit:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>  <!-- added -->
                <layout>Zip</layout> <!-- to use PropertiesLaunchar -->
            </configuration>
        </plugin>
    </plugins>
</build>

Pour cela, j'ai référencé la question suivante de StackOverflow: lanceur de propriétés de démarrage à ressort incapable d'utiliser . BTW, dans le document Spring Boot Maven Plugin ( http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html ), il n'y a pas de mention que la spécification de Zip déclenche l'utilisation de PropertiesLauncher. (Peut-être dans un autre document?)

Une fois le fichier jar créé, je pouvais constater que PropertiesLauncher était utilisé en inspectant la propriété Main-Class dans META-INF/MENIFEST.MF dans le fichier jar.

Maintenant, je peux exécuter le fichier jar comme suit (sous Windows):

Java -Dloader.path=file:///C:/My/External/Dir,MyApp-0.0.1-SNAPSHOT.jar -jar MyApp-0.0.1-SNAPSHOT.jar

Notez que le fichier jar de l'application est inclus dans loader.path.

Un fichier application.properties est maintenant chargé dans C:\My\External\Dir\config.

En prime, tous les fichiers (par exemple, les fichiers HTML statiques) de ce répertoire sont également accessibles par le fichier jar car ils se trouvent dans le chemin du chargeur.

En ce qui concerne la version non-jar (développée) mentionnée dans UPDATE 2, il y avait peut-être un problème d'ordre de classpath.

9
zeodtr

Si vous n'avez pas modifié les valeurs par défaut de Spring Boot (ce qui signifie que vous utilisez @EnableAutoConfiguration ou @SpringBootApplication et que vous n'avez pas modifié la gestion de Property Source), il recherchera les propriétés dans l'ordre suivant (les plus hautes substitutions seront les plus basses):

  1. Un sous-répertoire /config du répertoire en cours
  2. Le répertoire courant
  3. Un package classpath/config 
  4. La racine du classpath 

La liste ci-dessus est mentionnée dans this une partie de la documentation

Cela signifie que si une propriété est trouvée, par exemple, application.properties sous src/resources, elle sera remplacée par une propriété portant le même nom que celle trouvée dans application.properties dans le répertoire /config qui est "suivant" le fichier jar emballé.

Cet ordre par défaut utilisé par Spring Boot permet une externalisation très facile de la configuration, ce qui facilite la configuration des applications dans plusieurs environnements (développement, stockage intermédiaire, production, cloud, etc.).

Pour voir l'ensemble des fonctionnalités fournies par Spring Boot pour la lecture des propriétés (conseil: il y a beaucoup plus de choses disponibles que la lecture de application.properties), consultez this dans la documentation.

Comme on peut le voir dans ma brève description ci-dessus ou dans la documentation complète, les applications Spring Boot sont très conviviales pour DevOps!

42
geoand

Tout est expliqué ici dans la documentation:

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Ce qui explique qu'il s'agit de l'ordre de priorité:

  • Un sous-répertoire/config du répertoire en cours.
  • Le répertoire courant
  • Un paquet classpath/config
  • La racine du classpath

Il indique également que vous pouvez définir des fichiers de propriétés supplémentaires pour les remplacements, comme suit:

Java -jar myproject.jar 
    --spring.config.location=classpath:/overrides.properties

Si vous utilisez spring.config.location, tous les emplacements par défaut de application.properties sont également inclus. Cela signifie que vous pouvez définir les valeurs par défaut dans application.properties et les remplacer, le cas échéant, dans un environnement particulier.

13
Steve

Vous pourrez lancer votre application de démarrage printanier avec le chemin du fichier de propriétés externe comme suit:

Java -jar {jar-file-name}.jar 
--spring.config.location=file:///C:/{file-path}/{file-name}.properties
7
Krishna Kuntala
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <layout>Zip</layout> 
            </configuration>
        </plugin>
    </plugins>
</build>

Java -Dloader.path=file:///absolute_path/external.jar -jar example.jar
2
Ravindranath Akila

Solution pour le fichier yml:

1. Copiez yml dans le même répertoire que l'application jar

Commande 2.Run, exemple pour xxx.yml:

Java -jar app.jar --spring.config.location=xxx.yml

Cela fonctionne bien, mais dans le journal de démarrage, il y a INFO:

No active profile set .........
0
Piotr R

Une autre manière flexible d’utiliser un chemin de classe contenant fat jar (-cp fat.jar) ou tous les jars (-cp "$ JARS_DIR/*") et un autre chemin de classe ou dossier de configuration personnalisé contenant des fichiers de configuration, généralement ailleurs et en dehors de jar. Ainsi, au lieu du java limité -jar, utilisez la méthode plus souple des chemins de classes comme suit:

Java \
   -cp fat_app.jar \ 
   -Dloader.path=<path_to_your_additional_jars or config folder> \
   org.springframework.boot.loader.PropertiesLauncher

Voir Doc. Jar exécutable de démarrage au démarrage et ce lien

Si vous avez plusieurs MainApps communes, vous pouvez utiliser Comment puis-je dire à Spring Boot quelle classe principale utiliser pour le fichier jar exécutable?

Vous pouvez ajouter des emplacements supplémentaires en définissant une variable d'environnement LOADER_PATH ou loader.path dans loader.properties (liste de répertoires, archives ou répertoires séparés par des virgules). En gros, loader.path fonctionne pour les méthodes Java -jar ou Java -cp.

Et comme toujours, vous pouvez remplacer et spécifier exactement le fichier application.yml qu’il devrait récupérer à des fins de débogage 

--spring.config.location=/some-location/application.yml --debug
0
kisna

Cela arrive peut-être tard, mais je pense avoir trouvé un meilleur moyen de charger des configurations externes, surtout lorsque vous exécutez votre application spring-boot en utilisant Java jar myapp.war au lieu de @PropertySource ("classpath: some.properties")

La configuration serait chargée depuis la racine du projet ou depuis l'emplacement où le fichier war/jar est exécuté.

public class Application implements EnvironmentAware {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void setEnvironment(Environment environment) {
        //Set up Relative path of Configuration directory/folder, should be at the root of the project or the same folder where the jar/war is placed or being run from
        String configFolder = "config";
        //All static property file names here
        List<String> propertyFiles = Arrays.asList("application.properties","server.properties");
        //This is also useful for appending the profile names
        Arrays.asList(environment.getActiveProfiles()).stream().forEach(environmentName -> propertyFiles.add(String.format("application-%s.properties", environmentName))); 
        for (String configFileName : propertyFiles) {
            File configFile = new File(configFolder, configFileName);
            LOGGER.info("\n\n\n\n");
            LOGGER.info(String.format("looking for configuration %s from %s", configFileName, configFolder));
            FileSystemResource springResource = new FileSystemResource(configFile);
            LOGGER.log(Level.INFO, "Config file : {0}", (configFile.exists() ? "FOund" : "Not Found"));
            if (configFile.exists()) {
                try {
                    LOGGER.info(String.format("Loading configuration file %s", configFileName));
                    PropertiesFactoryBean pfb = new PropertiesFactoryBean();
                    pfb.setFileEncoding("UTF-8");
                    pfb.setLocation(springResource);
                    pfb.afterPropertiesSet();
                    Properties properties = pfb.getObject();
                    PropertiesPropertySource externalConfig = new PropertiesPropertySource("externalConfig", properties);
                    ((ConfigurableEnvironment) environment).getPropertySources().addFirst(externalConfig);
                } catch (IOException ex) {
                    LOGGER.log(Level.SEVERE, null, ex);
                }
            } else {
                LOGGER.info(String.format("Cannot find Configuration file %s... \n\n\n\n", configFileName));

            }

        }
    }

}

J'espère que ça aide.

0
JohnTheBeloved