مكتوبة من قبل:
بالأمس قمت بتسجيل التصميم الأولي لبرنامج دردشة المقبس ، لقد أخذت الوقت الكافي للكتابة على مدونتي. كان التصميم العام لهذا البرنامج. للاكتمال ، سأقوم اليوم بتسجيل تصميم جانب الخادم بالتفصيل. ستنشر الصفحة الرئيسية مخطط التصميم العام لبرنامج دردشة المقبس ، كما هو موضح أدناه:
وصف الوظيفة:
يحتوي الخادم على عمليتين رئيسيتين: إحداهما هو حظر مقبس العميل المستلم وأداء معالجة الاستجابة ، والآخر هو اكتشاف نبضات العميل. إذا لم يرسل العميل نبضات القلب لفترة من الوقت ، فقم بإزالة العميل ، وقم بإنشاء Serversocket ، ثم ابدأ تجمعين مؤشرات ترابط للتعامل مع هذين الأمرين (NewFixedThreadPool ، NewsCheduleDthreadPool). فئات المعالجة المقابلة هي SocketDispatcher و SocketSchedule. يتم توزيع SocketDispatcher على Sockethandlers مختلف وفقًا لطلبات المقبس المختلفة. يضيف SocketWrapper غلاف قذيفة إلى المقبس ، ويسجل أحدث وقت تفاعل للمقبس مع Socketholder يخزن مجموعة المقبس التي تتفاعل حاليًا مع الخادم.
تطبيق محدد:
[server.java]
الخادم هو مدخل الخادم. يتم تشغيل ServersOcket بواسطة طريقة START () للخادم ، ثم يحجب طلب العميل المستلم ويسلمه إلى SocketDispatcher للتوزيع. يتم تشغيل SocketDispatcher بواسطة مجموعة مؤشرات ترابط من نوع NewFixedThread. عندما يتجاوز عدد الاتصالات الحد الأقصى للبيانات ، سيتم معالجتها بواسطة قائمة الانتظار. يتم استخدام ScheduleAtfixedrate لبدء حلقة توقيت SocketSchedule للاستماع إلى حزمة نبضات العميل. كلا النوعين ينفذون الواجهة القابلة للتشغيل. ما يلي هو رمز الخادم:
package yaolin.chat.server ؛ import java.io.ioException ؛ استيراد java.net.serversocket ؛ import java.util.date ؛ import java.util.concurrent.executorservice ؛ import java.util.concurrent.executors ؛ import java.Util.Util.scurent.schedexexextervice ؛ java.util.concurrent.timeUnit ؛ استيراد yaolin.chat.common.constantvalue ؛ استيراد yaolin.chat.util.loggerutil ؛/*** خادم* Author yaolin*/خادم الفئة العامة {خادم خاص خاص ؛ تجمع الخاصين النهائيين للخدمة النهائية ؛ server public () يلقي ioException {server = new serversoCkE (constantValue.server_port) ؛ pool = Executors.NewFixedThreadPool (constantValue.max_pool_size) ؛ } public void start () {try {ScripedExecutorService thement = Executors.NewScheduledThreadPool (1) ؛ // مشاهدة الكلب. استثناء؟؟ الجدول الزمني. بينما (صحيح) {pool.execute (socketDispatcher جديد (server.accept ())) ؛ loggerUtil.info ("قبول عميل في" + تاريخ جديد ()) ؛ }} catch (ioException e) {pool.shutdown () ؛ }} public static void main (string [] args) {try {new server (). start () ؛ } catch (ioException e) {loggerUtil.error ("فشل Server START! ->" + E.GetMessage () ، e) ؛ }}}[SocketDispatcher.java]
الخادم هو مجرد مدخل الخادم ومركز الأوامر. SocketDispatcher هو مركز الأوامر للخادم. يقوم بتوزيع طلبات أنواع الرسائل المختلفة من العميل ، مما يسمح لـ Sockethandlers المختلفة بمعالجة طلبات الرسائل المقابلة. هنا ، يستخدم تفاعل الرسالة بين الخادم والعميل بيانات JSON. جميع فئات الرسائل ترث الأساس ، لذلك يتم تحويل البيانات المستلمة إلى نوع الأساس ، ثم يتم الحكم على النوع. (وحدة نوع البيانات تنتمي إلى الوحدة النمطية المشتركة). تجدر الإشارة هنا إلى أنه عندما يكون نوع الرسالة نوعًا من الملفات ، فسوف ينام لتكوين فاصل التنفيذ ، بحيث يمكن أن يكون لدى FileHandler الوقت لقراءة دفق الملف وإعادة تقديمه إلى العميل المحدد ، دون إدخال الحلقة التالية على الفور للحكم على نوع الرسالة (قد يكون التصميم مشكلة بعض الشيء هنا ، ولكن القيام بذلك للوقت). فيما يلي رمز SocketDispatcher:
/** * SocketDispatcher * * author yaolin */public class SocketDispatcher تنفذ Runnable {private Final Socket ؛ SocketDispatcher العامة (مأخذ التوصيل) {this.socket = socket ؛ } Override public void run () {if (socket! = null) {while (! socket.isclosed ()) {try {inputStream is = socket.getInputStream () ؛ خط السلسلة = فارغ ؛ StringBuffer SB = NULL ؛ if (is.available ()> 0) {bufferedReader bufr = new BufferEdReader (new inputStreamReader (IS)) ؛ sb = new StringBuffer () ؛ بينما (is.available ()> 0 && (line = bufr.ReadLine ())! = null) {sb.append (line) ؛ } loggerUtil.trach ("receed [" + sb.toString () + "] at" + new date ()) ؛ رسالة basemessage = json.parseObject (sb.toString () ، basemessage.class) ؛ Switch (message.gettype ()) {case messageType.alive: handlerfactory.gethandler (messageType.alive) .handle (Socket ، sb.toString ()) ؛ استراحة؛ case messageType.Chat: HandlerFactory.Gethandler (messageType.Chat) .Handle (Socket ، SB.ToString ()) ؛ استراحة؛ case messageType.file: handlerfactory.gethandler (messageType.file) .handle (socket ، sb.toString ()) ؛ استراحة؛ case messageType.file: handlerfactory.gethandler (messageType.file) .handle (socket ، sb.toString ()) ؛ loggerUtil.trach ("Sever: توقف مؤقت لاستلام الملف") ؛ thread.sleep (constantvalue.message_period) ؛ استراحة؛ case messageType.login: handlerfactory.gethandler (messageType.login) .handle (Socket ، Sb.ToString ()) ؛ استراحة؛ Case messageType.logout: Break ؛ case messageType.register: handlerfactory.gethandler (messageType.register) .handle (socket ، sb.toString ()) ؛ استراحة؛ }} آخر {thread.sleep (constantValue.Message_Period) ؛ }} catch (استثناء e) {// catch all handler stisplder thauggerutil.error ("socketDispatcher error! }}}}}}[SocketSchedule.java]
فئة أخرى (مكون) مرتبطة مباشرة بالخادم هي SocketSchedule. SocketSchedule مسؤول بشكل أساسي عن اكتشاف ما إذا كان آخر وقت التفاعل بين العميل والخادم يتجاوز الحد الأقصى للوقت المسموح به في تكوين النظام. إذا تجاوز الأمر ، فسيتم إزالة مقبس العميل من الخادم ، وإلا فإن أحدث وقت للتفاعل بين العميل والخادم سيتم تحديثه. فيما يلي التطبيقات المحددة:
/** * قم بإزالة المقبس من Socketholder إذا كان LastAlivetime> time_out * author yaolin * */socketschedule public cloxetschedule runnable {override public void run () {for (string key: socketholder.keyset ()) if (wrapper! = null && wrapper.getlastalivetime ()! = null) {if ((new date (). getTime ()) - closper.getlastalivetime (). }}}}}}[Socketholder.java ، SocketWrapper.java]
من الكود أعلاه ، يمكننا أن نرى أن SocketSchedule#Run () هو مجرد حكم بسيط للوقت. ما هو ذي معنى حقا هو Socketholder و SocketWrapper. يضيف SocketWrapper غلاف قذيفة إلى المقبس. يقوم Socketholder بتخزين جميع العملاء الذين يتفاعلون مع الخادم خلال الوقت الصحيح الحالي. تم تحديد Socketholder بشكل فريد من قبل العميل (اسم المستخدم هنا). كمفتاح ، يتم تخزين المقبس الذي يوجد فيه العميل كزوج من القيمة الرئيسية. يتم استخدام منطق المعالجة لـ Socketholder#FlushClientStatus () لإخطار العملاء الآخرين بالحالة عبر الإنترنت/غير متصل بالعميل الحالي. يرد أدناه التنفيذ المحدد لهاتين الفئتين:
/** * ملفوف ، socketschedule قم بإزالة المقبس إذا lastAlivetime> time_out * author yaolin * */public class SocketWrapper {private Socket ؛ تاريخ خاص LastAlivetime ؛ // Full Constructor Public SocketWrapper (Socket Socket ، Date LastAlivetime) {this.socket = socket ؛ this.lastalivetime = lastAlivetime ؛ } المقبس العام getSocket () {return Socket ؛ } public void setSocket (Socket Socket) {this.socket = socket ؛ } التاريخ العام getLastalivetime () {return lastalivetime ؛ } public void setlastalivetime (date lastAlivetime) {this.lastalivetime = lastAlivetime ؛ }} /** * Socketholder * @Author yaolin */public class Socketholder {private static concurrentMap <string ، socketWrapper> listsocketwrap = concurrenthashmap <string ، socketWrapper> () ؛ مجموعة ثابتة عامة <string> keyset () {return listsocketwrap.keyset () ؛ } SocketWrapper الثابتة العامة GET (مفتاح السلسلة) {return listsocketwrap.get (key) ؛ } pub static void pub (مفتاح السلسلة ، قيمة socketWrapper) {listsocketwrap.put (المفتاح ، القيمة) ؛ FlushClientStatus (مفتاح ، صحيح) ؛ } socketWrapper static remove (مفتاح السلسلة) {flushClientStatus (المفتاح ، false) ؛ الإرجاع listsocketwrap.remove (مفتاح) ؛ } public static void clear () {listsocketWrap.clear () ؛ } /** * <pre> المحتوى: {username: "" ، flag: false} </pre> * param flag true: put ، false: remove ؛ */ private static void flushClientStatus (مفتاح السلسلة ، العلم المنطقي) {clientNotifyDto dto = new ClientNotifyDto (flag ، key) ؛ returnMessage rm = new ReturnMessage (). rm.setfrom (constantValue.server_name) ؛ لـ (string toKey: listsocketwrap.keyset ()) {if (! toKey.equals (key)) {// لا ترسل إلى self rm.setto (tokey) ؛ socketWrapper wrap = listsocketwrap.get (tokey) ؛ if (wrap! = null) {sendhelper.send (wrap.getSocket () ، rm) ؛ }}}}}}[Sockethandler.java ، Handlerfactory.java ، otherlylerimpl.java]
يتيح SocketDispatcher مختلف Sockethandlers للتعامل مع طلبات الرسائل المقابلة. إن تصميم Sockethandler هو في الواقع مجموعة بسيطة من مكونات المصنع (يتم نقل عودة الإرجاع مؤقتًا بواسطة Sendhelper ، لكنه لم يتم استخدامه في الوقت الحالي. لقد تم تحديده ، ولا يزال يتم إعطاؤه هنا). مخطط الفصل الكامل هو كما يلي:
ويرد رمز هذا القسم أدناه. من أجل تقليل المساحة ، يتم جمع جميع التعليمات البرمجية التي تنفذها المعالج.
/** * Sockethandler * Author yaolin */الواجهة العامة Sockethandler {/** * التعامل مع مقبس العميل */مقبض الكائن العام (عميل المقبس ، بيانات الكائن) ؛} /** * SockethandlerFactory * author yaolin */public class HandlerFactory {// لا يمكن إنشاء مثيل معالج خاص () {} Sockethandler gethandler العام الثابت (type) Case messageType.Chat: Return New Chathandler () ؛ case messageType.login: إرجاع loginHandler جديد () ؛ // case messageType.Return: // return new Returnhandler () ؛ case messageType.logout: return new logouthandler () ؛ Case messageType.register: Return New RecordHandler () ؛ Case messageType.file: إرجاع FileHandler () جديد ؛ } إرجاع فارغ ؛ // nullPointException}} /** * alivesockethandler * Author yaolin */public class alivehandler تنفذ sockethandler {/** * @return null */Override public compition handle (socket client ، data abound) {if (data! if (stringutil.isnotempty (message.getFrom ())) {socketWrapper clospper = socketholder.get (message.getFrom ()) ؛ if (wrapper! = null) {clospper.setlastalivetime (new date ()) ؛ // Keep Socket ... Socketholder.put (message.getFrom () ، Wrapper) ؛ }}} return null ؛ }} /** * Chathandler * * Author yaolin */Class Public Class Chathandler تنفذ Sockethandler {Override HOUBLE HOUBLE (عميل المقبس ، بيانات الكائن) {if (data! = null) {chatmessage message = json.parsebject (data.toString () ، chatmessage.class) ؛ if (stringutil.isnotempty (message.getFrom ()) && stringutil.isnotempty (message.getto ())) {// موجودة وإرسال if (socketholder.keyset (). message.setowner (المالك) ؛ // سيتم عرض المالك if (constantValue.to_all.equals (message.getto ())) {// On-to-all // to_all tab سيتم تحديده ؛ message.setFrom (constantValue.to_all) ؛ لـ (مفتاح السلسلة: socketholder.keyset ()) {// أرسل أيضًا إلى ملف SocketWrapper الذاتي = socketholder.get (المفتاح) ؛ if (wrapper! = null) {sendhelper.send (clospper.getSocket () ، message) ؛ }}} else {// On-to-One SocketWrapper clospper = socketholder.get (message.getto ()) ؛ if (wrapper! = null) {// owner = from sendhelper.send (claspper.getSocket () ، message) ؛ // أيضا إرسال إلى Self // to tab سيتم تحديد ؛ message.setfrom (message.getto ()). setto (المالك) ؛ SendHelper.send (العميل ، الرسالة) ؛ }}}}} return null ؛ }} تنفذ FileHandler العام public Sockethandler {Override Public Object Handle (عميل المقبس ، بيانات الكائن) {if (client! = null) {fileMessage message = json.parsebject (data.toString () ، filemessage.class) ؛ if (stringutil.isnotempty (message.getFrom ()) && stringutil.isnotempty (message.getto ())) {// موجودة وإرسال if (socketholder.keyset (). socketholder.get (message.getto ()) ؛ if (wrapper! = null) {sendhelper.send (clospper.getSocket () ، message) ؛ حاول {if (client! = null && clospper.getSocket ()! = null && message.getSize ()> 0) {inputStream is = client.getInputStream () ؛ OutputStream OS = clospper.getSocket (). getOutputStream () ؛ int total = 0 ؛ بينما (! client.isclosed () &&! wrapper.getSocket (). isClosed ()) {if (is.available ()> 0) {byte [] buff = new byte [constantValue.buff_size] ؛ int len = -1 ؛ بينما (is.available ()> 0 && (len = iS.Read (buff))! = -1) {os.write (buff ، 0 ، len) ؛ المجموع += لين ؛ loggerUtil.debug ("إرسال Buff [" + len + "]") ؛ } os.flush () ؛ if (total> = message.getSize ()) {loggerUtil.info ("إرسال Buff [OK]") ؛ استراحة؛ }}} // بعد إرسال ملف // إرسال نتائج ReturnMessage بنجاح = new ReturnMessage (). setKey (key.tip) .SetSuccess (true) .setContent (i18n.info_file_send_succissistly) ؛ result.setFrom (message.getto ()). SendHelper.send (العميل ، النتيجة) ؛ // استقبال result. SendHelper.send (clospper.getSocket () ، نتيجة) ؛ }} catch (استثناء e) {loggerUtil.Error ("فشل ملف فشل!" + e.getMessage () ، e) ؛ }}}}}}} return null ؛ }} /** * loginHandler * * Author yaolin * */public class loginHandler تنفذ sockethandler {private usrservice usrservice = new usrservice () ؛ Override Public Object Handle (Socket Client ، Data Object) {returnMessage result = new ReturnMessage () ؛ النتيجة. if (data! = null) {loginMessage message = json.parseObject (data.toString () ، loginMessage.class) ؛ if (stringUtil.isnotempty (message.getusername ()) && stringutil.isnotempty (message.getPassword ())) {if (usrservice.login (message.getusername () ، message.getPassword ()! = null) {result.setsuccess (true) ؛ } آخر {result.setMessage (i18n.info_login_error_data) ؛ } result.setFrom (constantValue.server_name) .Setto (message.getUserName ()) ؛ } آخر {result.setMessage (i18n.info_login_empty_data) ؛ } // بعد تسجيل الدخول result.setKey (key.login) ؛ if (result.issuccess ()) {// Hold Socket Socketholder.put (result.getto () ، socketWrapper (عميل ، تاريخ جديد ())) ؛ } sendhelper.send (العميل ، النتيجة) ؛ if (result.issuccess ()) {// إرسال قائمة user clientistuserdto dto = new ClientListUserDto () ؛ dto.setListuser (socketholder.keyset ()) ؛ result.setContent (DTO) .SetKey (key.listuser) ؛ SendHelper.send (العميل ، النتيجة) ؛ }} الإرجاع null ؛ }} الفئة العامة logouthandler تنفذ Sockethandler {Override Public Object Handle (عميل المقبس ، بيانات الكائن) {if (data! = null) {logoutMessage message = json.parseObject (data.toString () ، logoutmessage.class) ؛ if (message! = null && stringutil.isnotempty (message.getFrom ())) {socketWrapper wrapper = socketholder.get (message.getFrom ()) ؛ مأخذ التوصيل = clospper.getSocket () ؛ if (socket! = null) {try {socket.close () ؛ مقبس = فارغ ؛ } catch (استثناء تجاهل) {}} socketholder.remove (message.getFrom ()) ؛ }} الإرجاع null ؛ }} تنفذ registerHandler من الطبقة العامة Sockethandler {usrservice usrservice = new usrservice () ؛ Override Public Object Handle (Socket Client ، Data Object) {returnMessage result = new ReturnMessage () ؛ النتائج. if (data! = null) {registerMessage message = json.parseObject (data.toString () ، registerMessage.Class) ؛ if (stringUtil.isnotempty (message.getUserName ()) && stringutil.isnotempty (message.getPassword ())) {if (usrservice.register (message.getusername () ، message.getPassword ()! = null) } آخر {result.setMessage (i18n.info_register_client_exist) ؛ }} آخر {result.setMessage (i18n.info_register_empty_data) ؛ } if (stringUtil.isnotempty (message.getuserName ())) {result.setto (message.getUserName ()) ؛ } // بعد التسجيل result.setKey (key.register) ؛ SendHelper.send (العميل ، النتيجة) ؛ } إرجاع فارغ ؛ }} /** * استخدم SendHelper لإرسال ReturnMessage ، * see yaolin.chat.server.socketDispatcher#run () * author yaolin */ @ @dreemated class public returnler reportler sockethandler (ReturnMessage) البيانات ؛ if (stringutil.isnotempty (message.getFrom ()) && stringutil.isnotempty (message.getto ())) {socketWrapper wrap = socketholder.get (message.getto ()) ؛ if (wrap! = null) {sendhelper.send (wrap.getSocket () ، message) ؛ }}} return null ؛ }}أعمال المستخدم:
بالإضافة إلى Sockets ، يحتوي الخادم أيضًا على عمل محدد صغير ، أي تسجيل المستخدم ، وتسجيل الدخول ، وما إلى ذلك. هنا ندرج ببساطة فئتين من usr و usrservice. لم يتم تنفيذ هذه الشركات في الوقت الحالي. لا أنوي تقديم إطار ORM في هذا البرنامج ، لذلك كتبت مجموعة من DBUTIL (ليتم تحسينها) ونشرها هنا.
يتم إجراء التحقق البسيط فقط هنا ، ولا يستمر في تخزينه في DB. هنا usr و usrservice:
الطبقة العامة usr {private long id ؛ اسم المستخدم الخاص بالسلسلة الخاصة ؛ كلمة مرور السلسلة الخاصة ؛ Public Long getId () {return id ؛ } public void setId (id long) {this.id = id ؛ } السلسلة العامة getUserName () {return username ؛ } public void setusername (string username) {this.userName = username ؛ } السلسلة العامة getPassword () {return password ؛ } public void setPassword (سلسلة كلمة مرور) {this.password = password ؛ }} ! سجل usr العام (اسم المستخدم ، كلمة مرور السلسلة) {if (stringUtil.isempty (اسم المستخدم) || stringutil.isempty (كلمة المرور)) {return null ؛ } if (db.containskey (username)) {return null ؛ // يخرج؛ } usr usr = جديد usr () ؛ usr.setusername (اسم المستخدم) ؛ usr.setPassword (md5util.getmd5code (كلمة المرور)) ؛ db.put (اسم المستخدم ، usr) ؛ إرجاع USR ؛ } تسجيل الدخول العام usr (اسم المستخدم ، كلمة مرور السلسلة) {if (stringUtil.isempty (اسم المستخدم) || stringutil.isempty (password)) {return null ؛ } if (db.containskey (اسم المستخدم)) {usr usr = db.get (اسم المستخدم) ؛ if (md5util.getmd5code (password) .equals (usr.getPassword ())) {return usr ؛ }} الإرجاع null ؛ }} هنا أداة dbutil:
/*** يجب تعديل DBUTILS // TODO وتحسينه !! * Author yaolin */public class dbutil {// قم بإجراء اتصال مستخدم مرارًا وتكرارًا القائمة النهائية الثابتة مرارًا وتكرارًا <connection> cache = new LinkedList <Connate> () ؛ عنوان url Static Static الخاص ؛ سائق سلسلة ثابتة خاصة ؛ مستخدم سلسلة ثابتة خاصة ؛ كلمة مرور السلسلة الثابتة الخاصة ؛ تصحيح Boolean الثابت الخاص ؛ ثابت {inputStream هو = dbutil.class.getResourCeasStream ("/db.properties") ؛ حاول {Properties p = new properties () ؛ p.load (IS) ؛ url = p.getProperty ("url") ؛ Driver = p.getProperty ("Driver") ؛ user = p.getProperty ("user") ؛ كلمة المرور = p.getProperty ("كلمة المرور") ؛ // فقط للتصحيح جرب {debug = boolean.valueof (p.getProperty ("debug")) ؛ } catch (استثناء تجاهل) {debug = false ؛ }} catch (استثناء e) {رمي new runTimeException (e) ؛ } أخيرًا {if (is! = null) {try {is.close () ؛ هو = فارغ. } catch (استثناء تجاهل) {}}}} اتصال ثابت عام getConnection () {if (cache.isempty ()) {cache.add (makeConnection ()) ؛ } connection conn = null ؛ int i = 0 ؛ حاول {do {conn = cache.remove (i) ؛ } بينما (conn! = null && conn.isclosed () && i <cache.size ()) ؛ } catch (استثناء تجاهل) {} جرب {if (conn == null || conn.isclosed ()) {cache.add (makeConnection ()) ؛ conn = cache.remove (0) ؛ } return conn ؛ } catch (استثناء e) {رمي new runTimeException (e) ؛ }}} إغلاق الفراغ الثابت المزامن العام (اتصال الاتصال) {try {if (connection! = null &&! connection.isclosed ()) {if (debug) debug ("connection!") ؛ Cache.Add (اتصال) ؛ }} catch (sqlexception تجاهل) {}} استعلام الكائن الثابت العام (سلسلة sql ، resultsetmapper mapper ، كائن ... args) {if (debug) debug (sql) ؛ Connection conn = getConnection () ؛ أعدت PS = NULL ؛ resultset rs = null ؛ نتيجة الكائن = فارغة ؛ حاول {ps = conn.preparestatement (sql) ؛ int i = 1 ؛ لـ (كائن كائن: args) {ps.setObject (i ++ ، كائن) ؛ } rs = ps.executequery () ؛ النتيجة = mapper.mapper (rs) ؛ } catch (استثناء e) {رمي new runTimeException (e) ؛ } أخيرًا {try {if (rs! = null) {rs.close () ؛ rs = فارغة ؛ } if (ps! = null) {ps.Close () ؛ PS = NULL ؛ }} catch (استثناء تجاهل) {}} يغلق (conn) ؛ نتيجة العودة } int static int modify (String SQL ، Object ... args) {if (debug) debug (sql) ؛ Connection conn = getConnection () ؛ أعدت PS = NULL ؛ int row = 0 ؛ حاول {ps = conn.preparestatement (sql) ؛ int i = 1 ؛ لـ (كائن كائن: args) {ps.setObject (i ++ ، كائن) ؛ } row = ps.executeupdate () ؛ } catch (استثناء e) {رمي new runTimeException (e) ؛ } أخيرًا {try {if (ps! = null) {ps.Close () ؛ PS = NULL ؛ }} catch (استثناء تجاهل) {}} يغلق (conn) ؛ صف العودة } int static int [] batch (list <string> sqls) {if (debug) debug (sqls.toString ()) ؛ Connection conn = getConnection () ؛ بيان stmt = فارغة ؛ int [] صف ؛ حاول {stmt = conn.createstatement () ؛ لـ (String SQL: SQLS) {stmt.addbatch (sql) ؛ } row = stmt.executeBatch () ؛ } catch (استثناء e) {رمي new runTimeException (e) ؛ } أخيرًا {try {if (stmt! = null) {stmt.close () ؛ STMT = فارغة ؛ }} catch (استثناء تجاهل) {}} يغلق (conn) ؛ صف العودة } public static int [] batch (string sql ، reparedStatementSetter setter) {if (debug) debug (sql) ؛ Connection conn = getConnection () ؛ أعدت PS = NULL ؛ int [] صف ؛ حاول {ps = conn.preparestatement (sql) ؛ setter.setter (ps) ؛ الصف = ps.executeBatch () ؛ } catch (استثناء e) {رمي new runTimeException (e) ؛ } أخيرًا {try {if (ps! = null) {ps.Close () ؛ PS = NULL ؛ }} catch (استثناء تجاهل) {}} يغلق (conn) ؛ صف العودة } اتصال ثابت خاص makeConnection () {try {class.forname (driver) .NewInstance () ؛ Connection conn = drivermanager.getConnection (url ، المستخدم ، كلمة المرور) ؛ إذا (تصحيح) تصحيح ("إنشاء اتصال!") ؛ إرجاع كون ؛ } catch (استثناء e) {رمي new runTimeException (e) ؛ }} debug private static void (سلسلة sqls) {simpleDateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss") ؛ System.out.println (sdf.format (new date ()) + "debug" + thread.currentThread (). getId () + "--- [ }} /** * ReparedStatementSetter * Author yaolin */واجهة عامة أعدت stateMentSetter {public void setter (preparedStatement ps) ؛} /** * resultsetMapper * Author yaolin */واجهة عامة resultsetMapper {كائن عام mapper (resultset rs) ؛} تنزيل رمز المصدر: العرض التوضيحي
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.