هذه المقالة هي الجزء الثاني من إرسال الرسائل النصية. نقدم هنا كيفية الحد من تواتر إرسال الرسائل النصية إلى نفس المستخدم (استنادًا إلى رقم الهاتف المحمول و IP).
1. استخدم الجلسة
إذا كان برنامج ويب ، فمن الممكن أيضًا تسجيل آخر مرة تم إرسالها في الجلسة ، ولكن يمكن تجاوزها. أبسط شيء هو إعادة تشغيل المتصفح مباشرة أو مسح ذاكرة التخزين المؤقت والبيانات الأخرى التي يمكن أن تضع علامة على الجلسة ، بحيث يمكن تجاوز السجلات في الجلسة. على الرغم من أن الكثير من الناس ليسوا محترفين في أجهزة الكمبيوتر ولم يتعلموا هذه. لكننا نحتاج إلى ملاحظة أن سبب الحد من التردد الإرسال هو منع "قنابل الرسائل القصيرة" ، أي شخص يطلب بشكل ضار وبشكل متكرر إرسال رسائل نصية إلى رقم هاتف محمول. لذلك ، قد يفهم هذا الشخص هذه المعرفة.
بعد ذلك ، نستخدم حد البيانات "العالمي" لإرسال التردد إلى نفس المستخدم. دعونا نفعل بعض العمل "التحضير" أولاً.
2. تحديد واجهات وفئات الكيانات
فصول الكيان التي نحتاجها على النحو التالي:
smsentity.java
الطبقة العامة smsentity {private integer id ؛ سلسلة متنقلة خاصة ؛ سلسلة IP الخاصة ؛ نوع عدد صحيح خاص ؛ وقت التاريخ الخاص ؛ سلسلة خاصة كابتشا ؛ // حذف طريقة المنشئ وطرق getter و setter}واجهة التصفية هي كما يلي:
smsfilter.java
الواجهة العامة smsfilter { / *** تهيئة المرشح* / void init () رمي الاستثناء ؛ /*** حدد ما إذا كان يمكن إرسال الرسالة النصية. * param smsentity محتوى الرسالة النصية المراد إرسالها * return إذا كان يمكن إرسالها ، فسوف يعود بشكل صحيح ، وإلا فإنه سيعود مرشح false */ boolean (smsentity smsentity) ؛ / *** تدمير الفلتر*/ void تدمير () ؛}3. الكود الرئيسي
للحد من تواتر الإرسال ، تحتاج إلى تسجيل رقم هاتف محمول معين (IP) ووقت آخر مرة أرسلت فيها رسالة نصية. من المناسب للغاية لإكمال الخريطة. نحن هنا نستخدم أولاً ConcurrentMap لتنفيذها:
الترددات
تنفذ الترددات العامة للطبقة العامة smsfilter { / *** إرسال الفاصل الزمني ، الوحدة: milliseconds* / private long sendInterval ؛ ConcurrentMap الخاص <string ، long> sendAddressMap = concurrenthashMap new concurrenthashMap <> () ؛ . } إرجاع خطأ ؛ } /*** قم بتعديل وقت الإرسال إلى الوقت الحالي. * إذا كان الفاصل الزمني من آخر إرسال أكبر من {link #sendinterval} ، فقم بتعيين الوقت إرسال إلى الوقت الحالي. خلاف ذلك ، لن يتم تعديل أي محتوى. * * @Param ID أرسل رقم الهاتف المحمول أو IP * @RETURN إذا تم تعديل وقت الإرسال بنجاح إلى الوقت الحالي ، فسوف يعود بشكل صحيح. خلاف ذلك ، سيعود false */ private boolean setSendTime (string id) {long currenttime = system.currentTimeMillis () ؛ recsTime طويل = sendAddressMap.putifabsent (معرف ، currenttime) ؛ if (sendtime == null) {return true ؛ } long nextCansEndTime = sendTime + sendInterval ؛ if (currenttime <nextCansEndTime) {return false ؛ } return sendaddressMap.replace (id ، sendtime ، currenttime) ؛ }}هنا ، يتم تنفيذ المنطق الرئيسي في طريقة setSendTime :
الأسطر 25-28: أولاً ، على افتراض أن المستخدم يرسل الرسائل القصيرة لأول مرة ، يجب وضع الوقت الحالي في sendaddressMap. في حالة إرجاع PutifabSent NULL ، فهذا يعني أن المستخدم يرسل بالفعل رسالة نصية قصيرة لأول مرة ، وقد تم وضع الوقت الحالي في الخريطة ، ويمكن إرساله.
الأسطر 30-33: إذا لم يرسل المستخدم رسالة نصية قصيرة لأول مرة ، فمن الضروري تحديد ما إذا كان الوقت والفاصل الزمني الحالي لإرسال الرسائل القصيرة في المرة الأخيرة والفاصل الزمني أقل من الفاصل الزمني المرسل. إذا كان أقل من الفاصل الزمني إرسال ، فلا يمكن إرساله.
السطر 35: إذا كان الفاصل الزمني كبيرًا بدرجة كافية ، فأنت بحاجة إلى محاولة تعيين وقت إرسال إلى الوقت الحالي.
1) ثم يمكنك تكرار الخطوط 25-35 للتأكد من أنها صحيحة تمامًا.
2) يمكنك أيضًا أن تفكر بشكل مباشر في أنه لا يمكن إرسالها ، لأنه على الرغم من أن الوقت النظري لـ "تنفيذ الأسطر 26-35" قد يكون أكبر من "إرسال الفاصل الزمني" ، فكم هو الاحتمال؟ يمكن تجاهله بشكل أساسي.
ينفذ هذا الكود من الحد من التردد ، ولكن إذا كان هناك فقط "في" ولكن ليس "خارج" ، فإن المحتوى الذي تشغله SendAddressMap سيصبح أكبر وأكبر حتى يتم إنشاء استثناء OutofMemoryError. بعد ذلك ، سنضيف الكود لتنظيف البيانات المنتهية الصلاحية بانتظام.
4. تنظيف البيانات منتهية الصلاحية
الترددات
/*** استنادًا إلى الكود أعلاه ، أضف الكود التالي*/الفئة العامة الترددات التي تنفذ smsfilter {private long cleanmapinterval ؛ TIMER Private Timer = New Timer ("sms_frequency_filter_clear_data_thread") ؛ Override public void init () {timer.schedule (new timertask () {Override public void run () {cleansendaddressMap () ؛}} ، cleanmapinterval ، cleanmapinterval) ؛ } / *** حذف جميع البيانات المنتهية في SendAddressMap* / private void cleansendaddressMap () {long currenttime = system.currentTimeMillis () ؛ Expires ExpiresTime = CurrentTime - SendInterval ؛ لـ (مفتاح السلسلة: SendAdressMap.KeySet ()) {long sendTime = sendAddressMap.get (مفتاح) ؛ if (sendTime <ExpiresendTime) {sendAddressMap.Remove (المفتاح ، sendtime) ؛ }}} Override public void destroy () {timer.cancel () ؛ }}هذا البرنامج غير معقد. ابدأ مؤقتًا وقم بتنفيذ طريقة CleansendadDressMap لكل ميلي ثانية من CleanMapinterval لتنظيف البيانات المنتهية.
تحصل طريقة CleanSendadDressMap أولاً على الوقت الحالي وتحصل على قيمة زمنية بناءً على الوقت الحالي: يتم إرسال جميع الرسائل النصية بعد هذا الوقت ، لا يمكن إرسال الرسائل القصيرة مرة أخرى. ثم احذف جميع أزواج القيمة الرئيسية بقيمة أصغر من هذه القيمة الزمنية من الخريطة بأكملها.
بالطبع ، بعد إضافة الكود أعلاه ، يكون للرمز الأولي خطأ آخر: عندما يفشل السطر الأخير SendAddressMap.replace (المعرف ، وقت الإرسال ، الوقت الحالي) في التنفيذ ، ليس بالضرورة استبدال مؤشرات الترابط الأخرى ، ولكن من الممكن أيضًا أن يكون مؤشر ترابط التنظيف قد حذف البيانات. لذلك نحن بحاجة إلى تعديل الأسطر القليلة الأخيرة من طريقة setSendTime:
الترددات
SetSendTime الخاص (معرف السلسلة) {// حذف الكود السابق if (sendAddressMap.replace (id ، sendtime ، currenttime)) {return true ؛ } return sendaddressMap.putifabsent (id ، currenttime) == null ؛}إذا نجح الاستبدال هنا ، فاحصل على TRUE مباشرة.
إذا لم ينجح الاستبدال ، فقد يتم استبدال مؤشرات الترابط الأخرى أولاً (في الحالة الأولى) ؛ قد يكون أيضًا حذفها بواسطة الخيط الذي تم تنظيفه (في الحالة الثانية) ؛ قد يكون حتى تم حذفها بواسطة الخيط الذي تم تنظيفه أولاً ، وقد أدخلت مؤشرات الترابط الأخرى قيم زمنية جديدة (في الحالة الثالثة).
في هذه المرحلة ، يتم الانتهاء من الرمز الذي يحد من وقت الإرسال. بالطبع ، يحتوي هذا البرنامج على خطأ صغير أو "ميزة":
إذا طلب عميل لديه IP "192.168.0.1" إرسال رسالة نصية إلى رقم الهاتف المحمول "12345678900" ، ثم يطلب إرسال رسالة نصية إلى رقم الهاتف المحمول "12345678900" داخل SendInterval على الجهاز مع IP "192.168.0.2". بعد ذلك ، لن يتم إرسال الرسالة النصية ، وتم تعيين آخر مرة من رقم الهاتف المحمول "12345678900" على الوقت الحالي.
5. أمثلة على الاستخدام
نوفر أدناه طبقة خادم لإظهار كيفية دمج الكود في المقالة السابقة وهذه المقالة:
smsservice.java
SMSSERVICE من الطبقة العامة {SMS SMS الخاصة ؛ قائمة خاصة <SmsFilter> مرشحات ؛ قالب الخصائص الخاصة ؛ // يتم حذف بعض الرموز/*** إرسال رمز التحقق** param smsentity البيانات الأساسية لإرسال الرسائل النصية* return إذا كان التقديم ناجحًا ، إرجاع 0. وإلا ، إرجاع القيم الأخرى. */ public int sendcaptcha (smsentity smsentity) {for (smsfilter filter: filters) {if (! filter.filter (smsentity)) {return 1 ؛ }} if (smsentity.register_type.equals (smsentity.gettype ())) {sendRegiStsms (smsentity) ؛ } آخر {return 2 ؛ } العودة 0 ؛ } / *** إرسال رمز التحقق من التسجيل** param smsentity البيانات الأساسية لإرسال الرسائل النصية* / private void sendregistersms (smsentity smsentity) {sms.sendmessage (smsentity.getmobile () ، template.getProperty ("register". }}ثم ، "حقن" الترددات و asyncsmsimpl في المقالة السابقة من خلال طريقة المجموعة.
ما سبق هو كل شيء عن هذا المقال ، آمل أن يكون من المفيد للجميع تعلم برمجة Java.