เมื่อเร็ว ๆ นี้เมื่อฉันเห็นวิธีการเทมเพลตของ JDBctemplete ของฤดูใบไม้ผลิฉันเริ่มสนใจเทมเพลตและการโทรกลับมากและฉันก็สอบถามข้อมูลบางอย่างและสรุป
ฟังก์ชั่นการโทรกลับ:
การโทรกลับที่เรียกว่าหมายความว่าโปรแกรมไคลเอนต์ C เรียกฟังก์ชั่นบางอย่าง A ในโปรแกรมบริการแล้วเรียกฟังก์ชั่น B บางอย่าง B ใน C ในบางครั้ง สำหรับ C, B นี้เรียกว่าฟังก์ชันการโทรกลับ ฟังก์ชั่นการเรียกกลับเป็นเพียงฟังก์ชั่นที่ใช้โดยผู้ใช้ตามฟังก์ชันการเรียกใช้การเรียกร้องการเรียก ฟังก์ชั่นการโทรกลับเป็นส่วนหนึ่งของเวิร์กโฟลว์และเวิร์กโฟลว์กำหนดเวลาของการโทรของฟังก์ชั่น (การโทรกลับ) โดยทั่วไปแล้ว C จะไม่เรียก B ด้วยตัวเอง จุดประสงค์ของ C ที่ให้ B คือการเรียกร้องให้เรียกมันและ C ต้องให้มัน เนื่องจาก S ไม่ทราบว่า B ถูกตั้งชื่อตาม C, S จะเห็นด้วยกับข้อกำหนดของอินเตอร์เฟสของ B (ฟังก์ชั่นต้นแบบ) และจากนั้น C จะบอกล่วงหน้าว่าเขาจะใช้ฟังก์ชัน B ผ่านฟังก์ชั่น R ของ S. กระบวนการนี้เรียกว่าการลงทะเบียนฟังก์ชันการโทรกลับและ R เรียกว่าฟังก์ชันการลงทะเบียน บริการเว็บและ Java RMI ใช้กลไกการโทรกลับเพื่อเข้าถึงโปรแกรมเซิร์ฟเวอร์ระยะไกล ฟังก์ชั่นการโทรกลับมีคุณสมบัติดังต่อไปนี้:
1. เป็นส่วนหนึ่งของเวิร์กโฟลว์;
2. จะต้องมีการประกาศ (กำหนด) ตามอนุสัญญาการโทรที่ระบุโดยเวิร์กโฟลว์
3. ช่วงเวลาของการโทรถูกกำหนดโดยเวิร์กโฟลว์ ผู้ดำเนินการของฟังก์ชั่นการโทรกลับไม่สามารถเรียกใช้ฟังก์ชันการโทรกลับโดยตรงเพื่อใช้ฟังก์ชั่นของเวิร์กโฟลว์
กลไกการโทรกลับ:
กลไกการโทรกลับเป็นรูปแบบการออกแบบทั่วไป มันเปิดเผยฟังก์ชั่นในเวิร์กโฟลว์ให้กับผู้ใช้ภายนอกตามอินเตอร์เฟสที่ตกลงกันไว้ให้ข้อมูลแก่ผู้ใช้ภายนอกหรือต้องการให้ผู้ใช้ภายนอกให้ข้อมูล
กลไกการโทรกลับ Java:
มีอินเทอร์เฟซบางอย่างระหว่างโมดูลซอฟต์แวร์อยู่เสมอ ในแง่ของวิธีการโทรพวกเขาสามารถแบ่งออกเป็นสามประเภท: การโทรแบบซิงโครนัสการโทรกลับและการโทรแบบอะซิงโครนัส
การโทรแบบซิงโครนัส: การโทรบล็อกผู้โทรต้องรอให้อีกฝ่ายดำเนินการเสร็จสิ้นก่อนที่จะกลับมา เป็นการโทรทางเดียว
การโทรกลับ: โหมดการโทรสองทางนั่นคือฝ่ายที่เรียกว่าจะเรียกอินเทอร์เฟซของอีกฝ่ายเมื่อมีการเรียกอินเทอร์เฟซ
การโทรแบบอะซิงโครนัส: กลไกที่คล้ายกับข้อความหรือเหตุการณ์ แต่ทิศทางการโทรนั้นตรงกันข้าม เมื่อบริการอินเทอร์เฟซได้รับข้อความหรือเหตุการณ์เกิดขึ้นจะแจ้งให้ไคลเอนต์แจ้งอย่างแข็งขัน (นั่นคือโทรหาอินเทอร์เฟซของลูกค้า)
ความสัมพันธ์ระหว่างการโทรกลับและการโทรแบบอะซิงโครนัสนั้นมีความสัมพันธ์กันอย่างใกล้ชิด: การเรียกกลับถูกใช้เพื่อใช้การลงทะเบียนข้อความแบบอะซิงโครนัสและการแจ้งเตือนของข้อความทำได้ผ่านการโทรแบบอะซิงโครนัส
อินสแตนซ์การโทรกลับ
1. อินเทอร์เฟซโทรกลับ
การโทรกลับส่วนต่อประสานสาธารณะ {สตริงโทรกลับ (); - 2. ผู้โทร
ชั้นเรียนสาธารณะอื่น {การโทรกลับส่วนตัว // การเรียกวิธีการที่ใช้โมฆะสาธารณะในชั้นเรียน setCallback (การเรียกกลับการโทรกลับ) {this.callback = callback; } // เมื่อธุรกิจต้องการให้เรียกใช้วิธีเฉพาะที่ใช้โมฆะ public void docallback () {system.out.println (callback.callback ()); - 3. ฟังก์ชั่นการโทรกลับ
Public Class TestCallCack {โมฆะคงที่สาธารณะหลัก (String [] args) {// สร้างคลาสการใช้งานของผู้โทรอีกอันอีกครั้ง = ใหม่อีกครั้ง (); // ลงทะเบียนอินเทอร์เฟซด้านหลังลงในคลาสการใช้งานอื่น SetCallback (การโทรกลับใหม่ () {@Override สตริงสาธารณะการเรียกกลับ () {return "คุณคือหมู";}}); // เรียกใช้ฟังก์ชันการโทรกลับอีกครั้ง docallback (); -การใช้วิธีการโทรกลับมักจะเกิดขึ้นในระหว่างการใช้ "อินเตอร์เฟส Java" และ "คลาสนามธรรม" รูปแบบการออกแบบวิธีการเทมเพลตใช้กลไกการโทรกลับวิธี รูปแบบนี้ก่อนกำหนดโครงกระดูกอัลกอริทึมของขั้นตอนเฉพาะและล่าช้าขั้นตอนบางอย่างในรูปแบบการออกแบบที่ใช้ในคลาสย่อย รูปแบบการออกแบบวิธีการเทมเพลตช่วยให้คลาสย่อยสามารถกำหนดขั้นตอนเฉพาะบางอย่างของอัลกอริทึมโดยไม่ต้องเปลี่ยนโครงสร้างของอัลกอริทึม
การบังคับใช้รูปแบบการออกแบบแม่แบบ:
1. ใช้ส่วนที่ไม่เปลี่ยนแปลงของอัลกอริทึมในครั้งเดียวและปล่อยให้อัลกอริทึมตัวแปรเป็นคลาสย่อยเพื่อนำไปใช้
2. พฤติกรรมสาธารณะในแต่ละคลาสย่อยควรได้รับการสกัดและเข้มข้นในชั้นพาเรนต์สาธารณะเพื่อหลีกเลี่ยงการทำซ้ำรหัส
3. สามารถควบคุมส่วนขยาย subclass ได้
ตัวอย่างแม่แบบ:
คลาสเทมเพลตบทคัดย่อคลาสคลาส:
บทคัดย่อระดับสาธารณะบทคัดย่อ {// วิธีการที่ต้องใช้การใช้งาน subclass public Public Public Public Public Print (); // วิธีการเทมเพลตโมฆะสาธารณะ doprint () {system.out.println ("ดำเนินการวิธีการเทมเพลต"); สำหรับ (int i = 0; i <3; i ++) {print (); - เมธอดการใช้งานคลาสย่อยคลาส: คลาส: คลาส:
คลาสย่อยคลาสสาธารณะขยายบทคัดย่อ {@Override โมฆะสาธารณะพิมพ์ () {System.out.println ("วิธีการใช้งานของคลาสย่อย"); - วิธีการทดสอบวิธีการเทมเพลต:
คลาสสาธารณะ templeTetest {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {subclass subclass = subclass ใหม่ (); subclass.print (); subclass.doprint (); - ต่อไปนี้เป็นการแนะนำรายละเอียดเกี่ยวกับการใช้วิธีเทมเพลตสปริง การใช้ JDBctemplete เป็นตัวอย่างเราจะอธิบายรายละเอียดเกี่ยวกับการใช้โหมดเทมเพลตและกลไกการโทรกลับ
ก่อนอื่นมาดูตัวอย่างการเขียนโปรแกรม JDBC แบบคลาสสิก:
รายการสาธารณะ <user> query () {รายการ <user> userlist = new ArrayList <user> (); String SQL = "SELECT * จากผู้ใช้"; การเชื่อมต่อ con = null; PreparedStatement PST = NULL; ผลลัพธ์ RS = NULL; ลอง {con = hsqldbutil.getConnection (); PST = Con.prepareStatement (SQL); rs = pst.executeQuery (); ผู้ใช้ผู้ใช้ = null; ในขณะที่ (rs.next ()) {user = user ใหม่ (); user.setId (rs.getInt ("id")); user.setUserName (rs.getString ("user_name")); user.setBirth (Rs.getDate ("เกิด")); user.setCreatedate (rs.getDate ("create_date")); userlist.add (ผู้ใช้); }} catch (sqlexception e) {e.printstacktrace (); } ในที่สุด {ถ้า (rs! = null) {ลอง {rs.close (); } catch (sqlexception e) {e.printstacktrace (); }} ลอง {pst.close (); } catch (sqlexception e) {e.printstacktrace (); } ลอง {ถ้า (! con.isclosed ()) {ลอง {con.close (); } catch (sqlexception e) {e.printstacktrace (); }}} catch (sqlexception e) {e.printstacktrace (); }} ส่งคืน UserList; -
แบบสอบถามง่าย ๆ ต้องการสิ่งต่าง ๆ มากมายและยังจัดการกับข้อยกเว้น มาเรียงกันถ้าเราไม่ต้องการ:
1. รับการเชื่อมต่อ
2. รับคำสั่ง
3. รับชุดผลลัพธ์
4. วนผ่านชุดผลลัพธ์และห่อหุ้มไว้ในคอลเลกชัน
5. การเชื่อมต่อปิดคำสั่งและชุดผลลัพธ์ในทางกลับกันและพิจารณาข้อยกเว้นต่าง ๆ ฯลฯ
หากการสืบค้นหลายครั้งจะสร้างรหัสที่ซ้ำกันมากขึ้นคุณสามารถใช้กลไกเทมเพลตได้ จากการสังเกตเราพบว่าขั้นตอนข้างต้นส่วนใหญ่ซ้ำซ้อนและนำกลับมาใช้ซ้ำได้ เฉพาะเมื่อสำรวจชุดผลลัพธ์และห่อหุ้มมันลงในคอลเลกชันสามารถปรับแต่งได้เนื่องจากแต่ละตารางแผนที่ถั่วชวาที่แตกต่างกัน ไม่มีวิธีที่จะนำรหัสนี้กลับมาใช้ใหม่ได้อีกครั้งสามารถปรับแต่งได้เท่านั้น
บทคัดย่อรหัสคลาส:
บทคัดย่อคลาสสาธารณะ JDBCTEMPLATE {// วิธีการเทมเพลตวัตถุสุดท้ายการดำเนินการวัตถุสุดท้าย (String SQL) พ่น SQLException {การเชื่อมต่อ con = hsqldbutil.getConnection (); คำสั่ง stmt = null; ลอง {stmt = con.createStatement (); resultset rs = stmt.executeQuery (SQL); Object result = doinStatement (RS); // วิธีการนามธรรม (วิธีการที่กำหนดเอง, การใช้งาน subclass จำเป็นต้องส่งคืนผลลัพธ์; } catch (sqlexception ex) {ex.printstacktrace (); โยนอดีต; } ในที่สุด {ลอง {stmt.close (); } catch (sqlexception e) {e.printstacktrace (); } ลอง {ถ้า (! con.isclosed ()) {ลอง {con.close (); } catch (sqlexception e) {e.printstacktrace (); }}} catch (sqlexception e) {e.printstacktrace (); }}} // วิธีการนามธรรม (วิธีการกำหนดเอง) วัตถุนามธรรมที่ได้รับการป้องกัน doinstatement (ผลลัพธ์ RS); -ในชั้นเรียนนามธรรมนี้กระบวนการหลักของ Sun JDBC API ถูกห่อหุ้มและขั้นตอนของการเดินทางผ่านชุดผลลัพธ์จะถูกวางไว้ในวิธีนามธรรม doinstatement () ซึ่งถูกนำมาใช้โดยคลาสย่อย
รหัสการใช้งาน subclass:
คลาสสาธารณะ JDBCTEMPLEDUSERIMPL ขยาย JDBCTEMPLATE {@Override วัตถุที่ได้รับการป้องกัน doinStatement (ResultSet RS) {รายการ <erer> userlist = new ArrayList <ผู้ใช้> (); ลอง {user user = null; ในขณะที่ (rs.next ()) {user = user ใหม่ (); user.setId (rs.getInt ("id")); user.setUserName (rs.getString ("user_name")); user.setBirth (Rs.getDate ("เกิด")); user.setCreatedate (rs.getDate ("create_date")); userlist.add (ผู้ใช้); } return userlist; } catch (sqlexception e) {e.printstacktrace (); คืนค่า null; -ในวิธีการ doinstatement () เราสำรวจชุดผลลัพธ์และในที่สุดก็ส่งคืน
รหัสทดสอบ:
String SQL = "SELECT * จากผู้ใช้"; JDBCTEMPLAT JT = ใหม่ JDBCTEMPLEDUSERIMPL (); รายการ <user> userlist = (รายการ <user>) jt.execute (SQL);
มีการใช้กลไกเทมเพลตมาจนถึงตอนนี้ แต่ถ้าคุณต้องการสืบทอดคลาสแม่ทุกครั้งที่คุณโทรหา JDBCTEMPLATE มันค่อนข้างไม่สะดวกดังนั้นกลไกการโทรกลับสามารถมีบทบาทได้
การโทรกลับที่เรียกว่าหมายถึงการผ่านอินเทอร์เฟซในพารามิเตอร์เมธอด เมื่อคลาสหลักเรียกวิธีนี้จะต้องเรียกคลาสการใช้งานของอินเตอร์เฟสที่ส่งผ่านในวิธีการ
การใช้งานโหมดการโทรกลับบวกกับเทมเพลต
อินเตอร์เฟสการโทรกลับ:
คำชี้แจงส่วนต่อประสานสาธารณะ callback {Object doinstatement (คำสั่ง STMT) พ่น sqlexception; - วิธีแม่แบบ:
คลาสสาธารณะ JDBCTEMPLATE {// วิธีการเทมเพลตวัตถุสาธารณะขั้นสุดท้ายดำเนินการ (คำแถลงการกระทำแบ็ค) พ่น sqlexception {การเชื่อมต่อ con = hsqldbutil.getConnection (); คำสั่ง stmt = null; ลอง {stmt = con.createStatement (); Object result = action.doinStatement (RS); // วิธีการโทรกลับผลส่งคืนผลลัพธ์; } catch (sqlexception ex) {ex.printstacktrace (); โยนอดีต; } ในที่สุด {ลอง {stmt.close (); } catch (sqlexception e) {e.printstacktrace (); } ลอง {ถ้า (! con.isclosed ()) {ลอง {con.close (); } catch (sqlexception e) {e.printstacktrace (); }}} catch (sqlexception e) {e.printstacktrace (); }}}} การสืบค้นวัตถุสาธารณะ (คำแถลง callback stmt) พ่น sqlexception {return execute (stmt); - ชั้นเรียนที่ผ่านการทดสอบ:
การสืบค้นวัตถุสาธารณะ (สตริงสุดท้าย SQL) พ่น sqlexception {คลาส queryStatementCallback ใช้คำแถลง callback {วัตถุสาธารณะ doinstatement (คำสั่ง STMT) พ่น sqlexception {ผลลัพธ์ rs = stmt.executeQuery (SQL); รายการ <user> userlist = arrayList ใหม่ <user> (); ผู้ใช้ผู้ใช้ = null; ในขณะที่ (rs.next ()) {user = user ใหม่ (); user.setId (rs.getInt ("id")); user.setUserName (rs.getString ("user_name")); user.setBirth (Rs.getDate ("เกิด")); user.setCreatedate (rs.getDate ("create_date")); userlist.add (ผู้ใช้); } return userlist; }} JDBCTEMPLATE JT = ใหม่ JDBCTEMPLATE (); return jt.Query (ใหม่ queryStatementCallback ()); -
เหตุใดฤดูใบไม้ผลิจึงไม่ใช้วิธีเทมเพลตแบบดั้งเดิม แต่ยังร่วมมือกับการโทรกลับด้วย?
แค่คิดว่าถ้ามี 10 วิธีนามธรรมในคลาสหลักและคลาสย่อยทั้งหมดที่สืบทอดมานั้นจำเป็นต้องใช้วิธีการนามธรรมทั้งหมด 10 วิธีทั้งหมดนี้จะปรากฏขึ้น บางครั้งฉันควรทำอย่างไรถ้าคลาสย่อยจำเป็นต้องปรับแต่งวิธีการบางอย่างในคลาสหลักเท่านั้น? ในเวลานี้มีการใช้การโทรกลับ
นอกจากนี้วิธีการข้างต้นโดยทั่วไปใช้วิธีการเทมเพลต + โหมดการโทรกลับ แต่มันก็ยังห่างไกลจาก JDBCTEMPLATE ของฤดูใบไม้ผลิเล็กน้อย แม้ว่าเราจะใช้วิธีการเทมเพลต + โหมดการโทรกลับด้านบน แต่ดูเหมือนว่า "น่าเกลียด" เล็กน้อยเมื่อเทียบกับ JDBCTEMPLATE ของ Spring ฤดูใบไม้ผลิแนะนำแนวคิดของ Rowmapper และ Resustometextractor อินเทอร์เฟซ RowMapper มีหน้าที่ในการประมวลผลข้อมูลแถวที่แน่นอน ตัวอย่างเช่นเราสามารถใช้งานได้ในบางแถวของระเบียนในวิธีการ MAPROW หรือห่อหุ้มไว้ในเอนทิตี ResustomeTextractor เป็นตัวแยกชุดข้อมูลซึ่งรับผิดชอบในการข้าม ResultSet และการประมวลผลข้อมูลตามกฎใน RowMapper ความแตกต่างระหว่าง RowMapper และ ResustomeTextractor คือ RowMapper ประมวลผลข้อมูลแถวที่แน่นอนและส่งคืนวัตถุเอนทิตี ResustomeTextractor ประมวลผลชุดข้อมูลและส่งคืนคอลเลกชันของวัตถุ
แน่นอนว่าข้างต้นเป็นเพียงหลักการพื้นฐานของการใช้งาน Spring JDBCTEMPLATE Spring JDBCTEMPLATE ได้ทำสิ่งต่าง ๆ มากขึ้นเช่นการห่อหุ้มการดำเนินการขั้นพื้นฐานทั้งหมดลงในอินเตอร์เฟส JDBCoperations และการใช้ JDBCACCESSOR เพื่อจัดการแหล่งข้อมูลและข้อยกเว้นการแปลง
ข้างต้นเป็นเรื่องเกี่ยวกับบทความนี้ฉันหวังว่ามันจะเป็นประโยชน์กับการเรียนรู้ของทุกคน