2017-03-16 28 views
1

私はSpringBootにEnvironmentPostProcessorを作成して、データベースからプロパティを取得し、PropertySourceとしてSpringのEnvironmentに接続しました。 EnvironmentPostProcessor実行でエラーをログに記録する方法

この

は私が持っているコードです:

@Override 
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { 
    Map<String, Object> propertySource = new HashMap<>(); 
    // LOG SOMETHING HERE ******************* 
    logger.error("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); 
    String[] activeProfiles = environment.getActiveProfiles(); 
    String[] defaultProfiles = environment.getDefaultProfiles(); 

    // Do not pull db configuration when 'default' profile (used by Jenkins only) is run 
    if (activeProfiles.length == 0 && defaultProfiles[0] == "default") { 
     return; 
    } 

    // Load properties for Config schema 
    String dataSourceUrl = environment.getProperty("service.datasource.url"); 
    String username = environment.getProperty("service.datasource.username"); 
    String password = environment.getProperty("service.datasource.password"); 
    String driver = environment.getProperty("service.datasource.driverClassName"); 

    try { 
     // Build manually datasource to Config 
     DataSource ds = DataSourceBuilder 
       .create() 
       .username(username) 
       .password(password) 
       .url(dataSourceUrl) 
       .driverClassName(driver) 
       .build(); 

     // Fetch all properties 
     PreparedStatement preparedStatement = ds.getConnection().prepareStatement("SELECT name, value FROM propertyConfig WHERE service = ?"); 
     preparedStatement.setString(1, APP_NAME); 

     ResultSet rs = preparedStatement.executeQuery(); 

     // Populate all properties into the property source 
     while (rs.next()) { 
      String propName = rs.getString("name"); 
      propertySource.put(propName, rs.getString("value")); 
     } 

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

    } catch (Exception e) { 
     throw new Exception("Error fetching properties from ServiceConfig"); 
    } 
} 

そして、これはmain/META-INF/spring-factoriesファイルが作成されなければならなかったです:コードはうまく機能

# Environment Post Processor 
org.springframework.boot.env.EnvironmentPostProcessor=com.blabla.config.ReadDbPropertiesPostProcessor 

、それは私が必要なものをDBから取得します。しかし、私はこれについての情報を記録したいと思います。何か問題が発生した場合、例えばdbがダウンしている場合、エラーをログに記録してアプリを起動するのを止めたいのです。私のアプリは、コンソールではなくロガーを使用するように設定されています。

例外をスローしてエラーを記録しようとしましたが、何かを印刷してもログは決してこの情報を記録しません。

この初期段階でロガーを使用するにはどうすればよいですか?とにかくこれを行うことは可能ですか? EnvironmentPostProcessorを間違って使用していますか?

答えて

1

ここでの問題は、ロギングシステムがスプリングコンテキストが初期化された後にのみ初期化されることです。 logメソッドが呼び出されると、ログシステムは情報の処理方法を知らず、何もしません。

この問題を解決するにはエレガントな方法はありません。あなたは、春管理のログシステムを取り除くか、遅延ログメカニズムを使用します(春が内部的に行うように)。

DeferredLogを使用できるようにするには、コンテキストの初期化後にシステムがログの再生を要求する必要があります。ここで

は、それが達成できたかのいずれかの方法である。この例では

@Component 
public class MyEnvironmentPostProcessor implements 
     EnvironmentPostProcessor, ApplicationListener<ApplicationEvent> { 

    private static final DeferredLog log = new DeferredLog(); 

    @Override 
    public void postProcessEnvironment(
      ConfigurableEnvironment env, SpringApplication app) { 
     log.error("This should be printed"); 
    } 

    @Override 
    public void onApplicationEvent(ApplicationEvent event) { 
     log.replayTo(MyEnvironmentPostProcessor.class); 
    } 
} 

すべてのログメッセージがDeferredLogにキャッシュされます。コンテキストが初期化されると、システムはonApplicationEventと呼ばれます。このメソッドは、キャッシュされたすべてのログイベントを標準のロガーに再生します。

注:ここではApplicationListenerを使用しましたが、すべての便利な方法を使用できます。考えはDeferredLog.replayTo()に一度コンテキストを初期化して呼び出すことです。どこから呼び出すかは関係ありません。

PS:spring.factoriesの位置はsrc/main/resources/META-INFである必要があります。そうでない場合はpostProcessEnvironmentが呼び出されないことがあります。

+0

回答ありがとうございます。非常に有益です...今すぐテストしてみましょう。何かを明確にしたいのですが、どのようにApplicationEventを結び付けますか?これらのイベントを購読/登録する場所はありますか?これはspringbootによって自動的に検出されますか? –

+1

'ApplicationListener'を実装し、あなたのクラスに' @ Component'を付けると、springはそれを自動的に 'ApplicationEvent'に登録します。 –

+0

最後の質問は、私のコードを参照してください...それはキャッチブロックがあり、実行時例外をスローします。例外がスローされた場合、ログは設定されません。このケースをどのように扱うか知っていますか? –

関連する問題