หากคุณใช้ LogBack เป็นองค์ประกอบการออกจากระบบในแอปพลิเคชันของคุณส่วนใหญ่จะกำหนดค่าไฟล์ `logback.xml` นอกจากนี้ในสภาพแวดล้อมการผลิตคุณสามารถแก้ไขระดับบันทึกในไฟล์ logback.xml โดยตรงและอาจมีผลโดยไม่ต้องเริ่มแอปพลิเคชันใหม่ ดังนั้นฟังก์ชั่นนี้ใช้งานได้อย่างไร?
หากคุณใช้ LogBack เป็นองค์ประกอบการออกจากระบบในแอปพลิเคชันของคุณส่วนใหญ่จะกำหนดค่าไฟล์ logback.xml นอกจากนี้ในสภาพแวดล้อมการผลิตคุณสามารถแก้ไขระดับบันทึกในไฟล์ logback.xml โดยตรงและอาจมีผลโดยไม่ต้องเริ่มแอปพลิเคชันใหม่
ดังนั้นฟังก์ชั่นนี้ใช้งานได้อย่างไร?
I. คำอธิบายปัญหาและการวิเคราะห์
ในการตอบสนองต่อปัญหาข้างต้นให้โยนคดีจริงก่อน ในเว็บไซต์ส่วนตัวของฉัน Z+แกดเจ็ตทั้งหมดจะถูกเพิ่มและซ่อนอยู่ผ่านไฟล์การกำหนดค่า เนื่องจากมีเซิร์ฟเวอร์เดียวไฟล์การกำหนดค่าจะง่ายขึ้นและวางโดยตรงในไดเรกทอรีบนเซิร์ฟเวอร์
ตอนนี้เมื่อฉันมีปัญหาฉันต้องตระหนักถึงการเปลี่ยนแปลงเมื่อเนื้อหาของไฟล์นี้เปลี่ยนไปแอปพลิเคชันสามารถรับรู้การเปลี่ยนแปลงโหลดเนื้อหาไฟล์ใหม่และอัปเดตแคชภายในของแอปพลิเคชัน
หนึ่งในวิธีที่ง่ายที่สุดในการคิดคือการสำรวจเพื่อตรวจสอบว่าไฟล์ได้รับการแก้ไขหรือไม่ หากมีการแก้ไขจะมีการโหลดซ้ำและรีเฟรช ดังนั้นปัญหาหลักที่ต้องกังวลมีดังนี้:
ii. การออกแบบและการดำเนินการ
หลังจากปัญหาถูกแยกออกโซลูชันที่เกี่ยวข้องจะชัดเจนขึ้น
การใช้งานที่ง่ายมากนั้นง่ายกว่า:
ชั้นเรียนสาธารณะ FilePtest {ช่วงเวลาส่วนตัวล่าสุด; @Test โมฆะสาธารณะ Public TestFileUpDate () {ไฟล์ไฟล์ = ไฟล์ใหม่ ("/tmp/rearkconfig"); // ก่อนครั้งแรกการประทับเวลาสุดท้ายของไฟล์ล่าสุด = file.lastModified (); // งานที่กำหนดเวลากำหนดว่าไฟล์มีการเปลี่ยนแปลงทุกวินาทีนั่นคือกำหนดว่าการเปลี่ยนแปลงล่าสุด SchedExecutorService ScheduleDexecutorService = Executors.newscheduledThreadPool (1); ScheduleDexecutorService.scheduleatFixedrate (ใหม่ runnable () {@Override โมฆะสาธารณะเรียกใช้ () {ถ้า (file.lastmodified ()> ล่าสุด) {system.out.println ("การอัปเดตไฟล์! Timeunit.seconds); ลอง {thread.sleep (1,000 * 60); } catch (interruptedException e) {e.printStackTrace (); -ข้างต้นเป็นการใช้งานที่ง่ายและพื้นฐานมากซึ่งโดยทั่วไปสามารถตอบสนองความต้องการของเราได้ ดังนั้นปัญหาของการใช้งานนี้คืออะไร?
จะเกิดอะไรขึ้นหากมีข้อยกเว้นเกิดขึ้นระหว่างการดำเนินงานเวลา?
ทำการปรับเปลี่ยนรหัสด้านบน
ชั้นเรียนสาธารณะ FilePtest {ช่วงเวลาส่วนตัวล่าสุด; โมฆะส่วนตัว tt () {โยน nullpointerexception ใหม่ (); } @Test โมฆะสาธารณะ testFileUpDate () {ไฟล์ไฟล์ = ไฟล์ใหม่ ("/tmp/rearkconfig"); ล่าสุด = file.lastModified (); ScheduleDexecutorservice ScheduleDexecutorService = Executors.NewsCheduledThreadPool (1); ScheduleDexecutorService.scheduleatfixedrate (ใหม่ runnable () {@Override โมฆะสาธารณะเรียกใช้ () {ถ้า (file.lastmodified ()> ล่าสุด) {system.out.println ("การอัปเดตไฟล์! Timeunit.seconds); ลอง {thread.sleep (1,000 * 60 * 10); } catch (interruptedException e) {e.printStackTrace (); -ในการทดสอบจริงฉันพบว่ารหัสข้างต้นถูกทริกเกอร์เฉพาะเมื่อมีการแก้ไขการดัดแปลงครั้งแรก แต่การดัดแปลงอีกครั้งจะไร้ประโยชน์อีกครั้ง นั่นคือเมื่อมีการโยนข้อยกเว้นงานเวลาจะไม่ถูกดำเนินการอีกต่อไป เหตุผลหลักสำหรับปัญหานี้คือ ScheduleDexecutorService คือ
ตรวจสอบคำแนะนำความคิดเห็นของซอร์สโค้ดรหัสของ ScheduleDexecutorService โดยตรง
หากการดำเนินการใด ๆ ของงานพบข้อยกเว้นการประหารชีวิตที่ตามมาจะถูกระงับในทางกลับกันงานจะยกเลิกผ่านการยกเลิกหรือการสิ้นสุดของผู้ดำเนินการเท่านั้น
ดังนั้นเมื่อใช้ท่านี้คุณต้องตรวจสอบให้แน่ใจว่างานของคุณไม่ได้ทำข้อยกเว้นมิฉะนั้นคุณจะไม่สามารถเล่นได้ในภายหลัง
โซลูชันที่สอดคล้องกันนั้นค่อนข้างง่ายเพียงแค่จับมันได้
iii. Edition Advanced Edition
ก่อนหน้านี้เป็นเวอร์ชันการใช้งานพื้นฐาน แน่นอนในวงกลม Java มีความต้องการทั่วไปมากมายที่สามารถพบได้ว่าใช้เครื่องมือโอเพ่นซอร์สที่สอดคล้องกัน แน่นอนว่านี่ไม่มีข้อยกเว้นและควรเป็นซีรี่ส์ Apache ที่ทุกคนมีคุณลักษณะมากขึ้น
ก่อนอื่นการพึ่งพา maven
<Ederency> <sdeplyId> Commons-io </groupId> <ratifactId> Commons-io </artifactId> <version> 2.6 </Serve> </Serperency>
ส่วนใหญ่เราใช้ filealterationobserver, filealterationListener และ filealterationMonitor ในเครื่องมือนี้เพื่อใช้สถานการณ์ข้อกำหนดที่เกี่ยวข้อง แน่นอนว่ามันใช้งานง่ายมากดังนั้นฉันไม่รู้วิธีอธิบาย เพียงดูรหัสที่คัดลอกมาจากหนึ่งในโครงการโอเพ่นซอร์สของฉันอย่างรวดเร็ว
Public PropertiesConfliStenerHelper {Public Static Boolean registerConfChangelistener (ไฟล์ไฟล์, ฟังก์ชั่น <ไฟล์, แผนที่ <สตริง, AlarmConfig >> func) {ลอง {// ช่วงเวลาสำรวจ 5 วินาทีช่วงเวลายาว = TimeUnit.seconds.tomillis (5); // เนื่องจากการฟังดำเนินการในไดเรกทอรีรูทไดเรกทอรีของไฟล์จะได้รับโดยตรงที่นี่ไฟล์ dir = file.getParentFile (); // สร้างผู้สังเกตการณ์ไฟล์เพื่อกรอง filealterationobserver observer = ใหม่ filealterationobserver (dir, filefilterutils.and (filefilterutils.fileFileFilter (), filefilterutils.namefilefilter (file.getName ()))); // ตั้งค่าไฟล์เปลี่ยนไฟล์ผู้สังเกตการณ์ AddListener (ใหม่ myFileListener (func)); การตรวจสอบ filealterationMonitor = new FelealterationMonitor (Interval, Observer); monitor.start (); กลับมาจริง; } catch (Exception e) {log.error ("การลงทะเบียนคุณสมบัติเปลี่ยนข้อผิดพลาดของฟัง! e: {}", e); กลับเท็จ; }} คลาสสุดท้ายคงที่ MyFileListener ขยาย FileAlterationListenerAdaptor {ฟังก์ชั่นส่วนตัว <ไฟล์, แผนที่ <สตริง, AlarmConfig >> func; สาธารณะ myFileListener (ฟังก์ชั่น <ไฟล์, แผนที่ <String, AlarmConfig >> func) {this.func = func; } @Override โมฆะสาธารณะ onFileChange (ไฟล์ไฟล์) {แผนที่ <สตริง, AlarmConfig> ans = func.apply (ไฟล์); // หากการโหลดล้มเหลวให้พิมพ์ log.warn ("PropertiesConfig เปลี่ยนไป! โหลดซ้ำ ANS: {}", ANS); -สำหรับการดำเนินการข้างต้นคำอธิบายสั้น ๆ สองสามข้อ:
คำถามจะเกิดอะไรขึ้นหากมีการโยนข้อยกเว้นเมื่อมีการดำเนินการวิธี Func?
ผลการทดสอบจริงเหมือนกับข้างต้น หลังจากโยนข้อยกเว้นคุณยังต้องระวังและไม่เรียกใช้ข้อยกเว้น
ดังนั้นลองมาดูตรรกะการใช้งานด้านบนและหักโมดูลหลักโดยตรง
โมฆะสาธารณะเรียกใช้ () {ในขณะที่ (จริง) {ถ้า (this.running) {iterator var1 = this.observers.iterator (); ในขณะที่ (var1.hasnext ()) {filealterationobserver observer = (filealterationobserver) var1.next (); Observer.CheckandNotify (); } if (this.running) {ลอง {thread.sleep (this.interval); } catch (interruptedException var3) {; } ดำเนินการต่อ; } } กลับ; -โดยพื้นฐานแล้วมันชัดเจนจากข้างต้นว่าตรรกะการใช้งานทั้งหมดนั้นแตกต่างจากวิธีการทำงานที่กำหนดเวลาครั้งแรกของเรา ที่นี่เราใช้เธรดและลูปที่ตายแล้วโดยตรงและใช้วิธีการนอนหลับเพื่อหยุดชั่วคราวภายใน ดังนั้นเมื่อมีข้อยกเว้นเกิดขึ้นมันก็เทียบเท่ากับการขว้างมันโดยตรงและเธรดจะคุกเข่าลง
รุ่น JDK เสริม
JDK1.7 ให้บริการ WatchService ซึ่งสามารถใช้ในการตรวจสอบการเปลี่ยนแปลงไฟล์ ฉันไม่เคยสัมผัสมาก่อนดังนั้นฉันจึงพบว่ามีสิ่งนี้ จากนั้นฉันค้นหาข้อมูลที่เกี่ยวข้องกับการใช้งานและพบว่ามันค่อนข้างง่าย ฉันเห็นโพสต์บล็อกที่อธิบายว่าเป็นเหตุการณ์ที่ขับเคลื่อนด้วยและมีประสิทธิภาพสูงขึ้น นี่คือตัวอย่างง่ายๆตัวอย่าง
@TestPublic เป็นโมฆะ testFilePwather () พ่น IOException {// คำแนะนำผู้ฟังที่นี่จะต้องเป็นเส้นทางเส้นทางไดเรกทอรี = paths.get ("/tmp"); watchService watcher = filesystems.getDefault (). newWatchService (); path.register (Watcher, entry_modify); เธรดใหม่ (() -> {ลอง {ในขณะที่ (จริง) {watchkey key = watcher.take (); สำหรับ (watchEvent <?> เหตุการณ์: key.pollevents ()) {ถ้า (event.kind () == ล้น) {// เหตุการณ์อาจสูญหาย if (! key.reset ()) {// รีเซ็ต Watchkey Break; ลอง {thread.sleep (1,000 * 60 * 10); } catch (interruptedException e) {e.printStackTrace (); -iv. สรุป
การใช้ Java เพื่อใช้การตรวจสอบการเปลี่ยนแปลงไฟล์การกำหนดค่าส่วนใหญ่เกี่ยวข้องกับสองคะแนน
โดยรวมแล้วการใช้งานนี้ค่อนข้างง่าย ไม่ว่าจะเป็นการใช้งานที่กำหนดเองหรือพึ่งพา commos-io มันไม่มีค่าใช้จ่ายทางเทคนิคมากนัก แต่สิ่งหนึ่งที่ควรทราบคือ:
เพื่อหลีกเลี่ยงสถานการณ์ข้างต้นการใช้งานที่สามารถทำได้คือใช้การแจ้งเตือนข้อความแบบอะซิงโครนัสของ EventBus หลังจากการเปลี่ยนแปลงไฟล์ส่งข้อความจากนั้นเพิ่มคำอธิบายประกอบ @Subsribe ลงในวิธีการเฉพาะของการโหลดเนื้อหาไฟล์ใหม่ สิ่งนี้ไม่เพียง แต่ตระหนักถึงการ decoupling เท่านั้น แต่ยังหลีกเลี่ยงข้อยกเว้นบริการที่เกิดจากข้อยกเว้น (หากคุณสนใจในการใช้งานนี้คุณสามารถแสดงความคิดเห็นและอธิบายได้)
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น