it-swarm.com.de

Spring Boot: Kann man externe application.properties-Dateien in beliebigen Verzeichnissen mit einem Fat-Jar verwenden?

Ist es möglich, mehrere Datei application.properties zu haben? (EDIT: Beachten Sie, dass sich diese Frage zu der Frage im Titel entwickelt hat.)

Ich habe versucht 2 Dateien zu haben.

  • Der erste befindet sich im Stammverzeichnis der Anwendung Jar.
  • Der zweite befindet sich in dem Verzeichnis, das in classpath angegeben ist.

Zwei Dateien heißen "application.properties".

Kann der Inhalt beider Dateien zusammengeführt werden? (und die Eigenschaftswerte des zweiten überschreiben den ersten). Oder wenn ich eine Datei habe, wird die andere Datei ignoriert?

UPDATE 1: Der Inhalt kann "zusammengefügt" werden. Gestern schien es, als wäre der erste ignoriert worden, aber es scheint, als wäre etwas gebrochen worden. Nun funktioniert es gut.

UPDATE 2: Es ist wieder da! Wieder wird nur eine von zwei Dateien angewendet. Es ist merkwürdig ... Es begann, nachdem ich die App-JAR-Datei mit Spring Tool Suite erstellt hatte. Es scheint, dass die Jar-Version immer die zweite (im Klassenpfad) ignoriert, während das Verhalten der erweiterten Version, die unter STS ausgeführt wird, unterschiedlich ist. Von wo aus kann ich mit der Untersuchung beginnen?

UPDATE 3:

Das Verhalten der Jar-Version war tatsächlich korrekt. Dies ist die Spezifikation von Java.exe . Wenn die Option -jar angegeben ist, ignoriert Java.exe sowohl die Option -classpath als auch die Umgebungsvariable CLASSPATH, und der Klassenpfad enthält nur die JAR-Datei. Die zweite Datei application.properties im Klassenpfad wird also ignoriert.

Wie kann ich nun die zweite application.properties des Klassenpfads laden lassen?

UPDATE 4:

Ich habe es geschafft, eine application.properties-Datei in einem externen Pfad zu laden, während ich die Option -jar verwendet.

Der Schlüssel war PropertiesLauncher.

Um PropertiesLauncher verwenden zu können, muss die Datei pom.xml folgendermaßen geändert werden:

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

Dazu habe ich auf die folgende StackOverflow-Frage verwiesen: Spring Boot Properties Launcher kann nicht verwenden. Übrigens: Im Spring Boot Maven Plugin-Dokument ( http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html ) ist keine Erwähnung enthalten Durch die Angabe von Zip wird ausgelöst, dass PropertiesLauncher verwendet wird. (Vielleicht in einem anderen Dokument?)

Nachdem die JAR-Datei erstellt wurde, konnte ich feststellen, dass der PropertiesLauncher verwendet wird, indem die Main-Class-Eigenschaft in META-INF/MENIFEST.MF im JAR überprüft wird.

Jetzt kann ich das Glas wie folgt ausführen (in Windows):

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

Beachten Sie, dass die Anwendungs-JAR-Datei in loader.path enthalten ist.

Nun wird eine application.properties-Datei in C:\My\External\Dir\config geladen.

Als Bonus kann auf jede Datei (z. B. statische HTML-Datei) in diesem Verzeichnis auch von der JAR zugegriffen werden, da sie sich im Ladepfad befindet.

In Bezug auf die in UPDATE 2 erwähnte (erweiterte) Version ohne Jar gab es möglicherweise ein Problem mit der Reihenfolge der Klassenpfade.

(Übrigens, ich habe den Titel der Frage geändert, um spezifischer auf dieses Problem einzugehen.)

48
zeodtr

Ich habe es geschafft, eine application.properties-Datei in einem externen Pfad zu laden, während ich die Option -jar verwendet.

Der Schlüssel war PropertiesLauncher.

Um PropertiesLauncher verwenden zu können, muss die Datei pom.xml folgendermaßen geändert werden:

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

Dazu habe ich auf die folgende StackOverflow-Frage verwiesen: Spring Boot Properties Launcher kann nicht verwenden. Übrigens: Im Spring Boot Maven Plugin-Dokument ( http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html ) ist keine Erwähnung enthalten Durch die Angabe von Zip wird ausgelöst, dass PropertiesLauncher verwendet wird. (Vielleicht in einem anderen Dokument?)

Nachdem die JAR-Datei erstellt wurde, konnte ich feststellen, dass der PropertiesLauncher verwendet wird, indem die Main-Class-Eigenschaft in META-INF/MENIFEST.MF im JAR überprüft wird.

Jetzt kann ich das Glas wie folgt ausführen (in Windows):

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

Beachten Sie, dass die Anwendungs-JAR-Datei in loader.path enthalten ist.

Nun wird eine application.properties-Datei in C:\My\External\Dir\config geladen.

Als Bonus kann auf jede Datei (z. B. statische HTML-Datei) in diesem Verzeichnis auch von der JAR zugegriffen werden, da sie sich im Ladepfad befindet.

In Bezug auf die in UPDATE 2 erwähnte (erweiterte) Version ohne Jar gab es möglicherweise ein Problem mit der Reihenfolge der Klassenpfade.

9
zeodtr

Wenn Sie die Standardeinstellungen von Spring Boot nicht geändert haben (dh Sie verwenden @EnableAutoConfiguration oder @SpringBootApplication und keine Eigenschaftsquellenbehandlung geändert), sucht das System nach Eigenschaften mit der folgenden Reihenfolge (höchste Überschreibungen am niedrigsten):

  1. Ein /config-Unterverzeichnis des aktuellen Verzeichnisses
  2. Das aktuelle Verzeichnis
  3. Ein classpath/config-Paket 
  4. Die Klassenpfadwurzel 

Die obige Liste ist in this Teil der Dokumentation aufgeführt

Das heißt, wenn eine Eigenschaft gefunden wird, zum Beispiel application.properties unter src/resources is, wird sie durch eine Eigenschaft mit demselben Namen überschrieben, die in application.properties im /config-Verzeichnis gefunden wird, das sich "neben" dem verpackten Glas befindet.

Diese Standardreihenfolge, die von Spring Boot verwendet wird, ermöglicht eine sehr einfache Konfigurations-Externalisierung, wodurch Anwendungen in mehreren Umgebungen (Dev, Staging, Produktion, Cloud usw.) einfach konfiguriert werden können.

Um alle von Spring Boot bereitgestellten Funktionen für das Lesen von Eigenschaften anzuzeigen (Hinweis: Es gibt viel mehr als das Lesen von application.properties), lesen Sie den Abschnitt this Teil der Dokumentation aus.

Wie aus meiner kurzen Beschreibung oben oder aus der vollständigen Dokumentation hervorgeht, sind Spring Boot-Apps sehr DevOps-freundlich!

42
geoand

Alles wird hier in den Dokumenten erklärt:

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

Was erklärt, dass dies die Rangfolge ist:

  • Ein/config-Unterverzeichnis des aktuellen Verzeichnisses.
  • Das aktuelle Verzeichnis
  • Ein Klassenpfad/Konfigurationspaket
  • Die Klassenpfadwurzel

Es wird auch darauf hingewiesen, dass Sie zusätzliche Eigenschaftendateien für Überschreibungen definieren können, z.

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

Wenn Sie spring.config.location verwenden, werden auch alle Standardspeicherorte für application.properties eingeschlossen. Dies bedeutet, dass Sie in application.properties Standardwerte einrichten und je nach Bedarf für eine bestimmte Umgebung überschreiben können.

13
Steve

Sie könnten Ihre Spring Boot-Anwendung mit dem Pfad der externen Eigenschaftendatei wie folgt starten:

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

Wenn Sie Spring Boot JAR mit Maven Install erstellen und möchten, dass alle Ressourcen wie die Eigenschaftendatei und der Lib-Ordner außerhalb von JAR erstellt werden, fügen Sie den folgenden Code in pom.xml hinzu, in dem der Ausgabeordner definiert wird, in dem ich möchte die gewünschten Ressourcen von Glas zu extrahieren und zu speichern.

<build>
<finalName>project_name_Build/project_name</finalName>
   <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/project_name_Build/lib</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>write here the qualified or complete path of main class of application</mainClass>
                    </manifest>
                    <manifestEntries>
                        <Class-Path>. resources/</Class-Path>
                    </manifestEntries>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>
    </plugins>

    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>application.properties</include>
                <include>log4j.properties</include>
            </includes>
            <targetPath>${project.build.directory}/ConsentGatewayOfflineBuild/resources</targetPath>
        </resource>

        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>application.properties</include>
                <include>log4j.properties</include>
            </includes>
        </resource>

    </resources>

    <pluginManagement>
        <plugins>
            <!-- Ignore/Execute plugin execution -->
            <plugin>
                <groupId>org.Eclipse.m2e</groupId>
                <artifactId>lifecycle-mapping</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <lifecycleMappingMetadata>
                        <pluginExecutions>
                            <!-- copy-dependency plugin -->
                            <pluginExecution>
                                <pluginExecutionFilter>
                                    <groupId>org.Apache.maven.plugins</groupId>
                                    <artifactId>maven-dependency-plugin</artifactId>
                                    <versionRange>[1.0.0,)</versionRange>
                                    <goals>
                                        <goal>copy-dependencies</goal>
                                    </goals>
                                </pluginExecutionFilter>
                                <action>
                                    <ignore />
                                </action>
                            </pluginExecution>
                        </pluginExecutions>
                    </lifecycleMappingMetadata>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
0
PulkitRajput

Lösung für Yml-Datei:

1.Copy yml in dasselbe Verzeichnis wie die jar-Anwendung

2. Run Befehl, Beispiel für xxx.yml:

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

Es funktioniert gut, aber im Startlogger ist INFO:

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

Eine andere flexible Möglichkeit ist der Klassenpfad, der fat jar (-cp fat.jar) oder alle Jars (-cp "$ JARS_DIR/*") enthält, und ein anderer benutzerdefinierter Klassenpfad oder Ordner mit Konfigurationsdateien, der normalerweise außerhalb und außerhalb von jar Konfigurationsdateien enthält. Verwenden Sie also anstelle des eingeschränkten Java-Jars den flexibleren Klassenpfad wie folgt:

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

Siehe Spring-Boot-ausführbare jar doc und diesen Link

Wenn Sie über mehrere MainApps verfügen, die häufig verwendet werden, können Sie Folgendes verwenden: __. Wie kann ich Spring Boot mitteilen, welche Hauptklasse für die ausführbare jar verwendet werden soll?

Sie können zusätzliche Speicherorte hinzufügen, indem Sie die Umgebungsvariable LOADER_PATH oder loader.path in loader.properties (durch Kommas getrennte Liste von Verzeichnissen, Archiven oder Verzeichnissen in Archiven) festlegen. Grundsätzlich funktioniert loader.path sowohl für Java-Jar als auch für Java-CP.

Und wie immer können Sie die application.yml überschreiben und genau angeben, die sie zum Debuggen abholen soll 

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

Dies könnte in Late kommen, aber ich denke, ich habe einen besseren Weg gefunden, externe Konfigurationen zu laden, insbesondere wenn Sie Ihre Spring-Boot-App mit Java jar myapp.waranstelle von @PropertySource ("classpath: some.properties") ausführen

Die Konfiguration wird vom Stamm des Projekts oder von dem Speicherort geladen, von dem aus die Kriegs-/JAR-Datei ausgeführt wird

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

            }

        }
    }

}

Ich hoffe es hilft.

0
JohnTheBeloved
Java -jar server-0.0.1-SNAPSHOT.jar --spring.config.location=application-prod.properties
0
HimalayanCoder

Ich weiß, dass es sich um eine gezielte Frage handelt, und die Operation wollte eine andere Eigenschaftendatei laden.

Meine Antwort ist, dass es eine schreckliche Idee ist, solche benutzerdefinierten Hacks durchzuführen.

Wenn Sie Spring-Boot mit einem Cloud-Anbieter wie Cloud Foundry verwenden, tun Sie sich selbst einen Gefallen und nutzen Sie Cloud-Konfigurationsdienste

https://spring.io/projects/spring-cloud-config

Es lädt und führt standardmäßige/dev/project-default/project-dev-spezifische Eigenschaften wie Magic zusammen

Auch hier bietet Ihnen Spring Boot bereits genügend Möglichkeiten, dies richtig zu tun . Https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external- config.html

Bitte erfinden Sie das Rad nicht neu.

0
Kalpesh Soni