ทำไมต้องพูดถึงการจัดการข้อยกเว้นในโครงการ J2EE? บางทีผู้เริ่มต้น Java หลายคนอาจต้องการพูดว่า "ไม่ได้รับการจัดการเพียงแค่ลอง .... จับ ... ในที่สุดทุกคนก็รู้เรื่องนี้!" ผู้เขียนก็คิดแบบนี้เมื่อเขาเรียนรู้ Java เป็นครั้งแรก จะกำหนดคลาสข้อยกเว้นที่สอดคล้องกันในโครงการ J2EE หลายชั้นได้อย่างไร? วิธีจัดการข้อยกเว้นในแต่ละเลเยอร์ในโครงการ? ข้อยกเว้นถูกโยนเมื่อไหร่? ข้อยกเว้นถูกบันทึกเมื่อใด จะบันทึกข้อยกเว้นได้อย่างไร? เมื่อใดที่ฉันควรแปลงข้อยกเว้นที่ตรวจสอบเป็นข้อยกเว้นที่ไม่ได้ตรวจสอบและเมื่อใดที่ฉันควรแปลงข้อยกเว้นที่ไม่ได้ตรวจสอบเป็นข้อยกเว้นที่ตรวจสอบได้เมื่อใด ควรนำเสนอข้อยกเว้นไปยังหน้าส่วนหน้าหรือไม่? วิธีการออกแบบกรอบข้อยกเว้น? ปัญหาเหล่านี้จะกล่าวถึงในบทความนี้
1. การจัดการข้อยกเว้น Java
ในภาษาการเขียนโปรแกรมขั้นตอนเราสามารถกำหนดได้ว่าวิธีการดังกล่าวจะดำเนินการตามปกติหรือไม่โดยการคืนค่า ตัวอย่างเช่นในโปรแกรมที่เขียนด้วยภาษา C หากวิธีการถูกดำเนินการอย่างถูกต้องมันจะส่งคืน 1 ถ้ามีการดำเนินการข้อผิดพลาดมันจะส่งคืน 0 ในแอปพลิเคชันที่พัฒนาโดย VB หรือ Delphi เมื่อเกิดข้อผิดพลาดเราจะปรากฏกล่องข้อความถึงผู้ใช้
เราไม่สามารถรับรายละเอียดข้อผิดพลาดผ่านค่าส่งคืนของวิธีการ อาจเป็นเพราะวิธีการเขียนโดยโปรแกรมเมอร์ที่แตกต่างกันเมื่อเกิดข้อผิดพลาดประเภทเดียวกันในวิธีการที่แตกต่างกันผลลัพธ์ที่ส่งคืนและข้อมูลข้อผิดพลาดจะไม่สอดคล้องกัน
ดังนั้นภาษา Java จึงใช้กลไกการจัดการข้อยกเว้นแบบครบวงจร
ข้อยกเว้นคืออะไร? ข้อผิดพลาดที่จับได้และประมวลผลได้เกิดขึ้นที่รันไทม์
ในภาษา Java ข้อยกเว้นคือคลาสหลักของข้อยกเว้นทั้งหมด ข้อยกเว้นใด ๆ จะถูกขยายไปยังคลาสข้อยกเว้น ข้อยกเว้นเทียบเท่ากับประเภทข้อผิดพลาด หากคุณต้องการกำหนดประเภทข้อผิดพลาดใหม่ให้ขยาย subclass ข้อยกเว้นใหม่ ข้อได้เปรียบของการใช้ข้อยกเว้นคือสามารถค้นหาตำแหน่งซอร์สโค้ดได้อย่างถูกต้องซึ่งทำให้เกิดข้อผิดพลาดของโปรแกรมและรับข้อมูลข้อผิดพลาดโดยละเอียด
การจัดการข้อยกเว้น Java ถูกนำไปใช้ผ่านคำหลักห้าคำลองจับจับโยนโยนในที่สุด โครงสร้างการจัดการข้อยกเว้นเฉพาะถูกนำมาใช้โดยการลอง… .Catch …. บล็อกสุดท้าย TRY Block Stores คำสั่ง Java ที่อาจมีข้อยกเว้น การจับใช้เพื่อจับการเกิดข้อยกเว้นและจัดการกับข้อยกเว้น บล็อกสุดท้ายถูกใช้เพื่อล้างทรัพยากรที่ไม่ได้รับผลกระทบในโปรแกรม บล็อกสุดท้ายจะถูกเรียกใช้งานเสมอหากรหัสที่ไม่ได้จัดการวิธีการกลับบล็อกลองกลับมา
รหัสการจัดการข้อยกเว้นทั่วไป
สตริงสาธารณะ getPassword (string userId) พ่น dataAccessException {string sql = "เลือกรหัสผ่านจาก userInfo โดยที่ userId = '" +userId +"'"; รหัสผ่านสตริง = null; การเชื่อมต่อ con = null; คำสั่ง s = null; resultet rs = null; ในขณะที่ (rs.next ()) {password = rs.getString (1);} rs.close (); s.close ();} catch (sqlexception ex) {โยน dataaccessexception ใหม่ (ex);} ในที่สุด {ลอง {ถ้า (con! = null) {con.close () ล้มเหลว! ", sqlex);}} ส่งคืนรหัสผ่าน;} จะเห็นได้ว่าข้อดีของกลไกการจัดการข้อยกเว้นของ Java:
ข้อผิดพลาดถูกจัดประเภทอย่างสม่ำเสมอและนำไปใช้โดยขยายคลาสข้อยกเว้นหรือคลาสย่อย สิ่งนี้หลีกเลี่ยงได้ว่าข้อผิดพลาดเดียวกันอาจมีข้อความแสดงข้อผิดพลาดที่แตกต่างกันในวิธีการต่าง ๆ เมื่อเกิดข้อผิดพลาดเดียวกันในวิธีการต่าง ๆ คุณจะต้องโยนวัตถุข้อยกเว้นเดียวกันเท่านั้น
รับข้อมูลข้อผิดพลาดโดยละเอียดเพิ่มเติม ผ่านคลาสข้อยกเว้นข้อมูลข้อผิดพลาดสามารถให้กับข้อยกเว้นที่มีรายละเอียดมากขึ้นและมีประโยชน์มากขึ้นสำหรับผู้ใช้ ง่ายสำหรับผู้ใช้ในการติดตามและโปรแกรมการดีบัก
แยกผลลัพธ์การส่งคืนที่ถูกต้องจากข้อความแสดงข้อผิดพลาด ลดความซับซ้อนของโปรแกรม ผู้โทรไม่จำเป็นต้องรู้เพิ่มเติมเกี่ยวกับผลการส่งคืน
บังคับให้ผู้โทรจัดการข้อยกเว้นเพื่อปรับปรุงคุณภาพของโปรแกรม เมื่อการประกาศวิธีการจำเป็นต้องโยนข้อยกเว้นผู้โทรจะต้องใช้การลอง .... Catch Block เพื่อจัดการข้อยกเว้น แน่นอนว่าผู้โทรยังสามารถอนุญาตให้มีข้อยกเว้นที่จะถูกโยนไปยังระดับบน
2. ตรวจสอบข้อยกเว้นหรือข้อยกเว้นที่ไม่ได้ตรวจสอบ?
ข้อยกเว้น Java แบ่งออกเป็นสองประเภท: ตรวจสอบข้อยกเว้นและข้อยกเว้นที่ไม่ได้ตรวจสอบ ข้อยกเว้นทั้งหมดที่สืบทอด java.lang.exception เป็นของข้อยกเว้นที่ตรวจสอบ ข้อยกเว้นทั้งหมดที่สืบทอด java.lang.runtimeException เป็นของข้อยกเว้นที่ไม่ถูกตรวจสอบ
เมื่อวิธีการเรียกวิธีการที่อาจส่งข้อยกเว้นที่ตรวจสอบแล้วข้อยกเว้นจะต้องถูกจับและประมวลผลหรือถูกโยนอีกครั้งผ่านการลอง ... Catch Block
ลองมาดูการประกาศวิธีการ createstatement () ของอินเตอร์เฟสการเชื่อมต่อ
คำแถลงสาธารณะ createStatement () พ่น Sqlexception; Sqlexception เป็นข้อยกเว้นที่ตรวจสอบแล้ว เมื่อมีการเรียกใช้วิธีการสร้างสรรค์ Java บังคับให้ผู้โทรจับ Sqlexception สตริงสาธารณะ getPassword (string userId) {ลอง {... คำสั่ง s = con.createstatement (); ... catch (sqlexception sqlex) {... } ... } หรือ
สตริงสาธารณะ getPassword (string userId) พ่น sqlexception {คำสั่ง s = con.createstatement ();} (แน่นอนว่าทรัพยากรเช่นการเชื่อมต่อและการเชื่อมโยงต้องปิดในเวลานี่เป็นเพียงเพื่อแสดงให้เห็นว่าข้อยกเว้นที่ตรวจสอบจะต้องบังคับให้ผู้โทรจับหรือโยนต่อไป)
ข้อยกเว้นที่ไม่ได้ตรวจสอบเรียกอีกอย่างว่าข้อยกเว้นรันไทม์ โดยปกติแล้ว RuntimeException ระบุข้อยกเว้นที่ผู้ใช้ไม่สามารถกู้คืนได้เช่นการไม่สามารถรับการเชื่อมต่อฐานข้อมูลการไม่สามารถเปิดไฟล์ได้ ฯลฯ แม้ว่าผู้ใช้จะสามารถตรวจสอบข้อยกเว้นที่ไม่ได้ตรวจสอบเช่นการจัดการข้อยกเว้นที่ตรวจสอบ แต่ถ้าผู้โทรไม่ได้รับข้อยกเว้นที่ไม่ได้ตรวจสอบคอมไพเลอร์จะไม่บังคับให้คุณทำเช่นนั้น
ตัวอย่างเช่นรหัสที่แปลงอักขระเป็นค่าจำนวนเต็มมีดังนี้:
String str = "123"; ค่า int = integer.parseint (str);
ลายเซ็นวิธี ParseInt คือ:
Public Staticint ParseInt (String S) พ่น NumberFormatexception
เมื่อพารามิเตอร์ที่ผ่านไม่สามารถแปลงเป็นจำนวนเต็มที่เกี่ยวข้องได้จะมีการโยน numberFormatexception เนื่องจาก NumberFormatexception ขยายไปถึง RuntimeException จึงเป็นข้อยกเว้นที่ไม่ได้ตรวจสอบ ดังนั้นจึงไม่จำเป็นต้องลอง ... จับเมื่อโทรหาวิธี ParseInt
เพราะ Java ไม่ได้บังคับให้ผู้โทรจับหรือโยนข้อยกเว้นที่ไม่ได้ตรวจสอบ ดังนั้นโปรแกรมเมอร์จึงชอบที่จะโยนข้อยกเว้นที่ไม่ได้ตรวจสอบเสมอ หรือเมื่อต้องการคลาสข้อยกเว้นใหม่มันจะถูกใช้เพื่อขยายจาก RuntimeException เสมอ เมื่อคุณเรียกวิธีการเหล่านี้หากไม่มีบล็อกจับที่สอดคล้องกันคอมไพเลอร์จะช่วยให้คุณผ่านได้เสมอและคุณไม่จำเป็นต้องเข้าใจว่าวิธีนี้จะมีข้อยกเว้นใดบ้าง ดูเหมือนว่านี่เป็นความคิดที่ดี แต่การทำเช่นนั้นอยู่ห่างจากความตั้งใจที่แท้จริงของการจัดการข้อยกเว้น Java และมันทำให้เข้าใจผิดกับโปรแกรมเมอร์ที่เรียกชั้นเรียนของคุณเพราะผู้โทรไม่มีความคิดภายใต้สถานการณ์ที่จำเป็นในการจัดการข้อยกเว้น ข้อยกเว้นที่ตรวจสอบสามารถบอกผู้โทรได้อย่างชัดเจนว่าต้องจัดการข้อยกเว้นเมื่อโทรเข้าชั้นเรียนนี้ หากผู้โทรไม่ประมวลผลคอมไพเลอร์จะแจ้งและไม่สามารถรวบรวมและผ่านได้ แน่นอนว่าจะจัดการกับผู้โทรได้อย่างไร
ดังนั้น Java แนะนำให้ผู้คนควรใช้ข้อยกเว้นที่ตรวจสอบในรหัสแอปพลิเคชันของพวกเขา เช่นเดียวกับที่เรากล่าวถึงในส่วนก่อนหน้าว่าข้อได้เปรียบของการใช้ข้อยกเว้นคือมันสามารถบังคับให้ผู้โทรจัดการข้อยกเว้นที่จะสร้างขึ้น มีการใช้ข้อยกเว้นที่ตรวจสอบเป็นมาตรฐานในเอกสาร Java อย่างเป็นทางการเช่น "Java Tutorial"
การใช้ข้อยกเว้นที่ตรวจสอบควรหมายความว่ามีหลายครั้งที่ลอง ... จับในรหัสของคุณ หลังจากเขียนและจัดการมากขึ้นลองมากขึ้น ... จับบล็อกในที่สุดหลายคนก็เริ่มสงสัยว่าควรใช้ข้อยกเว้นที่ตรวจสอบเป็นมาตรฐานหรือไม่
แม้แต่ Bruce Eckel ผู้แต่งเรื่อง "Thinking in Java" ที่มีชื่อเสียงก็เปลี่ยนความคิดในอดีตของเขา Bruce Eckel ยังสนับสนุนการใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบเป็นการใช้งานมาตรฐาน และเผยแพร่บทความเพื่อทดสอบว่าควรลบข้อยกเว้นที่ตรวจสอบจาก Java หรือไม่ Bruce Eckel: "เมื่อมีรหัสจำนวนเล็กน้อยข้อยกเว้นที่ตรวจสอบนั้นไม่ต้องสงสัยเลยว่าเป็นแนวคิดที่สง่างามมากและช่วยหลีกเลี่ยงข้อผิดพลาดที่อาจเกิดขึ้นได้ แต่ประสบการณ์แสดงให้เห็นว่าผลลัพธ์นั้นตรงกันข้ามกับรหัสจำนวนมาก"
สำหรับการอภิปรายโดยละเอียดเกี่ยวกับข้อยกเว้นที่ตรวจสอบและข้อยกเว้นที่ไม่ได้ตรวจสอบโปรดดูที่
Java Tutorial http://java.sun.com/docs/books/Tutorial/essential/exceptions/runtime.html
การใช้ข้อยกเว้นที่ตรวจสอบอาจทำให้เกิดปัญหามากมาย
ตรวจสอบข้อยกเว้นทำให้ลองมากเกินไป ... จับรหัส
อาจมีข้อยกเว้นที่ตรวจสอบมากมายที่ไม่สามารถจัดการได้อย่างสมเหตุสมผลโดยนักพัฒนาเช่น Sqlexception แต่นักพัฒนาต้องลอง ... จับได้ เมื่อนักพัฒนาไม่สามารถจัดการข้อยกเว้นที่ตรวจสอบได้อย่างถูกต้องพวกเขามักจะพิมพ์ข้อยกเว้นหรือไม่ทำอะไรเลย โดยเฉพาะอย่างยิ่งสำหรับสามเณรข้อยกเว้นที่ตรวจสอบมากเกินไปทำให้เขารู้สึกสูญเสีย
ลอง {…คำสั่ง s = con.createstement (); … catch (sqlexception sqlex) {sqlex.printstacktrace ();} หรือ
ลอง {... คำสั่ง s = con.createStatement (); ... catch (sqlexception sqlex) {// ไม่ทำอะไรเลย} ข้อยกเว้นที่ตรวจสอบทำให้เกิดการสร้างรหัสที่เข้าใจยากจำนวนมาก
เมื่อนักพัฒนาต้องจับข้อยกเว้นที่ตรวจสอบว่าพวกเขาไม่สามารถจัดการได้อย่างถูกต้องพวกเขามักจะบรรจุใหม่เป็นข้อยกเว้นใหม่แล้วโยน การทำเช่นนั้นไม่ได้นำประโยชน์ใด ๆ มาสู่โปรแกรม มันทำให้รหัสยากที่จะเข้าใจในภายหลัง
เช่นเดียวกับที่เราใช้รหัส JDBC มีการลองมากมาย…จับได้ รหัสที่มีประโยชน์จริงๆรวมอยู่ในลอง ... จับได้ ทำให้ยากที่จะเข้าใจวิธีนี้
ข้อยกเว้นที่ตรวจสอบทำให้ข้อยกเว้นถูกห่อหุ้มอย่างต่อเนื่องในข้อยกเว้นคลาสอื่นและจากนั้นโยนทิ้งไป
โมฆะสาธารณะเมธอด () พ่นข้อยกเว้น {… .. throw ใหม่ exceptiona ();} โมฆะสาธารณะ methodb () พ่นข้อยกเว้น {ลอง {methoda (); …} catch (exceptiona ex) {โยนข้อยกเว้นใหม่ (ex);}} โมฆะสาธารณะวิธีการ เราเห็นว่าข้อยกเว้นถูกห่อหุ้มและการโยนเลเยอร์อีกครั้งโดยเลเยอร์
ตรวจสอบข้อยกเว้นทำให้เกิดการทุจริตวิธีการเชื่อมต่อ
มีการใช้วิธีการในอินเทอร์เฟซหลายคลาส เมื่อมีการเพิ่มข้อยกเว้นที่ตรวจสอบเพิ่มเติมลงในวิธีนี้รหัสทั้งหมดที่เรียกใช้วิธีนี้จะต้องมีการแก้ไข
จะเห็นได้ว่าปัญหาข้างต้นถูกบังคับให้จับและดำเนินการเนื่องจากผู้โทรไม่สามารถจัดการกับข้อยกเว้นที่ตรวจสอบได้อย่างถูกต้องและถูกบังคับให้ห่อหุ้มแล้วโยนอีกครั้ง สิ่งนี้ไม่สะดวกมากและไม่ได้นำประโยชน์ใด ๆ ในกรณีนี้มักจะใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบ
ข้อยกเว้นที่ตรวจสอบไม่ได้ทั้งหมด ข้อยกเว้นที่ตรวจสอบนั้นใช้งานง่ายกว่าค่าการส่งคืนข้อผิดพลาดของการเขียนโปรแกรมแบบดั้งเดิม มันจะดีกว่ามากเพื่อให้แน่ใจว่ามีการจัดการข้อยกเว้นอย่างถูกต้องผ่านคอมไพเลอร์มากกว่าที่จะตัดสินด้วยค่าผลตอบแทน
หากข้อยกเว้นเป็นอันตรายถึงชีวิตก็จะไม่สามารถกู้คืนได้ หรือผู้โทรไปจับมันโดยไม่มีประโยชน์ใด ๆ ให้ใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบ
หากผู้โทรสามารถกู้คืนได้อย่างถูกต้องและสามารถจัดการได้อย่างถูกต้องให้ใช้ข้อยกเว้นที่ตรวจสอบ
เมื่อใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบข้อยกเว้นที่ไม่ได้ตรวจสอบที่วิธีการอาจจะต้องอธิบายในรายละเอียดในการประกาศวิธีการ ผู้โทรตัดสินใจว่าจะจับข้อยกเว้นที่ไม่ได้ตรวจสอบหรือไม่
เมื่อใดควรใช้ข้อยกเว้นที่ตรวจสอบและเมื่อใดที่จะใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบ? ไม่มีมาตรฐานสัมบูรณ์ แต่ฉันสามารถให้คำแนะนำได้บ้าง
เมื่อผู้โทรทุกคนต้องจัดการกับข้อยกเว้นนี้ผู้โทรสามารถได้รับอนุญาตให้ลองดำเนินการอีกครั้ง หรือข้อยกเว้นเทียบเท่ากับค่าผลตอบแทนที่สองของวิธีการ ใช้ข้อยกเว้นที่ตรวจสอบแล้ว
ข้อยกเว้นนี้สามารถจัดการได้โดยผู้โทรขั้นสูงอีกสองสามคนเท่านั้นและผู้โทรธรรมดาไม่สามารถจัดการได้อย่างถูกต้อง ใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบ ผู้โทรที่มีความสามารถในการประมวลผลสามารถดำเนินการประมวลผลขั้นสูงได้ แต่โดยทั่วไปแล้วผู้โทรไม่สามารถจัดการได้เลย
ข้อยกเว้นนี้เป็นข้อผิดพลาดที่ร้ายแรงมากเช่นข้อผิดพลาดในการเชื่อมต่อฐานข้อมูลไฟล์ล้มเหลวในการเปิด ฯลฯ หรือข้อยกเว้นเหล่านี้เกี่ยวข้องกับสภาพแวดล้อมภายนอก เป็นไปไม่ได้ที่จะแก้ปัญหาการลองใหม่ ใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบ เพราะเมื่อข้อยกเว้นนี้เกิดขึ้นผู้โทรไม่สามารถจัดการได้เลย
หากไม่แน่ใจให้ใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบ และอธิบายรายละเอียดข้อยกเว้นที่อาจถูกโยนทิ้งเพื่อให้ผู้โทรตัดสินใจว่าจะจัดการกับมันหรือไม่
3. ออกแบบคลาสข้อยกเว้นใหม่
เมื่อออกแบบคลาสข้อยกเว้นใหม่ก่อนอื่นให้ตรวจสอบว่าจำเป็นต้องใช้คลาสข้อยกเว้นนี้จริงหรือไม่ โดยทั่วไปแล้วพยายามอย่าออกแบบคลาสข้อยกเว้นใหม่ ๆ แต่ลองใช้คลาสยกเว้นที่มีอยู่แล้วใน Java
ชอบ
orderalargumentException, unsupportedoperationexception
ไม่ว่าจะเป็นข้อยกเว้นใหม่ข้อยกเว้น chekced หรือข้อยกเว้นที่ไม่ได้ตรวจสอบ เราทุกคนต้องพิจารณาปัญหาการทำรังของข้อยกเว้น
โมฆะโมฆะสาธารณะ () พ่นข้อยกเว้น {… .. ถึงข้อยกเว้นใหม่ ();} วิธีการการประกาศวิธีการทำให้เกิดข้อยกเว้น
โมฆะสาธารณะ Methodb () พ่นข้อยกเว้น
การประกาศ MethodB จะโยนข้อยกเว้น เมื่อวิธีการที่เรียกว่าในเมธอดบ์จะไม่สามารถประมวลผล exceptiona ได้ดังนั้นข้อยกเว้นควรจะโยนต่อไป วิธีหนึ่งคือการทำให้การประกาศ MethodB โยนข้อยกเว้น แต่สิ่งนี้ได้เปลี่ยนลายเซ็นวิธีการของ MethodB เมื่อมีการเปลี่ยนแปลงแล้ววิธีการทั้งหมดที่เรียกเมธอดบีจะต้องเปลี่ยน
อีกวิธีหนึ่งคือการห่อหุ้ม Exceptiona ลงในข้อยกเว้นแล้วโยนมัน หากเราไม่ได้สรุปข้อยกเว้นในข้อยกเว้นเราจะสูญเสียข้อมูลข้อยกเว้นรูททำให้เป็นไปไม่ได้ที่จะติดตามแหล่งที่มาดั้งเดิมของข้อยกเว้น
โมฆะสาธารณะ Methodb () พ่นข้อยกเว้น {ลอง {methoda (); ... } catch (exceptiona ex) {โยนข้อยกเว้นใหม่ (ex);}} เช่นเดียวกับในรหัสข้างต้น ExceptionB ทำรังยกเว้น เราจะเรียกว่า "ทำให้เกิดข้อยกเว้น" ในขณะนี้เนื่องจากข้อยกเว้นทำให้เกิดข้อยกเว้น สิ่งนี้จะป้องกันไม่ให้ข้อมูลข้อยกเว้นหายไป
ดังนั้นเมื่อเรากำหนดคลาสข้อยกเว้นใหม่เราต้องจัดทำคอนสตรัคเตอร์ที่สามารถมีข้อยกเว้นซ้อนกันได้ และมีสมาชิกส่วนตัวที่จะบันทึก "ข้อยกเว้น" นี้
ข้อยกเว้นคลาสสาธารณะขยายข้อยกเว้น {สาเหตุที่โยนได้ส่วนตัว; ข้อยกเว้นสาธารณะ (สตริงผงชูรส, Ex Ex) {super (msg); this.cause = ex;} public ExceptionB (String msg) {super (msg);} public ExceptionB แน่นอนเมื่อเราเรียกวิธี PrintStackTrace เราต้องพิมพ์ข้อมูล "ข้อยกเว้น" ทั้งหมดในเวลาเดียวกัน ดังนั้นเราจำเป็นต้องแทนที่วิธี PrintStackTrace เพื่อแสดงร่องรอยสแต็กข้อยกเว้นทั้งหมด รวมถึงร่องรอยสแต็กของข้อยกเว้นซ้อนกัน
โมฆะสาธารณะ printStackTrace (printstrean ps) {ถ้า (สาเหตุ == null) {super.printstacktrace (ps);} else {ps.println (นี่); ace.printstacktrace (ps);}}} การสนับสนุนที่สมบูรณ์สำหรับซอร์สโค้ดคลาสยกเว้นที่ตรวจสอบแล้วมีดังนี้ เรียกมันว่า nestedexception ที่นี่ในขณะนี้
Public NestedException ขยายข้อยกเว้น {สาเหตุที่น่าจดจำส่วนตัว; NestedException สาธารณะ (String msg) {super (msg);} public nestedexception (String msg, ex ex) {super (msg); this.cuse = ex; super.getMessage (); สาเหตุที่โยนได้ = getCause (); ถ้า (สาเหตุ! = null) {message = message + "; ข้อยกเว้นที่ซ้อนกันคือ" + สาเหตุ;} ข้อความกลับ; null) {super.printstacktrace (ps);} else {ps.println (นี่); getcause (). printstacktrace (ps);}} โมฆะสาธารณะ printstacktrace (printwrite pw) {if (getCause () == null) {super.printstacktrace (pw);} else {pw.println (นี่); getcause (). printstacktrace (pw);}} โมฆะสาธารณะ printstacktrace () {printstacktrace (system.error);}}}}}}}}}}นอกจากนี้คุณต้องออกแบบคลาสข้อยกเว้นที่ไม่ได้ตรวจสอบดังกล่าวข้างต้น มันแค่ต้องสืบทอด RuntimeException
4. วิธีบันทึกข้อยกเว้น
ในฐานะที่เป็นระบบแอปพลิเคชันขนาดใหญ่จำเป็นต้องมีไฟล์บันทึกเพื่อบันทึกการทำงานของระบบเพื่ออำนวยความสะดวกในการติดตามและบันทึกการทำงานของระบบ ข้อยกเว้นที่เกิดขึ้นในระบบจำเป็นต้องบันทึกตามธรรมชาติในระบบบันทึก
สตริงสาธารณะ getPassword (string userId) พ่น nosuchuserexception {userInfo user = userDao.QueryUserById (userId); ถ้า (user == null) {logger.info ("ข้อมูลผู้ใช้ไม่สามารถพบ userId =" userId); user.getPassword ();}} โมฆะสาธารณะ senduserPassword (string userId) โยนข้อยกเว้น {userInfo user = null; ลอง {user = getPassword (userId); // … .. sendmail (); //} จับ (nosuchuserexception ex) เราสังเกตเห็นว่าข้อผิดพลาดถูกบันทึกสองครั้ง ที่ต้นกำเนิดของข้อผิดพลาดเราจะบันทึกเฉพาะระดับข้อมูล ในวิธี SenduserPassword เรายังบันทึกข้อมูลข้อยกเว้นทั้งหมด
ผู้เขียนได้เห็นหลายโครงการบันทึกข้อยกเว้นด้วยวิธีนี้โดยไม่คำนึงถึง 3721 และข้อยกเว้นทั้งหมดจะถูกบันทึกเมื่อพบข้อยกเว้นเท่านั้น หากข้อยกเว้นถูกห่อหุ้มอย่างต่อเนื่องและโยนหลายครั้งมันจะถูกบันทึกหลายครั้ง ดังนั้นควรบันทึกข้อยกเว้นที่ไหน?
ควรบันทึกข้อยกเว้นที่ตำแหน่งเริ่มต้น!
หากคุณต้องจับข้อยกเว้นที่ไม่สามารถจัดการได้อย่างถูกต้องเพียงแค่ห่อหุ้มไว้ในข้อยกเว้นอื่นแล้วโยนมันขึ้น ไม่จำเป็นต้องบันทึกข้อยกเว้นที่บันทึกไว้อีกครั้ง
หากมีข้อยกเว้นถูกจับได้ข้อยกเว้นนี้สามารถจัดการได้ ไม่จำเป็นต้องบันทึกข้อยกเว้น
วันที่สาธารณะ getDate (string str) {วันที่ applidate = null; รูปแบบ simpledateFormat = new SimpledateFormat ("mm/dd/yyyy"); ลอง {applidate = format.parse (appledatestr);} catch (parseexception ex) {// ทำไม เมื่อจับข้อยกเว้นที่ไม่ได้บันทึกไว้หรือข้อยกเว้นของระบบภายนอกควรบันทึกรายละเอียดของข้อยกเว้น
ลอง {… string sql =” เลือก * จาก userinfo”; คำสั่ง s = con.createstatement (); … catch (sqlexception sqlex) {logger.error ("ข้อผิดพลาดในการดำเนินการ SQL"+SQL+SQLEX);} สถานที่บันทึกข้อมูลข้อยกเว้นและวิธีการบันทึกข้อมูลข้อยกเว้นอาจเป็นเรื่องของความคิดเห็น บางระบบยังให้ข้อยกเว้นบันทึกคลาสข้อยกเว้น เมื่อมีการสร้างวัตถุข้อยกเว้นใหม่ข้อมูลข้อยกเว้นจะถูกบันทึกโดยอัตโนมัติ
Public Class BusinessException ขยายข้อยกเว้น {โมฆะส่วนตัว logtrace () {StringBuffer buffer = new StringBuffer (); buffer.append ("ข้อผิดพลาดทางธุรกิจในชั้นเรียน:"); buffer.append (getClassName ()); Buffer.Append (","); "); buffer.append (this.getMessage ()); logger.error (buffer.toString ());} ธุรกิจสาธารณะ (String s) {super (s); Race ();} สิ่งนี้น่าจะวิเศษมาก แต่มันจะนำไปสู่ข้อยกเว้นที่ถูกบันทึกซ้ำ ๆ อย่างหลีกเลี่ยงไม่ได้ ในขณะเดียวกันก็ละเมิด "หลักการกระจายความรับผิดชอบของชั้นเรียน" และเป็นการออกแบบที่ไม่ดี ข้อยกเว้นการบันทึกไม่ได้อยู่ในพฤติกรรมของคลาสข้อยกเว้นและการบันทึกข้อยกเว้นควรทำโดยระบบบันทึกพิเศษ และข้อมูลการบันทึกที่ผิดปกติมีการเปลี่ยนแปลงอยู่ตลอดเวลา เรากำลังบันทึกข้อยกเว้นที่ควรให้ข้อมูลที่สมบูรณ์ยิ่งขึ้น สิ่งนี้ช่วยให้เราค้นหาสาเหตุของปัญหาตามข้อมูลข้อยกเว้นเพื่อแก้ปัญหา
แม้ว่าเราจะได้พูดคุยกันมากมายเกี่ยวกับการบันทึกข้อยกเว้น แต่การเน้นไปที่สิ่งเหล่านี้มากเกินไปทำให้นักพัฒนาสับสนมากขึ้น วิธีหนึ่งที่ดีคือการจัดทำกรอบการจัดการข้อยกเว้นสำหรับระบบ เฟรมเวิร์กตัดสินใจว่าจะบันทึกข้อยกเว้นและวิธีการบันทึกข้อยกเว้น มันไม่ได้ขึ้นอยู่กับโปรแกรมเมอร์ธรรมดาที่จะตัดสินใจ แต่มันเป็นประโยชน์ที่จะรู้อะไรบางอย่าง
5. การจัดการข้อยกเว้นในโครงการ J2EE
ในปัจจุบันโครงการ J2EE โดยทั่วไปจะแบ่งออกเป็นหลายชั้นอย่างมีเหตุผล คลาสสิกแบ่งออกเป็นสามเลเยอร์: เลเยอร์การนำเสนอเลเยอร์ธุรกิจและเลเยอร์การรวม (รวมถึงการเข้าถึงฐานข้อมูลและการเข้าถึงระบบภายนอก)
โครงการ J2EE มีความซับซ้อนและมีหลายประเด็นที่ต้องได้รับความสนใจเป็นพิเศษเมื่อจัดการข้อยกเว้นในโครงการ J2EE
เมื่อใช้แอปพลิเคชันแบบกระจายเราพบข้อยกเว้นที่ตรวจสอบมากมาย การโทร RMI ทั้งหมด (รวมถึงการเรียกอินเทอร์เฟซระยะไกล EJB) จะโยน java.rmi.remoteexception; ในเวลาเดียวกัน RemoteException เป็นข้อยกเว้นที่ตรวจสอบแล้ว เมื่อเราทำการโทรจากระยะไกลในระบบธุรกิจเราทุกคนต้องเขียนรหัสจำนวนมากเพื่อจัดการข้อยกเว้นที่ตรวจสอบเหล่านี้ เมื่อมีการรับรู้ remoteexception ข้อยกเว้นที่ตรวจสอบเหล่านี้จะร้ายแรงมากกับระบบและแทบจะไม่มีความเป็นไปได้ที่จะลองใหม่ กล่าวอีกนัยหนึ่งเมื่อข้อยกเว้นที่ตรวจสอบได้อย่างน่ากลัวเหล่านี้เช่น RemoteException ปรากฏขึ้นเราไม่จำเป็นต้องลองใหม่ แต่เราต้องเขียนลองมากมาย ... รหัสจับเพื่อจัดการกับมัน โดยทั่วไปเราทำการโทร RMI ที่ระดับล่างสุด ตราบใดที่มีการเรียก RMI อินเทอร์เฟซระดับบนทั้งหมดจะต้องมีการโยน remoteexception เพราะวิธีที่เราจัดการกับ RemoteException คือการขว้างมันต่อไป สิ่งนี้จะทำลายอินเทอร์เฟซธุรกิจของเรา RemoteException ข้อยกเว้นระดับระบบ J2EE เหล่านี้ส่งผลกระทบอย่างจริงจังต่ออินเทอร์เฟซธุรกิจของเรา วัตถุประสงค์ของการจัดเรียงระบบของเราคือการลดการพึ่งพาระหว่างระบบและการเปลี่ยนแปลงทางเทคโนโลยีในแต่ละชั้นจะไม่ส่งผลกระทบต่อเลเยอร์อื่น ๆ
// คลาสสาธารณะ usersoaimplimples usersoa {public userinfo getUserInfo (String userId) พ่น RemoteException {// …วิธีการโทรระยะไกล//………} ในทำนองเดียวกันการเข้าถึง JDBC จะทำการตรวจสอบข้อยกเว้นของ Sqlexception
เพื่อหลีกเลี่ยงการบุกรุกอย่างลึกซึ้งของข้อยกเว้นระดับระบบที่ตรวจสอบในระบบธุรกิจเราสามารถกำหนดข้อยกเว้นของระบบธุรกิจสำหรับวิธีการทางธุรกิจ สำหรับข้อยกเว้นที่ร้ายแรงมากเช่น Sqlexception และ RemoteException เราสามารถกำหนดข้อยกเว้นที่ไม่ได้ตรวจสอบใหม่แล้วห่อหุ้ม sqlexception และ remoteexception เป็นข้อยกเว้นที่ไม่ได้ตรวจสอบแล้วโยนมัน
หากข้อยกเว้นระดับระบบนี้จะถูกส่งไปยังผู้โทรก่อนหน้านี้เพื่อจัดการคุณสามารถกำหนดข้อยกเว้นทางธุรกิจที่ตรวจสอบใหม่แล้วปิดผนึกข้อยกเว้นระดับระบบเป็นข้อยกเว้นระดับธุรกิจแล้วโยนมัน
โดยทั่วไปเราจำเป็นต้องกำหนดข้อยกเว้นที่ไม่ได้ตรวจสอบเพื่อให้วิธีการทั้งหมดของอินเตอร์เฟสเลเยอร์การรวมประกาศที่จะโยนข้อยกเว้นที่ไม่ได้ตรวจสอบนี้
Public DataAccessExceptionExtends runtimeException {... } อินเตอร์เฟสสาธารณะ userdao {สตริงสาธารณะ getPassword (String userId) พ่น DataAccessException;} คลาสสาธารณะ UserDaoimplimples UserDao {Public String getPassword (String userId) '"+userId+"' "; ลอง {… // jdbc เรียก s.executeQuery (sql); …} catch (sqlexception ex) {โยน dataaccessexception ใหม่ (" การสืบค้นฐานข้อมูลล้มเหลว "+sql, ex);}}}}}} กำหนดข้อยกเว้นทางธุรกิจที่ตรวจสอบแล้วเพื่อให้วิธีการทั้งหมดของอินเตอร์เฟสเลเยอร์ธุรกิจประกาศว่าจะโยนข้อยกเว้นที่ตรวจสอบ
Public Class BusinessExceptionExtends ข้อยกเว้น {… .. } ส่วนต่อประสานสาธารณะ UserManager {Public UserInfo CopyUserInfo (ผู้ใช้ UserInfo) โยน BusinessException {userInfo newUser = null; ลอง {newUser = (userInfo) userException รองรับ: "+userinfo.class.getName (), ex);}}} เลเยอร์การเป็นตัวแทน J2EE ควรเป็นเลเยอร์ที่บางมากและฟังก์ชั่นหลักของมันคือ: รับคำขอเพจ, รวบรวมพารามิเตอร์หน้าลงในวัตถุ POJO, เรียกวิธีการทางธุรกิจที่เกี่ยวข้องแล้วส่งต่อหน้านำข้อมูลธุรกิจที่เกี่ยวข้องไปยังหน้า เลเยอร์การนำเสนอจำเป็นต้องให้ความสนใจกับปัญหาหนึ่ง เลเยอร์การนำเสนอจำเป็นต้องตรวจสอบความถูกต้องตามกฎหมายของข้อมูลเช่นฟิลด์อินพุตบางอย่างไม่สามารถว่างเปล่าการตรวจสอบความยาวอักขระ ฯลฯ
พารามิเตอร์ทั้งหมดที่ส่งผ่านจาก J2EE ไปยังพื้นหลังจากหน้าเป็นประเภทอักขระ หากคุณต้องการอินพุตของพารามิเตอร์ประเภทตัวเลขหรือวันที่ค่าอักขระจะต้องแปลงเป็นค่าตัวเลขหรือวันที่ที่สอดคล้องกัน
หากพารามิเตอร์การตรวจสอบรหัสเลเยอร์การเป็นตัวแทนไม่ถูกต้องควรส่งคืนไปยังหน้าต้นฉบับทำให้ผู้ใช้สามารถป้อนข้อมูลอีกครั้งและพร้อมรับข้อมูลข้อผิดพลาดที่เกี่ยวข้อง
โดยปกติพารามิเตอร์ที่ส่งผ่านจากหน้าจะถูกแปลงเป็นค่าตัวเลขเราสามารถดูรหัสดังกล่าวได้
ModeAnDView HandLeRequest (คำขอ httpservletRequest, การตอบสนอง httpservletResponse) โยนข้อยกเว้น {String agestr = request.getParameter ("อายุ"); อายุ int = integer.parse (agestr); ……… SimpledateFormat format = new SimpledateFormat ("mm/dd/yyyy"); วันที่วันเกิด = format.parse (เกิดวันเกิด);} ควรเห็นรหัสข้างต้นบ่อยครั้ง แต่เมื่อผู้ใช้ป้อนอักขระที่ไม่สามารถแปลงเป็นจำนวนเต็มจากหน้าหรือค่าวันที่ที่ไม่ถูกต้อง
เมธอด integer.parse () ถูกโยนข้อยกเว้นที่ไม่ได้ตรวจสอบด้วย numberFormatexception อย่างไรก็ตามข้อยกเว้นนี้ไม่ใช่ข้อยกเว้นที่ร้ายแรง โดยทั่วไปเมื่อค่าที่ป้อนโดยผู้ใช้ในฟิลด์รายการหน้านั้นผิดกฎหมายเราควรแจ้งให้ผู้ใช้กลับเข้ามาอีกครั้ง แต่เมื่อมีข้อยกเว้นที่ไม่ได้ตรวจสอบแล้วไม่มีโอกาสลองอีกครั้ง รหัสเช่นนี้ทำให้เกิดข้อมูลข้อยกเว้นจำนวนมากที่จะแสดงบนหน้า ทำให้ระบบของเราดูบอบบางมาก
ในทำนองเดียวกันวิธี SimpledateFormat.parse () จะทำการยกเว้น Parseexception ที่ไม่ได้ตรวจสอบ
ในกรณีนี้เราควรตรวจสอบข้อยกเว้นที่ไม่ได้ตรวจสอบเหล่านี้และแจ้งให้ผู้ใช้กลับเข้ามาอีกครั้ง
ModeAnDView HandLeRequest (คำขอ httpservletRequest, httpservletResponse การตอบสนอง) โยนข้อยกเว้น {string agestr = request.getParameter ("อายุ"); สตริงเกิด daystr = request.getParameter ("วันเกิด"); อายุ int = 0; วันเกิดวันเกิด = null; Ex) {error.reject ("อายุ", "ไม่ใช่ค่าจำนวนเต็มตามกฎหมาย");} ………ลอง {รูปแบบ simpledateFormat = ใหม่ simpledateFormat ("mm/dd/yyyy"); วันเกิด = รูปแบบ. parse (วันเกิด) 'mm/dd/yyy' รูปแบบ ");}} ในเลเยอร์การนำเสนอคุณต้องคิดออกว่าวิธีการโทรจะมีข้อยกเว้นที่ไม่ได้ตรวจสอบภายใต้สถานการณ์ใดข้อยกเว้นเหล่านี้จะถูกโยนลงและทำการประมวลผลที่ถูกต้อง
ในเลเยอร์การนำเสนอไม่จำเป็นต้องจับข้อยกเว้นโดยทั่วไป หากข้อยกเว้นที่ถูกโยนโดยวิธีการทางธุรกิจที่เรียกว่าเทียบเท่ากับค่าผลตอบแทนที่สองในกรณีนี้จำเป็นต้องจับภาพ
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น