في الآونة الأخيرة ، عندما رأيت طريقة القالب لـ JDBCTEMPHITE من Spring ، أصبحت مهتمًا جدًا بالقوالب وعمليات الاسترجاعات ، وقد استفسرت بعض المعلومات وقمت ببعض الملخصات.
وظيفة رد الاتصال:
يعني ما يسمى رد الاتصال أن برنامج العميل C يستدعي وظيفة معينة في برنامج الخدمة ، ثم يقوم S باستدعاء وظيفة معينة في C في وقت ما. بالنسبة لـ C ، يطلق على هذا B وظيفة رد الاتصال. وظيفة رد الاتصال هي مجرد وظيفة يتم تنفيذها من قبل المستخدم وفقًا لاتفاقية استدعاء وظيفة رد الاتصال. وظيفة رد الاتصال هي جزء من سير العمل ، ويحدد سير العمل توقيت دعوة الوظيفة (رد الاتصال). بشكل عام ، لن يدعو C بمفرده. الغرض من توفير C هو السماح لـ S بالاتصال به ، ويجب على C تقديمه. نظرًا لأن S لا يعرف من الذي تم تسميته على اسم C ، فإن S سوف يتفق على مواصفات واجهة B (النموذج الأولي للوظيفة) ، وبعد ذلك سيخبر C مقدمًا أنه سيستخدم وظيفة B من خلال وظيفة S من S. وتسمى هذه العملية تسجيل وظيفة رد الاتصال ، ويسمى R وظيفة التسجيل. تستخدم خدمة الويب و Java RMI آليات رد الاتصال للوصول إلى برامج الخادم البعيد. تحتوي وظيفة رد الاتصال على الخصائص التالية:
1. ينتمي إلى جزء من سير العمل ؛
2. يجب إعلانه (محدد) وفقًا لاتفاقية الاتصال المحددة بواسطة سير العمل ؛
3. يتم تحديد توقيت دعوتها بواسطة سير العمل. لا يمكن للمنفذ وظيفة رد الاتصال استدعاء وظيفة رد الاتصال مباشرة لتنفيذ وظيفة سير العمل ؛
آلية رد الاتصال:
آلية رد الاتصال هي نموذج تصميم شائع. يعرض وظيفة في سير العمل للمستخدمين الخارجيين وفقًا للواجهة المتفق عليها ، أو يوفر البيانات للمستخدمين الخارجيين ، أو يتطلب من المستخدمين الخارجيين تقديم بيانات.
آلية رد الاتصال جافا:
هناك دائمًا واجهات معينة بين وحدات البرامج. فيما يتعلق بطرق الاتصال ، يمكن تقسيمها إلى ثلاث فئات: المكالمات المتزامنة ، وعمليات الاسترجاعات والمكالمات غير المتزامنة.
مكالمة متزامنة: مكالمة حظر ، يتعين على المتصل انتظار الطرف الآخر لإكمال التنفيذ قبل العودة. إنها مكالمة في اتجاه واحد.
رد الاتصال: وضع اتصال ثنائي الاتجاه ، أي أن الطرف المسمى سيتصل أيضًا بواجهة الطرف الآخر عند استدعاء الواجهة ؛
المكالمة غير المتزامنة: آلية مماثلة لرسالة أو حدث ، ولكن اتجاه الاتصال الخاص به هو عكس ذلك تمامًا. عندما تتلقى خدمة الواجهة رسالة معينة أو حدث حدث ، فإنها ستخطر العميل بنشاط (أي استدعاء واجهة العميل).
ترتبط العلاقة بين عمليات الاسترجاعات والمكالمات غير المتزامنة ارتباطًا وثيقًا: يتم استخدام عمليات الاسترجاعات لتنفيذ تسجيل الرسائل غير المتزامنة ، ويتم تحقيق إخطار الرسائل من خلال المكالمات غير المتزامنة.
مثيل رد الاتصال
1. واجهة رد الاتصال
اتصال الواجهة العامة {String Callback () ؛ } 2. المتصل
الفئة العامة أخرى {رد الاتصال الخاص ؛ // استدعاء الطريقة التي تنفذ فئة الفئة العامة setCallback (رد اتصال رد الاتصال) {this.callback = callback ؛ } // عندما يحتاج العمل ، اتصل بالطريقة المحددة التي تنفذ class public void docallback () {system.out.println (callback.callback ()) ؛ }} 3. اختبار وظيفة رد الاتصال
الفئة العامة TestCallCack {public static void main (string [] args) {// إنشاء فئة تنفيذ المتصل أخرى = جديد آخر () ؛ // قم بتسجيل الواجهة الخلفية في فئة التنفيذ الأخرى. // تنفيذ وظيفة رد الاتصال other.docallback () ؛ }}عادة ما يحدث استخدام طرق رد الاتصال أثناء استخدام "واجهة Java" و "الفئة التجريدية". يستخدم نمط تصميم طريقة القالب آلية رد الاتصال الطريقة. يحدد هذا النمط أولاً الهيكل العظمي للخوارزمية لخطوات محددة ويؤخر بعض الخطوات إلى نمط التصميم المنفذ في الفئة الفرعية. يتيح نمط تصميم طريقة القالب الفئات الفرعية إعادة تعريف خطوات معينة محددة للخوارزمية دون تغيير بنية الخوارزمية.
قابلية تطبيق نمط تصميم القالب:
1. قم بتنفيذ الجزء غير المتغير من الخوارزمية في وقت واحد واترك الخوارزمية المتغيرة إلى الفئات الفرعية لتنفيذها.
2. يجب استخراج السلوكيات العامة في كل فئة فرعية وتركيزها في فئة الوالدين العامة لتجنب ازدواج الرمز.
3. يمكن التحكم في امتدادات الفئة الفرعية.
مثال قالب:
فئة طريقة القالب التجريدي:
Abstract Class Publicsup {// الأساليب التي تتطلب تنفيذ الفئة الفرعية Public Abstract void print () ؛ // template method public void doprint () {system.out.println ("تنفيذ طريقة القالب") ؛ لـ (int i = 0 ؛ i <3 ؛ i ++) {print () ؛ }}} فئة طريقة تنفيذ الفئة الفرعية:
تمتد الفئة الفرعية من الفئة العامة الملخصات {Override public void print () {system.out.println ("طريقة التنفيذ للفئات الفرعية") ؛ }} فئة اختبار طريقة القالب:
الفئة العامة TempleTetest {public static void main (string [] args) {الفئة الفرعية الفرعية = فئة فرعية جديدة () ؛ الفئة الفرعية. الفئة الفرعية. doperrint () ؛ }} فيما يلي مقدمة مفصلة لاستخدام طريقة قالب الربيع. أخذ JDBCtemplete كمثال ، سنشرح بالتفصيل استخدام وضع القالب وآلية رد الاتصال.
أولاً ، دعونا نلقي نظرة على مثال برمجة JDBC الكلاسيكي:
القائمة العامة <Sether> query () {list <Serve> userList = new ArrayList <Serve> () ؛ String SQL = "SELECT * from user" ؛ الاتصال con = null ؛ أعدت PST = NULL ؛ resultset rs = null ؛ حاول {con = hsqldbutil.getConnection () ؛ PST = con.preparestatement (SQL) ؛ rs = pst.executequery () ؛ مستخدم المستخدم = فارغ ؛ بينما (rs.next ()) {user = new user () ؛ user.setId (rs.getInt ("id")) ؛ user.setUserName (rs.getString ("user_name")) ؛ user.setBirth (rs.getDate ("birth")) ؛ user.setCreatedAte (rs.getDate ("create_date")) ؛ userList.add (المستخدم) ؛ }} catch (sqlexception e) {E.PrintStackTrace () ؛ } أخيرًا {if (rs! = null) {try {rs.close () ؛ } catch (sqlexception e) {E.PrintStackTrace () ؛ }} جرب {pst.close () ؛ } catch (sqlexception e) {E.PrintStackTrace () ؛ } حاول {if (! con.isclosed ()) {try {con.close () ؛ } catch (sqlexception e) {E.PrintStackTrace () ؛ }}} catch (sqlexception e) {E.PrintStackTrace () ؛ }} إرجاع قائمة المستخدمين ؛ }
يتطلب الاستعلام البسيط الكثير من الأشياء وأيضًا التعامل مع الاستثناءات. دعونا نفرزها إذا كنا لا نريد:
1. الحصول على اتصال
2. الحصول على بيان
3. الحصول على نتائج
4. التكرار من خلال ResultSet وتغلفها في مجموعة
5. إغلاق الاتصال والبيان ونتائجها بدوره ، والنظر في استثناءات مختلفة ، إلخ.
إذا كانت الاستعلامات المتعددة ستولد المزيد من الكود المكررة ، فيمكنك استخدام آلية القالب. من خلال الملاحظة ، وجدنا أن معظم الخطوات المذكورة أعلاه متكررة وقابلة لإعادة الاستخدام. فقط عند اجتياز مجموعة النتائج وتغليفها في مجموعة قابلة للتخصيص ، لأن كل جدول يخطط لحبوب Java مختلفة. لا توجد طريقة لإعادة استخدام هذا الجزء من الكود ، لا يمكن تخصيصه إلا.
رمز الفئة التجريدية:
الفئة المجردة العامة jdbctemplate {// طريقة القالب الكائن النهائي العام تنفيذ (سلسلة SQL) يلقي sqlexception {connection con = hsqldbutil.getConnection () ؛ بيان stmt = فارغة ؛ حاول {stmt = con.createstatement () ؛ resultset rs = stmt.executequery (SQL) ؛ نتيجة الكائن = doinstatement (RS) ؛ // طريقة الملخص (طريقة مخصصة ، تنفيذ الفئة الفرعية المطلوبة) نتيجة الإرجاع ؛ } catch (sqlexception ex) {ex.printStackTrace () ؛ رمي السابقين } أخيرًا {try {stmt.close () ؛ } catch (sqlexception e) {E.PrintStackTrace () ؛ } حاول {if (! con.isclosed ()) {try {con.close () ؛ } catch (sqlexception e) {E.PrintStackTrace () ؛ }}} catch (sqlexception e) {E.PrintStackTrace () ؛ }}} // method method (طريقة مخصصة) كائن تجريدي محمي doInstatement (resultset rs) ؛ }في هذه الفئة التجريدية ، يتم تغليف العملية الرئيسية ل Sun JDBC API ، ويتم وضع خطوة اجتياز Resultset في طريقة التجريدية doinstatement () ، والتي يتم تنفيذها بواسطة الفئة الفرعية.
رمز تنفيذ الفئة الفرعية:
الفئة العامة jdbctemplateuserimpl تمتد jdbctemplate {override كائن محمي doInStatement (resultset rs) {list <serve> userlist = new ArrayList <Ser> () ؛ حاول {user user = null ؛ بينما (rs.next ()) {user = new user () ؛ user.setId (rs.getInt ("id")) ؛ user.setUserName (rs.getString ("user_name")) ؛ user.setBirth (rs.getDate ("birth")) ؛ user.setCreatedAte (rs.getDate ("create_date")) ؛ userList.add (المستخدم) ؛ } إرجاع قائمة المستخدمين ؛ } catch (sqlexception e) {E.PrintStackTrace () ؛ العودة لاغية. }}}في طريقة doinstatement () ، نعبر مجموعة النتائج وأخيراً.
رمز الاختبار:
String SQL = "SELECT * from user" ؛ jdbctemplate jt = new jdbctemplateuserimpl () ؛ قائمة <Sether> userList = (List <Ser>) jt.execute (SQL) ؛
تم استخدام آلية القالب حتى الآن ، ولكن إذا كنت بحاجة إلى ورث فئة الأصل في كل مرة تتصل فيها بـ JDBCTEMPLATE ، فهي غير مريحة للغاية ، وبالتالي يمكن أن تلعب آلية رد الاتصال دورًا.
يعني ما يسمى رد الاتصال تمرير واجهة في معلمات الطريقة. عندما تستدعي فئة الأصل هذه الطريقة ، يجب أن تستدعي فئة التنفيذ الخاصة بالواجهة التي تم تمريرها في الطريقة.
تنفيذ وضع الاتصال Plus Plus
واجهة رد الاتصال:
واجهة عامة stateCallback {object doinstatement (بيان STMT) يلقي sqlexception ؛ } طريقة القالب:
الفئة العامة jdbctemplate {// طريقة القالب الكائن النهائي العام تنفيذ (إجراءات statlecallback) يلقي sqlexception {connection con = hsqldbutil.getConnection () ؛ بيان stmt = فارغة ؛ حاول {stmt = con.createstatement () ؛ نتيجة الكائن = Action.DoinStatement (RS) ؛ // طريقة إرجاع طريقة رد الاتصال ؛ } catch (sqlexception ex) {ex.printStackTrace () ؛ رمي السابقين } أخيرًا {try {stmt.close () ؛ } catch (sqlexception e) {E.PrintStackTrace () ؛ } حاول {if (! con.isclosed ()) {try {con.close () ؛ } catch (sqlexception e) {E.PrintStackTrace () ؛ }}} catch (sqlexception e) {E.PrintStackTrace () ؛ }}}} استعلام الكائنات العامة (statlecallback stmt) يلقي sqlexception {return execute (stmt) ؛ }}} فئة تم اختبارها:
استعلام الكائن العام (السلسلة النهائية SQL) يلقي sqlexception {class QueryStateMentCallback تنفذ itturecallback {doinstatement الكائن العام (بيان STMT) يلقي sqlexception {resultset rs = stmt.executequery (sql) ؛ قائمة <Sether> userList = new ArrayList <Sether> () ؛ مستخدم المستخدم = فارغ ؛ بينما (rs.next ()) {user = new user () ؛ user.setId (rs.getInt ("id")) ؛ user.setUserName (rs.getString ("user_name")) ؛ user.setBirth (rs.getDate ("birth")) ؛ user.setCreatedAte (rs.getDate ("create_date")) ؛ userList.add (المستخدم) ؛ } إرجاع قائمة المستخدمين ؛ }} jdbctemplate jt = new jdbctemplate () ؛ return jt.query (New QueryStateMentCallback ()) ؛ }
لماذا لا يستخدم الربيع طرق القالب التقليدي ، ولكن أيضًا يتعاون مع رد الاتصال؟
فقط تخيل ، إذا كانت هناك 10 طرق مجردة في فئة الوالدين وجميع الفئات الفرعية التي ترثها تحتاج إلى تنفيذ جميع هذه الأساليب التجريدية العشرة ، ستظهر الفئة الفرعية متضخمة للغاية. في بعض الأحيان ، ما الذي يجب أن أفعله إذا احتاجت الفئة الفرعية فقط إلى تخصيص طريقة معينة في الفئة الأصل؟ في هذا الوقت ، يتم استخدام رد الاتصال.
بالإضافة إلى ذلك ، تنفذ الطريقة أعلاه بشكل أساسي طريقة الاتصال + وضع رد الاتصال. لكنها لا تزال بعيدة قليلاً عن JDBCtemplate في الربيع. على الرغم من أننا قمنا بتنفيذ طريقة اتصال القالب + وضع الاتصال أعلاه ، إلا أنه يبدو "قبيحًا" قليلاً مقارنة بـ JDBCtemplate في الربيع. يقدم Spring مفاهيم Rowmapper و ResultSetExtractor. واجهة RowMapper مسؤولة عن معالجة صف معين من البيانات. على سبيل المثال ، يمكننا العمل على صف معين من السجلات في طريقة MAPROW ، أو تغليفها في الكيان. ResultSetExtractor هو مستخرج مجموعة بيانات ، وهو مسؤول عن اجتياز ResultSet ومعالجة البيانات وفقًا للقواعد الموجودة في RowMapper. الفرق بين RowMapper و ResultSetExtractor هو أن RowMapper يعالج صفًا معينًا من البيانات ويعيد كائن كيان. يقوم ResultSetExtractor بمعالجة مجموعة بيانات وإرجاع مجموعة من الكائنات.
بالطبع ، ما سبق هو مجرد المبادئ الأساسية لتنفيذ الربيع jdbctemplate. قام Spring JDBCtemplate بمزيد من الأشياء ، مثل تغليف جميع العمليات الأساسية في واجهة JDBCOPERES ، واستخدام JDBCACCESSSER لإدارة استثناءات بيانات البيانات والتحويل.
ما سبق هو كل شيء عن هذا المقال ، آمل أن يكون مفيدًا لتعلم الجميع.