Artikel ini adalah bagian kedua dari mengirim pesan teks. Di sini kami memperkenalkan cara membatasi frekuensi mengirim pesan teks ke pengguna yang sama (berdasarkan nomor ponsel dan IP).
1. Gunakan sesi
Jika itu adalah program Web, juga dimungkinkan untuk merekam terakhir kali dikirim dalam sesi, tetapi dapat dilewati. Yang paling sederhana adalah memulai kembali secara langsung browser atau menghapus cache dan data lain yang dapat menandai sesi, sehingga catatan dalam sesi dapat dilewati. Meskipun banyak orang tidak profesional di komputer dan belum mempelajarinya. Tetapi kita perlu mencatat bahwa alasan untuk membatasi frekuensi pengiriman adalah untuk mencegah "bom SMS", yaitu, seseorang secara jahat dan sering meminta untuk mengirim pesan teks ke nomor ponsel. Karena itu, orang ini dapat memahami pengetahuan ini.
Selanjutnya, kami menggunakan batas data "global" untuk mengirim frekuensi ke pengguna yang sama. Mari kita lakukan beberapa "persiapan" bekerja terlebih dahulu.
2. Tentukan Antarmuka dan Kelas Entitas
Kelas entitas yang kita butuhkan adalah sebagai berikut:
Smsentity.java
SmSentity kelas publik {private integer ID; ponsel string pribadi; ip string pribadi; tipe integer pribadi; waktu tanggal pribadi; captcha string pribadi; // hilangkan metode konstruktor dan metode pengambil dan setter}Antarmuka penyaringan adalah sebagai berikut:
Smsfilter.java
antarmuka publik smsfilter { / *** inisialisasi filter* / void init () melempar pengecualian; /*** Tentukan apakah pesan teks dapat dikirim. * @param smsentity Konten pesan teks yang akan dikirim * @return jika dapat dikirim, itu akan mengembalikan true, jika tidak, ia akan mengembalikan filter false */ boolean (smsentity smsentity); / *** Hancurkan filter*/ void dashar ();}3. Kode utama
Untuk membatasi frekuensi pengiriman, Anda perlu merekam nomor ponsel tertentu (IP) dan waktu terakhir kali Anda mengirim pesan teks. Sangat cocok untuk diselesaikan peta. Di sini kami pertama kali menggunakan ConcurrentMap untuk mengimplementasikannya:
Frekuensifilter.java
Frekuensi kelas publik mengimplementasikan smsfilter { / *** Kirim Interval, Unit: Milliseconds* / Private Long SendInterval; private concurrentMap <string, long> sendaddressmap = new concurrenthashmap <> (); // Beberapa kode yang tidak berguna dihilangkan @Override public boolean filter (smsentity smsentity) {if (setSendTime (smsentity.getMobile ()) && setSendTime (smsentity.getip ())) {return true; } return false; } /*** Ubah waktu pengiriman ke waktu saat ini. * Jika interval waktu dari yang terakhir dikirim lebih besar dari {@link #SendIval}, atur waktu pengiriman ke waktu saat ini. Kalau tidak, tidak ada konten yang akan dimodifikasi. * * @param ID Kirim Nomor Ponsel atau IP * @Return Jika waktu pengiriman berhasil dimodifikasi ke waktu saat ini, itu akan mengembalikan true. Jika tidak, itu akan mengembalikan false */ private boolean setSendtime (string id) {long currentTime = system.currentTimeMillis (); Long SendTime = sendaddressmap.putifabsent (id, currentTime); if (sendTime == null) {return true; } long nextCansEndtime = sendTime + sendInterval; if (currentTime <nextCansEndtime) {return false; } return sendaddressmap.replace (id, sendtime, currentTime); }}Di sini, logika utama diimplementasikan dalam metode SetSendtime :
Baris 25-28: Pertama, dengan asumsi bahwa pengguna mengirim SMS untuk pertama kalinya, maka waktu saat ini harus dimasukkan ke dalam sendaddressmap. Jika putifabsent mengembalikan nol, itu berarti bahwa pengguna memang mengirim SMS untuk pertama kalinya, dan waktu saat ini telah dimasukkan ke dalam peta, dan itu dapat dikirim.
Baris 30-33: Jika pengguna tidak mengirim SMS untuk pertama kalinya, maka perlu untuk menentukan apakah waktu dan interval saat ini mengirim SMS terakhir kali dan interval waktu kurang dari interval waktu pengiriman. Jika kurang dari interval waktu pengiriman, maka itu tidak dapat dikirim.
Baris 35: Jika interval waktu cukup besar, maka Anda perlu mencoba mengatur waktu pengiriman ke waktu saat ini.
1) Maka Anda dapat mengulangi baris 25-35 untuk memastikan bahwa mereka benar-benar benar.
2) Anda juga dapat secara langsung berpikir bahwa itu tidak dapat dikirim, karena meskipun waktu teoretis untuk "pelaksanaan baris 26-35" mungkin lebih besar dari "interval kirim", berapa probabilitasnya? Pada dasarnya dapat diabaikan.
Kode ini menerapkan batasan frekuensi, tetapi jika hanya ada "dalam" tetapi tidak "keluar", maka konten yang ditempati oleh SendAddressMap akan menjadi lebih besar dan lebih besar sampai pengecualian outofmemoryerror dihasilkan. Selanjutnya, kami akan menambahkan kode untuk membersihkan data yang sudah kadaluwarsa secara teratur.
4. Bersihkan data yang sudah kadaluwarsa
Frekuensifilter.java
/*** Berdasarkan kode di atas, tambahkan kode berikut*/frekuensi kelas publik. timer private timer = timer baru ("sms_frequency_filter_clear_data_thread"); @Override public void init () {timer.schedule (timerKask baru () {@Override public void run () {cleanSendaddressMap ();}}, cleanMapInterval, cleanMapInterval); } / *** Hapus semua data yang kedaluwarsa di sendaddressmap* / private void cleanSendAddressMap () {long currentTime = system.currentTimeMillis (); Long ExpiresEndTime = CurrentTime - SendInterval; untuk (tombol string: sendaddressmap.keyset ()) {long sendTime = sendaddressMap.get (key); if (sendTime <ExpireSEndTime) {sendaddressmap.remove (key, sendTime); }}} @Override public void dashar () {timer.cancel (); }}Program ini tidak rumit. Mulailah timer dan jalankan metode CleanSendAddressMap setiap milidetik CleanMapinterval untuk membersihkan data yang sudah kadaluwarsa.
Metode CleanSendaddressMap pertama -tama mendapatkan waktu saat ini dan memperoleh nilai waktu berdasarkan waktu saat ini: Semua pesan teks dikirim setelah waktu ini, SMS tidak dapat dikirim lagi. Kemudian hapus semua pasangan nilai kunci dengan nilai lebih kecil dari nilai waktu ini dari seluruh peta.
Tentu saja, setelah menambahkan kode di atas, kode awal memiliki bug lain: ketika baris terakhir sendaddressmap.replace (id, sendtime, currentTime) gagal dieksekusi, tidak harus bahwa utas lain telah diganti, tetapi mungkin juga bahwa utas pembersih telah menghapus data. Jadi kita perlu memodifikasi beberapa baris terakhir dari metode setSendtime:
Frekuensifilter.java
private boolean setSendtime (string id) {// hilangkan kode sebelumnya if (sendaddressmap.replace (id, sendTime, currentTime)) {return true; } return sendaddressmap.putifabsent (id, currentTime) == null;}Jika penggantian berhasil di sini, maka kembalikan true secara langsung.
Jika penggantian tidak berhasil, maka mungkin utas lain telah diganti terlebih dahulu (dalam kasus pertama); Mungkin juga mereka telah dihapus oleh benang yang dibersihkan (dalam kasus kedua); Bahkan mungkin mereka telah dihapus oleh utas yang dibersihkan terlebih dahulu, dan utas lainnya telah memasukkan nilai waktu baru (dalam kasus ketiga).
Pada titik ini, kode yang membatasi waktu pengiriman selesai. Tentu saja, program ini memiliki bug kecil atau "fitur":
Jika pelanggan dengan IP "192.168.0.1" meminta untuk mengirim pesan teks ke nomor ponsel "12345678900", dan kemudian meminta untuk mengirim pesan teks ke nomor ponsel "12345678900" di dalam SendInterVal pada mesin dengan IP "192.168.0.2". Kemudian pesan teks tidak akan dikirim, dan terakhir kali nomor ponsel "12345678900" diatur ke waktu saat ini.
5. Contoh Penggunaan
Di bawah ini kami menyediakan lapisan server untuk menunjukkan cara mengintegrasikan kode dalam artikel sebelumnya dan artikel ini:
Smsservice.java
SMSService kelas publik {sms SMS pribadi; daftar pribadi <Msfilter> filter; template properti pribadi; // Beberapa kode dihilangkan/*** Kirim kode verifikasi** @param smsentity data dasar untuk mengirim pesan teks* @return jika pengiriman berhasil, kembalikan 0. jika tidak, kembalikan nilai lain. */ public int sendCaptcha (smsentity smsentity) {for (smsfilter filter: filter) {if (! filter.filter (smsentity)) {return 1; }} if (smsentity.register_type.equals (smsentity.getType ())) {sendRegistersMS (smsentity); } else {return 2; } return 0; } / *** Kirim kode verifikasi pendaftaran** @param smsentity data dasar untuk mengirim pesan teks* / private void sendregisterms (smsentity smsentity) {sms.sendMessage (smsentity.getMobile (), template.getproperty ("register"). Ganti ("{{captcha {" captcha {"{{" {{{" }}Kemudian, "suntikan" frekuensifilter dan asyncsmsml dalam artikel sebelumnya melalui metode set.
Di atas adalah semua tentang artikel ini, saya harap akan sangat membantu bagi semua orang untuk belajar pemrograman Java.