응용 프로그램에서 로그 아웃 구성 요소로 로그백을 사용하는 경우 대부분은`logback.xml` 파일을 구성합니다. 또한 생산 환경에서 Logback.xml 파일에서 로그 레벨을 직접 수정할 수 있으며 응용 프로그램을 다시 시작하지 않고도 적용 할 수 있습니다. 그렇다면이 기능은 어떻게 구현됩니까?
애플리케이션에서 로그 아웃 구성 요소로 로그백을 사용하는 경우 대부분 Logback.xml 파일을 구성합니다. 또한 생산 환경에서 Logback.xml 파일에서 로그 레벨을 직접 수정할 수 있으며 응용 프로그램을 다시 시작하지 않고도 적용 할 수 있습니다.
그렇다면이 기능은 어떻게 구현됩니까?
I. 문제 설명 및 분석
위의 문제에 대한 응답으로 먼저 실제 사례를 던지십시오. 내 개인 웹 사이트 Z+에서 모든 가제트는 구성 파일을 통해 동적으로 추가되고 숨겨집니다. 서버가 하나만 있으므로 구성 파일은 단순화되어 서버의 디렉토리에 직접 배치됩니다.
이제 문제가 있으면이 파일의 내용이 변경 될 때 변경 사항을 인식해야합니다. 응용 프로그램은 변경 사항을 감지하고 파일 컨텐츠를 다시로드하며 응용 프로그램의 내부 캐시를 업데이트 할 수 있습니다.
가장 쉬운 방법 중 하나는 파일이 수정되었는지 여부를 결정하기 위해 폴링하는 것입니다. 수정되면 다시로드 및 새로 고침됩니다. 따라서 걱정해야 할 주요 문제는 다음과 같습니다.
II. 설계 및 구현
문제가 추상화되면 해당 솔루션이 더 명확합니다.
그런 다음 매우 간단한 구현이 더 쉽습니다.
공개 클래스 파일 fileUtSTEST {개인 장기 마지막 시간; @test public void testfileupdate () {file file = 새 파일 ( "/tmp/alarmconfig"); // 먼저, 마지막으로 수정 된 마지막 타임 스탬프 마지막 시간 = file.lastModified (); // 시간이 지정된 작업, 파일이 매 초마다 변경되었는지 여부, 즉 마지막으로 변형 된 변경 사항 ScheduleDexecutorService ScheduleDexecutorService = executors.newScheduledThreadPool (1); ScheduleDexecutorService.schedUeAtFixEdrate (new Runnable () {@Override public void run () {if (file.lastModified ()> lasttime) {System.out.println ( "파일 업데이트! time :" + file.lastModified ()); lasttime = file.lastModified ();}}}, 1, 1, TimeUnit.seconds); try {thread.sleep (1000 * 60); } catch (InterruptedException e) {e.printstacktrace (); }}}위의 것은 매우 간단하고 매우 기본적인 구현으로 기본적으로 우리의 요구를 충족시킬 수 있습니다. 그렇다면이 구현의 문제는 무엇입니까?
타이밍 작업을 실행하는 동안 예외가 발생하면 어떻게됩니까?
위의 코드를 수정하십시오
공개 클래스 파일 fileUtSTEST {개인 장기 마지막 시간; private void tt () {throw new nullpointerexception (); } @test public void testFileUpDate () {file file = 새 파일 ( "/tmp/alarmConfig"); 마지막으로 = file.lastModified (); ScheduleDexecutorService ScheduleDexecutorService = executors.newScheduledThreadPool (1); ScheduleDexecutorService.schedUeAtFixEdrate (new Runnable () {@override public void run () {if (file.lastModified ()> lasttime) {system.out.println ( "파일 업데이트! time :" + file.lastmodified ()); lasttime = file.lastModified (); TimeUnit.seconds); try {thread.sleep (1000 * 60 * 10); } catch (InterruptedException e) {e.printstacktrace (); }}}실제 테스트에서, 위의 코드는 첫 번째 수정이 수정 된 경우에만 트리거되었지만 다시 수정은 쓸모가 없습니다. 즉, 예외가 발생하면 타이밍 작업이 더 이상 실행되지 않습니다. 이 문제의 주된 이유는 ScheduleDexecutorService가
ScheduledExecutorService의 소스 코드 주석 지침을 직접 확인하십시오.
작업의 실행이 예외가 발생하면 후속 실행이 억제됩니다.이 작업은 실행자의 취소 또는 종료를 통해서만 종료됩니다.
따라서이 자세를 사용할 때는 작업이 예외를 던지지 않도록해야합니다. 그렇지 않으면 나중에 플레이 할 수 없습니다.
해당 솔루션은 비교적 간단합니다
III. 고급 판
이전은 기본 구현 버전입니다. 물론 Java Circle에는 기본적으로 해당 오픈 소스 도구를 사용할 수있는 많은 일반적인 요구가 있습니다. 물론 이것은 예외는 아니며 모든 사람이 더 많은 속성을 가지고있는 아파치 시리즈 여야합니다.
우선, Maven 의존성
<pectionency> <groupId> Commons-Io </groupId> <artifactid> Commons-Io </artifactid> <bersion> 2.6 </version> </fectionency>
주로이 도구에서 FileTerationObserver, FilealterationListener 및 FilealterationMonitor를 사용하여 관련 요구 사항 시나리오를 구현합니다. 물론 사용하기가 매우 간단하기 때문에 설명하는 방법을 모르겠습니다. 오픈 소스 프로젝트 중 하나에서 복사 된 코드를 살펴보십시오.
public class propertiesconflistenerhelper {public static boolean registerconfchangelistener (파일 파일, 함수 <file, map <string, alarmconfig >> func) {try {// 폴링 간격 5 초 긴 간격 = timeUnit.seconds.tomillis (5); // 청취는 디렉토리에서 수행되므로 파일의 루트 디렉토리는 여기에서 직접 얻습니다. 파일 dir = file.getParentFile (); // filerationObserver isserver를 필터링 할 파일 관찰자를 만듭니다. new FileLealterationObserver (dir, filefilterutils.and (filefilterutils.filefilefilter (), filefilterutils.namefilefilter (file.getname ())); // 파일 설정 청취자 옵저버 .addlistener (new MyFilelistener (func)); filealterationmonitor monitor = New FilealterationMonitor (Interval, Observer); monitor.start (); 진실을 반환하십시오. } catch (예외 e) {log.error ( "레지스터 속성을 변경하십시오. 거짓을 반환합니다. }} 정적 최종 클래스 MyFilEListener 확장 FilealterationListenerAdAptor {private function <file, map <String, alarmConfig >> func; public myfilelistener (function <file, map <string, alarmconfig >> func) {this.func = func; } @override public void onfileChange (파일 파일) {map <string, alarmconfig> ans = func.apply (파일); //로드가 실패하면 log.warn ( "PropertiesConfig 변경! Reload Ans : {}", ans); }}}위 구현의 경우 몇 가지 간단한 설명이 있습니다.
질문, func 메소드가 실행될 때 예외가 발생하면 어떻게됩니까?
실제 테스트 결과는 위와 동일합니다. 예외를 던진 후에도 여전히 조심해야하고 예외를 실행하지 않아야합니다.
위의 구현 로직을 살펴보고 핵심 모듈을 직접 공제하겠습니다.
public void run () {while (true) {if (this.running) {iterator var1 = this.observers.iterator (); while (var1.hasnext ()) {FileTerationObserver Observer = (FileLealterationObserver) var1.next (); Observer.checkandnotify (); } if (this.running) {try {thread.sleep (this.interval); } catch (InterruptedException var3) {; } 계속하다; } } 반품; }}기본적으로 전체 구현 로직이 첫 번째 시간이 정한 작업 방법과 다르다는 것이 명확합니다. 여기서 우리는 스레드와 죽은 루프를 직접 사용하며 수면 방법은 내부적으로 일시 중지하는 데 사용됩니다. 따라서 예외가 발생하면 직접 던지는 것과 같습니다. 실이 무릎을 꿇게됩니다.
보충 JDK 버전
JDK1.7은 파일 변경을 모니터링하는 데 사용될 수있는 WatchService를 제공합니다. 나는 전에 그것에 노출되지 않았으므로 이것이 있다는 것을 알았습니다. 그런 다음 사용 관련 정보를 검색하여 매우 간단하다는 것을 알았습니다. 블로그 게시물이 이벤트 중심이며 효율성이 높다고 설명하는 블로그 게시물을 보았습니다. 다음은 간단한 예제 데모입니다
@testpublic void testfileupwather ()는 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}}} {e.printstacktrace ()); try {thread.sleep (1000 * 60 * 10); } catch (InterruptedException e) {e.printstacktrace (); }}IV. 요약
Java를 사용하여 구성 파일 변경 모니터링을 구현하면 주로 두 가지가 포함됩니다.
전반적 으로이 구현은 비교적 간단합니다. 커스텀 구현이든 Commos-Io에 의존하든 기술 비용이 많지 않지만 주목해야 할 것은 다음과 같습니다.
위의 상황을 피하기 위해 수행 할 수있는 구현은 EventBus의 비동기 메시지 알림을 사용하는 것입니다. 파일이 변경되면 메시지를 보내고 파일 내용을 다시로드하는 특정 방법에 @SubScribe 주석을 추가하십시오. 이것은 디커플링을 실현할뿐만 아니라 예외로 인한 서비스 예외도 피합니다 (이 구현에 관심이있는 경우 댓글을 달고 설명 할 수 있음).
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.