2017-08-01 4 views
1

Ich habe eine SpringBoot App, die mit integriertem Tomcat ausgeführt wird. Dieser Listener ist dafür zuständig, die Anwendungseigenschaften aus einer MySQL-Datenbank zu laden und in die Umgebung einzufügen. Es sieht wie folgt aus:Spring Boot Embedded Tomcat lädt externe Eigenschaftendatei nicht in ApplicationListener

@Component 
public class DbMigrationAndPropertyLoaderApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered { 

    private static final Logger LOGGER = LoggerFactory.getLogger(DbMigrationAndPropertyLoaderApplicationListener.class); 

    private static final String PROPERTY_SOURCE_NAME = "applicationProperties"; 

    private final int order = Ordered.HIGHEST_PRECEDENCE + 4; 

    private final PropertySourceProcessor propertySourceProcessor = new PropertySourceProcessor(); 

    @Override 
    public int getOrder() { 
     return this.order; 
    } 

    @Override 
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { 
     Properties databaseProperties; 
     try { 
      databaseProperties = PropertiesLoaderUtils.loadAllProperties("application-datasource.properties"); 
     } catch (IOException e) { 
      throw new RuntimeException("Unable to load properties from application-datasource.properties. Please ensure that this file is on your classpath", e); 
     } 
    ConfigurableEnvironment environment = event.getEnvironment(); 
    Map<String, Object> propertySource = new HashMap<>(); 
    try { 
     DataSource ds = DataSourceBuilder 
       .create() 
       .username(databaseProperties.getProperty("flyway.user")) 
       .password(EncryptionUtil.decrypt(databaseProperties.getProperty("flyway.password"))) 
       .url(databaseProperties.getProperty("spring.datasource.url")) 
       .driverClassName(databaseProperties.getProperty("spring.datasource.driver-class-name")) 
       .build(); 

     LOGGER.debug("Running Flyway Migrations"); 
     //Run Flyway migrations. If this is the first time, it will create and populate the APPLICATION_PROPERTY table. 
     Flyway flyway = new Flyway(); 
     flyway.setDataSource(ds); 
     flyway.migrate(); 

     LOGGER.debug("Initializing properties from APPLICATION_PROPERTY table"); 
     //Fetch all properties 

     Connection connection = null; 
     PreparedStatement preparedStatement = null; 
     ResultSet resultSet = null; 
     try { 
      connection = ds.getConnection(); 
      preparedStatement = connection.prepareStatement("SELECT prop_key, prop_value FROM APPLICATION_PROPERTY"); 

      resultSet = preparedStatement.executeQuery(); 

      //Populate all properties into the property source 
      while (resultSet.next()) { 
       String propName = resultSet.getString("prop_key"); 
       propertySource.put(propName, propertySourceProcessor.decrypt(resultSet.getString("prop_value"))); 
      } 

      //Create a custom property source with the highest precedence and add it to the Environment 
      environment.getPropertySources().addFirst(new MapPropertySource(PROPERTY_SOURCE_NAME, propertySource)); 

ich so um die Anwendung aufzurufen:

public static void main(String[] args) { 
     ApplicationContext ctx = new SpringApplicationBuilder(PortalApplication.class) 
       .listeners(new DbMigrationAndPropertyLoaderApplicationListener()) 
       .build(args) 
       .run(); 

Was ich versuche zu tun, um die application-datasource.properties Datei auszulagern, damit es auf meine verschiedenen residieren kann App-Server (Dev, QA, Prod etc.). Ich bin jedoch nicht in der Lage, den Zuhörer dazu zu bringen, diese Eigenschaftendatei zu finden, und ich bin nicht sicher, warum. Ich versuchte, die RUN_ARGS Eigenschaft in der deployment.conf Datei zu so etwas wie

RUN_ARGS Einstellung = - spring.config.location =/path/to/application-datasource.properties

Ich habe auch versucht, das Hinzufügen Verzeichnis mit der Eigenschaftendatei zum Klassenpfad. Nichts, was ich tue, scheint zu funktionieren, aber ich bin mir sicher, ich mache hier nur etwas Dummes. Beachten Sie, dass ich beim Laden der Datei keine Ausnahme erhalte, die resultierenden Eigenschaften sind einfach leer.

Antwort

1

Spring Boot gemacht Eigenschaft Datei laden sehr einfach und stressfrei.Sie müssen nicht stören beim Laden von Eigenschaften und Spring Boot ist da. Es gibt viele Möglichkeiten, Objekte mit Federverschluß sind nur einige der dort Datei zu laden: 1) einfach mit application-{Profile}.properties Auftragungseigenschaft auf Classpath bieten und gerade aktive Profil als Argument übergeben --spring.profiles.active= profileName

2) Konfigurationsdatei mit spring.config.location, in denen Eigenschaften geladen als eine verwendete Umgebungseigenschaft definiert werden. (Wir können es aus Classpath oder externen Dateipfad laden Wie pro Feder Boot offizielle Dokumentation, standardmäßig die konfigurierten Standorte sind classpath:/,classpath:/config/,file:./,file:./config/. Die resultierende Suchreihenfolge ist.

file:./config/ 

file:./ 

classpath:/config/ 

classpath:/ 

Wenn benutzerdefinierte Konfigurations Standorte konfiguriert sind, sind sie . Zusätzlich zu den Standardpositionen verwendet benutzerdefinierte Standorte werden vor den Standardpositionen gesucht wenn beispielsweise benutzerdefinierte Standorte classpath:/custom-config/,file:./custom-config/ konfiguriert werden, wird die Suchreihenfolge:.

file:./custom-config/ 

classpath:custom-config/ 

file:./config/ 

file:./ 

classpath:/config/ 

classpath:/ 

3) Sie können auch @PropertySource Anmerkungen auf IhremverwendenKlassen

Bitte beachten this für weitere Einzelheiten (24.4 und 24.5)

Antwort Herausgegeben

Wie pro Ihren Kommentar möchten Sie Ihre Eigenschaften vor jeder Bohne geladen dann erstellt, warum Sie es aus Classpath wollen ?? ? Sie können es sicherer machen, indem Sie es auf dem relativen Dateipfad beibehalten. Beim Lesen der Eigenschaftendatei aus dem relativen Dateipfad ergeben sich mehrere Vorteile.

1) Property-Datei im relativen Dateipfad auf dem Server, die sicher und ohne direkten Zugriff ist. 2) Wenn die Datei geändert wird, ist kein neuer Patch erforderlich. Sie müssen nur den Prozess neu starten und die aktualisierten Eigenschaften werden verwendet. 3) Über alle weniger Anstrengungen in der Modifikation erforderlich.

nun unter dem Beispiel ist die mit Ihren Anforderungen perfekte Übereinstimmung ist:

private static Properties loadConfigProps() { 
     InputStream configStream = null; 
     Properties _ConfigProps = null; 
     try { 
      String prjDir = System.getProperty("user.dir"); 
      String activeProfile = System.getProperty("activeProfile"); 
      int lastIndex = prjDir.lastIndexOf(File.separator); 

      String configPath = prjDir.substring(0, lastIndex); 
      configStream = new FileInputStream(new File(configPath 
        + File.separator + "_configurations" + File.separator + activeProfile + File.separator 
        + "resources" + File.separator + "myDatabaseProperties.properties")); 
      _ConfigProps = new Properties(); 
      _ConfigProps.load(configStream); 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
      System.exit(1); 
     } finally { 
      if (null != configStream) { 
       try { 
        configStream.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
     return _ConfigProps; 
    } 

Jetzt nur noch zwei Dinge tun müssen, um Sie, 1) Verzeichnis erstellen 2) Stellen Sie tatsächliches aktives Profil auf der Laufzeit

1) Verzeichnis erstellen:

Wenn Ihr Arbeitsverzeichnis ./path/to/applications/active_project dann neue Ordner in ./path/to/applications/ Verzeichnis erstellen:

./path/to/applications/ 
      -active_project/ 
      -_configurations/ 
          -QA/myDatabaseProperties.properties 
          -Dev/myDatabaseProperties.properties 
          -Prod/myDatabaseProperties.properties 

2) tatsächliches aktives Profil auf Laufzeit bereitstellen:

java -DactiveProfile=Dev -jar jarFileName.jar 
+0

Nun, das Problem ist, ich habe, dass meine Anwendung Hörer ausführt, bevor Bohnen oder vor dem autowiring abgeschlossen erstellt wurden, so Die Anwendungseigenschaften wurden noch nicht geladen. Daher versuche ich, die Eigenschaftendatei manuell aus dem Klassenpfad zu laden und dann die Eigenschaften zu verwenden, um eine Datenquelle zu initialisieren und den Rest meiner Eigenschaften abzurufen und in die Umgebung zu übertragen, damit sie bei der App-Initialisierung verfügbar sind. – cloudwalker

+0

ok ich habe deinen Punkt und ich glaube, es gibt ein Problem mit bereitgestellten Pfad. –

+0

ok ich habe Ihren Punkt und ich glaube, es gibt ein Problem mit bereitgestellten Pfad, zum Beispiel bieten Sie Pfad wie '/path/to/application-datasource.properties', aber Frühjahr nicht unter Unterverzeichnissen des Klassenpfads 'src/main/Ressourcen/'standardmäßig. Ich werde meine Antwort entsprechend aktualisieren. –

0

Sie können dies von der Hauptmethode selbst versuchen.

public static void main(String[] args){ 
    SpringApplication app = new SpringApplication(Application.class); 
    Map<String, Object> properties = new HashMap<>(); 
    properties.put("spring.profiles.default", "local"); 
    app.setDefaultProperties(properties); 
    Environment env = app.run(args).getEnvironment(); 
    env.getProperty("spring.application.name") 
    } 

und Sie können die entsprechende Datei für Umwelt eingestellten erstellen.

Verwandte Themen