アプリケーションのログバックとしてログバックを使用する場合、それらのほとんどが `logback.xml`ファイルを構成します。さらに、生産環境では、logback.xmlファイルのログレベルを直接変更でき、アプリケーションを再起動せずに有効にすることができます。では、この機能はどのように実装されていますか?
アプリケーションのログバックをログバックとして使用する場合、それらのほとんどがlogback.xmlファイルを構成します。さらに、生産環境では、logback.xmlファイルのログレベルを直接変更でき、アプリケーションを再起動せずに有効にすることができます。
では、この機能はどのように実装されていますか?
I.問題の説明と分析
上記の問題に応じて、最初に実際のケースを投げます。私の個人WebサイトZ+では、すべてのガジェットが動的に追加され、構成ファイルを介して非表示になります。サーバーが1つしかないため、構成ファイルは簡素化され、サーバー上のディレクトリに直接配置されます。
今、私が問題を抱えているとき、私はこのファイルのコンテンツが変更されたときに変更を実現する必要があります、アプリケーションは変更を感知し、ファイルコンテンツをリロードし、アプリケーションの内部キャッシュを更新できます
考える最も簡単な方法の1つは、ファイルが変更されたかどうかを判断するためにポーリングすることです。変更された場合、リロードされてリフレッシュされます。したがって、心配する必要がある主な問題は次のとおりです。
ii。設計と実装
問題が抽象化された後、対応するソリューションはより明確になります
その後、非常に単純な実装が簡単になります:
public class fileuptest {private long lasttime; @test public void testfileupdate(){file file = new file( "/tmp/alarmconfig"); //最初に、ファイルの最後の変更されたタイムスタンプlast = file.lastModified(); //タイミングされたタスクは、ファイルが毎秒変更されたかどうか、つまりlastModifiedの変更スケジューリングScheduleDecutorService = executors.newscheduledthreadpool(1); scheduledexecutorservice.scheduleatfixedrate(new runnable(){@override public void run(){if(file.lastModified()> lasttime){system.out.println( "file update!time:" + file.lastmodified()); lastmodified(); lastmodified(); TimeUnit.seconds); {thread.sleep(1000 * 60); } catch(arturnedexception e){e.printstacktrace(); }}}上記は非常にシンプルで非常に基本的な実装であり、基本的に私たちのニーズを満たすことができます。では、この実装の問題は何ですか?
タイミングタスクの実行中に例外が発生した場合はどうなりますか?
上記のコードにいくつかの変更を加えます
public class fileuptest {private long lasttime; private void tt(){nullpointerexceptionをスローします(); } @test public void testfileupdate(){file file = new file( "/tmp/alarmconfig"); lasttime = file.lastModified(); ScheduleDexecutorservice Scheduleedexecutorservice = executors.newscheduledthreadpool(1); scheduledexecutorservice.scheduleatfixedrate(new runnable(){@override public void run(){if(file.lastmodified()> lasttime){system.out.println( "file update!time:" + file.lastmodified()); lastmodified(); tt(); file.lastmodified(); TimeUnit.seconds); {thread.sleep(1000 * 60 * 10); } catch(arturnedexception e){e.printstacktrace(); }}}実際のテストでは、上記のコードが最初の変更が変更されたときにのみトリガーされたことがわかりましたが、変更は再び役に立たないでしょう。つまり、例外がスローされた場合、タイミングタスクは実行されなくなります。この問題の主な理由は、スケジュールされたexecutorserviceが
ソースコードのコメントスケジュールexecutorserviceのコメントの指示を直接チェックしてください
タスクの実行が例外に遭遇した場合、その後の実行は抑制されます。他に、タスクは実行者のキャンセルまたは終了を介してのみ終了します。
したがって、この姿勢を使用する場合、タスクが例外をスローしないことを確認する必要があります。そうしないと、後でプレイできなくなります。
対応するソリューションは比較的単純です。ただキャッチしてください
iii。 Advanced Edition
前のものは基本的な実装バージョンです。もちろん、Java Circleには、基本的に対応するオープンソースツールを使用することがわかっている多くの一般的なニーズがあります。もちろん、これも例外ではなく、誰もがより多くの属性を持っているのはApacheシリーズであるべきです。
まず第一に、メイブン依存関係
<Dependency> <GroupId> commons-io </groupId> <Artifactid> commons-io </artifactid> <バージョン> 2.6 </version> </dependency>
主に、このツールでfileAlterationObserver、fileAlterationListener、およびfileAlterationMonitorを使用して、関連する要件シナリオを実装します。もちろん、使用するのは非常に簡単なので、説明する方法がわかりません。私のオープンソースプロジェクトのQuick-Alarmの1つからコピーされたコードを見てください。
public class propertiesconflistenerhelper {public static boolean RegisterConfChangelistener(ファイルファイル、機能<ファイル、Map <String、AlarmConfig >> func){try {//ポーリングインターバル5秒間インターバル= timeUnit.seconds.tomillis(5); //リスニングはディレクトリで実行されるため、ファイルのルートディレクトリはここで直接取得されますfile dir = file.getParentFile(); //ファイルオブザーバーを作成してFileAlterationObserver Observer = new FilealterationObserver(dir、filefilterutils.and(filefilterutils.filefilefilter()、filefilterutils.namefilefilter(file.getName())); //ファイルを設定するリスナーオブザーバーを変更します。 fileAlterationMonitor Monitor = new filealterationMonitor(interval、observer); monitor.start(); trueを返します。 } catch(Exception e){log.Error( "Register Properties変更リスナーエラー!e:{}"、e); falseを返します。 }} static final class myfilelistener extends filealterationlisteneradaptor {private function <file、map <string、alarmconfig >> func; public myfilelistener(function <file、map <string、alarmconfig >> func){this.func = func; } @Override public void onfilechange(file file){map <string、alarmconfig> ans = func.apply(file); //ロードが失敗した場合、log log.warn( "propertiesconfig chander!reload ans:{}"、ans)を印刷します。 }}}上記の実装については、いくつかの簡単な説明:
質問、FUNCメソッドが実行されたときに例外がスローされた場合はどうなりますか?
実際のテスト結果は上記と同じです。例外を投げた後、あなたはまだ注意しなければならず、例外を実行しないでください。
したがって、上記の実装ロジックを見て、コアモジュールを直接控除しましょう。
public void run(){while(true){if(this.running){iterator var1 = this.observers.iterator(); while(var1.hasnext()){filealterationobserver observer =(filealterationobserver)var1.next(); Observer.CheckandNotify(); } if(this.running){try {thread.sleep(this.interval); } catch(arternedexception var3){; } 続く; } } 戻る; }}上記から基本的には、実装ロジック全体が最初のタイミングされたタスク方法と異なることは明らかです。ここでは、スレッドとデッドループを直接使用し、睡眠方法を使用して内部で一時停止します。したがって、例外が発生すると、直接投げることに相当し、スレッドがひざまずきます。
補足JDKバージョン
JDK1.7はWatchServiceを提供します。WatchServiceは、ファイルの変更を監視するためにも使用できます。私はそれにさらされたことがなかったので、このことがあることがわかりました。次に、使用関連情報を検索して、非常に簡単であることがわかりました。イベント駆動型であり、効率が高いことを説明するブログ投稿を見ました。簡単な例デモを次に示します
@testpublic void testfileupwather()throws ioexception {//命令、ここのリスナーはディレクトリパス= paths.get( "/tmp"); watchservice watcher = filesystems.getDefault()。newWatchService(); path.register(watcher、entry_modify);新しいスレッド(() - > {try {while(true){watchkey key = watcher.take(); for(watchevent <?> event:key.pollevents()){if(event.kind()== overflow){//イベントが紛失または廃棄されます; } if(!key.reset()){// WatchKey Break; {thread.sleep(1000 * 60 * 10); } catch(arturnedexception e){e.printstacktrace(); }}IV。まとめ
Javaを使用して構成ファイルの変更の監視を実装するには、主に2つのポイントが含まれます
全体として、この実装は比較的簡単です。カスタム実装であろうとCommos-IOに依存しているかどうかにかかわらず、技術的なコストはあまりありませんが、注意すべきことの1つは次のとおりです。
上記の状況を回避するために、実行できる実装は、EventBusの非同期メッセージ通知を使用することです。ファイルが変更されたら、メッセージを送信してから、ファイルコンテンツをリロードする特定の方法に@Subscribeアノテーションを追加します。これは、デカップリングを実現するだけでなく、例外によって引き起こされるサービスの例外を回避します(この実装に興味がある場合は、コメントして説明できます)
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。