web-dev-qa-db-fra.com

Comment externaliser Spring Boot application.properties dans le dossier Tomcat / lib

J'ai besoin d'une guerre déployable et sans configuration, myapp1.war qui peut récupérer les fichiers de configuration à partir du dossier Tomcat/lib. Comme j'ai d'autres applications Web coexistant sur le même Tomcat: myapp2.war, myapp3.war, j'ai besoin de cette disposition:

Tomcat/lib/myapp1/application.properties
Tomcat/lib/myapp2/application.properties
Tomcat/lib/myapp3/application.properties

De cette façon, je peux créer les fichiers de guerre sans aucun fichier de propriétés à l'intérieur de la guerre et déployer sur n'importe quel serveur.

J'ai lu la documentation Spring mais elle explique comment définir l'emplacement lors de l'exécution en tant que jar:

Java -jar myapp.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

Je ne peux pas comprendre comment procéder dans le cas de plusieurs fichiers de guerre coexistants.

Je voudrais savoir si cela est possible ou dois-je abandonner Spring Boot et revenir aux applications Spring MVC traditionnelles.

23
Daniel Mora

Une solution pourrait être de charger application- {profile} .properties comme des annotations @PropertySource comme cela question le suggère, mais le système de journalisation ne fonctionnera pas, comme vous pouvez le voir dans la documentation =.

Le système de journalisation est initialisé au début du cycle de vie de l'application et, en tant que telles, les propriétés de journalisation ne seront pas trouvées dans les fichiers de propriétés chargés via les annotations @PropertySource.

Cela signifie que vos propriétés de journalisation dans application- {profiles} .properties comme:

logging.config=classpath:myapp1/logback.xml
logging.path = /path/to/logs
logging.file = myapp1.log

sera ignoré et le système de journalisation ne fonctionnera pas.

Pour résoudre ce problème, j'ai utilisé la méthode SpringApplicationBuilder.properties () pour charger les propriétés au début, lorsque l'application est configurée. Là, j'ai défini le 'spring.config.location' utilisé par Spring Boot pour charger tous les {profils} .properties d'application:

public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
        return springApplicationBuilder
                .sources(Application.class)
                .properties(getProperties());
    }

    public static void main(String[] args) {

        SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(Application.class)
                .sources(Application.class)
                .properties(getProperties())
                .run(args);
    }

   static Properties getProperties() {
      Properties props = new Properties();
      props.put("spring.config.location", "classpath:myapp1/");
      return props;
   }
}

Ensuite, j'ai déplacé les fichiers de propriétés de src/main/resources vers src/main/resources/myapp1

.
├src
| └main
|   └resources
|     └myapp1
|       └application.properties
|       └application-development.properties
|       └logback.xml
└─pom.xml

Dans le pom.xml, je dois définir la portée des bibliothèques Tomcat intégrées comme "fournies". En outre, pour exclure tous les fichiers de propriétés dans src/main/resources/myapp1 de la guerre finale et générer une guerre déployable sans configuration:

    <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
            <failOnMissingWebXml>false</failOnMissingWebXml>
            <packagingExcludes>
              **/myapp1/
            </packagingExcludes>
        </configuration>
    </plugin>

Puis à Tomcat j'ai

├Apache-Tomcat-7.0.59
 └lib
   ├─myapp1
   |  └application.properties        
   |  └logback.xml
   └─myapp2
     └application.properties
     └logback.xml

Maintenant, je peux générer la guerre sans configuration et la déposer dans le dossier Apache-Tomcat-7.0.59/webapps. Les fichiers de propriétés seront résolus à l'aide du chemin de classe, indépendamment pour chaque application Web:

   Apache-Tomcat-7.0.59/lib/myapp1
   Apache-Tomcat-7.0.59/lib/myapp2
   Apache-Tomcat-7.0.59/lib/myapp3
30
Daniel Mora

Avec Spring 4.2 et @Annotation config et Tomcat sur serveur linux

Dans votre classe Application, définissez la @PropertySource comme ceci:

@Configuration
@EnableWebMvc
@PropertySource(value = { "classpath:application-yourapp.properties"})
@ComponentScan(basePackages = "com.yourapp")
public class YourAppWebConfiguration extends WebMvcConfigurerAdapter {

    ...
}

Maintenant, il vous suffit d'inclure le fichier de propriétés dans votre chemin de classe

En production

Déployez vos fichiers .war (ou quoi que ce soit) sur Tomcat, et placez quand même vos applications-votreapp.properties sur votre machine de production. (par exemple dans /opt/applyconfigfolder/application-yourapp.properties ")

Ensuite, dans votre Tomcat (ici Tomcat 7), ouvrez bin\catalina.sh

Vous avez cette ligne

# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=

Ajoutez simplement le chemin du dossier qui contient application.properties

CLASSPATH=:/opt/applyconfigfolder

Si vous avez déjà défini un chemin de classe, vous pouvez l'ajouter

CLASSPATH=:/opt/applyconfigfolder:/yourpath1:/yourpath2:

Je n'ai pas essayé avec Windows mais je pense qu'il n'y a pas de problème

En Dev (avec Eclipse)

├src
| └main
|   └ ....
└config
| └application-yourapp.properties

au lieu de src/main/resources/application-yourapp.properties

Maintenant, dans Eclipse, ajoutez votre dossier de configuration au chemin de classe, accédez à "Exécuter les configurations" de votre serveur Tomcat (ou équivalent) et ajoutez le dossier Config aux entrées utilisateur

enter image description here

D'accord, votre application.properties est hors de l'application et votre projet fonctionne parfaitement dans un environnement de développement.

2
amdev

Daniel Mora a donné une bonne solution mais au lieu d'utiliser spring.config.location, vous pouvez utiliser spring.config.name ( https://docs.spring.io/spring-boot/docs/current/reference/html/ boot-features-external-config.html # boot-features-external-config-application-property-files ), vous pouvez donc avoir un fichier de propriétés différent pour différentes applications Web dans le même répertoire Tomcat/lib:

    public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
        return springApplicationBuilder
                .sources(Application.class)
                .properties(getProperties());
    }
    public static void main(String[] args) {

        SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(Application.class)
                .sources(Application.class)
                .properties(getProperties())
                .run(args);
    }

   static Properties getProperties() {
      Properties props = new Properties();
      props.put("spring.config.name", "myapp1");
      return props;
   }
}

Je pense que le répertoire lib est destiné aux bibliothèques tierces et non au stockage des propriétés de configuration de vos applications Web. Je pense donc qu'une meilleure solution consiste à ajouter un dossier externe en tant que dossier de chemin de classe supplémentaire en utilisant la propriété shared.loader dans conf/catalina.properties:

shared.loader = $ {catalina.base}/shared/configurations

Vous pouvez mettre vos propriétés d'application app1.properties, app2.properties, ecc .. dans Apache-Tomcat-7.0.59/shared/configurations.

Avant de trouver la solution Daniel Mora de substitution de la méthode de configuration de SpringBootServletInitializer, ma solution consistait à ajouter un context.xml dans src/main/webapp/META-INF avec ce contenu:

<Context>
    <Environment name="spring.config.name" value="myapp1" type="Java.lang.String" override="false" description="define the property file for srping boot application"/>
</Context>
2