この記事は、テキストメッセージの送信の第2部です。ここでは、同じユーザーにテキストメッセージを送信する頻度を制限する方法を紹介します(携帯電話番号とIPに基づいて)。
1。セッションを使用します
Webプログラムの場合、セッションで送信された最後の時間を記録することもできますが、バイパスすることもできます。最も簡単なのは、セッションをマークする可能性のあるブラウザまたはクリアキャッシュやその他のデータを直接再起動することです。これにより、セッションのレコードをバイパスできます。多くの人々はコンピューターでは専門家ではなく、これらを学んでいません。ただし、送信頻度を制限する理由は、「SMS爆弾」、つまり悪意を持って頻繁にテキストメッセージを携帯電話番号に送信するように要求するのを防ぐためであることに注意する必要があります。したがって、この人はこの知識を理解するかもしれません。
次に、「グローバル」データ制限を使用して、同じユーザーに周波数を送信します。最初にいくつかの「準備」作業をしましょう。
2。インターフェイスとエンティティクラスを定義します
必要なエンティティクラスは次のとおりです。
smsentity.java
パブリッククラスsmsentity {private integer id;プライベートストリングモバイル;プライベート文字列IP;プライベート整数タイプ。プライベートデート時間;プライベートストリングキャプチャ; //コンストラクターメソッドとゲッターとセッターのメソッドを省略します}フィルタリングインターフェイスは次のとおりです。
smsfilter.java
パブリックインターフェイスsmsfilter { / ***フィルターの初期化* / void init()スロー例外。 /***テキストメッセージを送信できるかどうかを判断します。 * @param smsentity送信するテキストメッセージのコンテンツ * @returnが送信されると、trueを返します。 / ***フィルターを破壊*/ void Destroy();}3。メインコード
送信の頻度を制限するには、特定の携帯電話番号(IP)を記録し、最後にテキストメッセージを送信した時間を記録する必要があります。マップが完了するのに非常に適しています。ここでは、まずconcurrentMapを使用して実装します。
FuelcureFilter.java
パブリッククラスFrequencyFilterはsmsfilter { / ***間隔を送信します。 private concurrentmap <string、long> sendaddressmap = new concurrenthashmap <>(); //いくつかの役に立たないコードは、@Override public booleanフィルター(smsentity smsentity){setsendtime(smsentity.getmobile())&& setsendtime(smsentity.getip())){return true; } falseを返します。 } /***送信時間を現在まで変更します。 *最後に送信された時間間隔が{@link #sendinterval}より大きい場合、送信時間を現在に設定します。それ以外の場合、コンテンツは変更されません。 * * @ParamID携帯電話番号またはIPを送信 * @return送信時間が現在に正常に変更された場合、それはtrueに戻ります。それ以外の場合、false */ private boolean setsendtime(string id){long currenttime = system.currenttimemillis(); long sendime = sendaddressmap.putifabsent(id、currenttime); if(sendtime == null){return true; } long nextcansendtime = sendtime + sendInterval; if(cunrytime <nextcansendtime){return false; } sendAddressmap.Replace(id、sendtime、currenttime)を返します。 }}ここでは、主なロジックがSetSendtimeメソッドに実装されています。
25〜28行目:最初に、ユーザーが初めてSMSを送信すると仮定すると、現在の時刻をSendAddressMapに入れる必要があります。 pentifabsentがnullを返す場合、ユーザーが実際に初めてSMSを送信し、現在の時間がマップに入れられ、送信できます。
30〜33行目:ユーザーが初めてSMSを送信していない場合、SMSを最後に送信する時間と現在の間隔が送信時間間隔よりも少ないかどうかを判断する必要があります。送信時間間隔よりも少ない場合、送信できません。
35行目:時間間隔が十分に大きい場合は、送信時間を現在の時間に設定する必要があります。
1)その後、25〜35行目を繰り返して、それらが絶対に正しいことを確認できます。
2)「26〜35行目の実行」の理論的時間は「間隔を送信する」よりも大きいかもしれないが、確率はいくらですか?基本的に無視できます。
このコードは頻度の制限を実装しますが、「in」のみが「out」ではない場合、sendaddressmapが占めるコンテンツは、outofmemoryerror例外が生成されるまでますます大きくなります。次に、コードを追加して、期限切れのデータを定期的にクリーンアップします。
4.期限切れのデータをクリーンアップします
FuelcureFilter.java
/***上記のコードに基づいて、次のコードを追加します*/public class freucefilterはsmsfilter {private long mapinterval;プライベートタイマータイマー=新しいタイマー( "sms_frequency_filter_clear_data_thread"); @Override public void init(){timer.schedule(new timertask(){@override public void run(){cleansendadddressmap();}}、cleanmapinterval、cleanmapinterval); } / *** sendAddressMapのすべての期限切れのデータを削除* / private void cleansendaddressmap(){long currenttime = system.currenttimemillis(); long expiresEndtime = currentTime -sendInterval; for(string key:sendaddressmap.keyset()){long sendtime = sendaddressmap.get(key); if(sendtime <expiresEndtime){sendaddressmap.remove(key、sendtime); }}} @Override public void Destroy(){Timer.Cancel(); }}このプログラムは複雑ではありません。タイマーを開始し、CleanMapIntervalのミリ秒ごとにCleanSendAddressMapメソッドを実行して、期限切れのデータをクリーンアップします。
CleanSendAddressMapメソッドは、最初に現在の時間を取得し、現在の時間に基づいて時間値を取得します。すべてのテキストメッセージはこの時間以降に送信され、SMSは再び送信できません。次に、マップ全体からこの時間値よりも小さい値ですべてのキー価値ペアを削除します。
もちろん、上記のコードを追加した後、初期コードには別のバグがあります。最後の行SendAddressMap.Replace(ID、SendTime、CurrentTime)が実行に失敗すると、必ずしも他のスレッドが交換されているわけではありませんが、クリーニングスレッドがデータを削除した可能性もあります。したがって、setsendtimeメソッドの最後の数行を変更する必要があります。
FuelcureFilter.java
private boolean setsendtime(string id){//前のコードを省略if(sendaddressmap.replace(id、sendtime、currenttime)){return true; } return sendAddressmap.putifabsent(id、currenttime)== null;}ここで交換が成功した場合は、直接trueを返します。
交換が成功しない場合、他のスレッドが最初に置き換えられた可能性があります(最初の場合)。また、それらはクリーニングされたスレッドによって削除された可能性があります(2番目のケース)。最初にクリーニングされたスレッドによって削除され、他のスレッドが新しい時間値を挿入した可能性があります(3番目のケース)。
この時点で、送信時間を制限するコードが完了します。もちろん、このプログラムには小さなバグまたは「機能」があります。
IP「192.168.0.1」を持つ顧客が、携帯電話番号「12345678900」にテキストメッセージを送信するように要求し、IP「192.168.0.2」を備えたマシン上のsendInterval内の携帯電話番号「12345678900」にテキストメッセージを送信するよう要求した場合。テキストメッセージは送信されず、携帯電話番号「12345678900」の最後の時間は現在に設定されます。
5。使用の例
以下に、前の記事とこの記事でコードを統合する方法を示すサーバーレイヤーを示します。
smsservice.java
パブリッククラスSMSService {プライベートSMS SMS;プライベートリスト<SMSFILTER>フィルター。プライベートプロパティテンプレート。 //一部のコードは省略されています/***検証コードを送信** @param smsentityテキストメッセージを送信するための基本データ* @return送信が成功した場合、0を返します。それ以外の場合は、他の値を返します。 */ public int sendcaptcha(smsentity smsentity){for(smsfilterフィルター:フィルター){if(!filter.filter(smsentity)){return 1; }} if(smsentity.register_type.equals(smsentity.getType())){sendregistersms(smsentity); } else {return 2; } return 0; } / ***登録確認コードを送信** @param smsentityテキストメッセージを送信するための基本データ}}次に、以前の記事では、FuelfereFilterとasyncsmsimplを「注入」し、SETメソッドを介して「注入」します。
上記はこの記事に関するものです。誰もがJavaプログラミングを学ぶことが役立つことを願っています。