Java Send short message series limit send frequency _java

Source: Internet
Author: User
Tags time interval

This is the second part of sending a text message, and here's how to limit the frequency of sending text messages to the same user (based on cell phone number and IP).

1. Use session

If it is a Web program, it is OK to record the last time sent in the session, but it can be bypassed. In the simplest case, you can bypass the record in the session by simply restarting the browser or clearing the data that can mark the session with the cache. Although a lot of people are not computer professional, also did not learn these. However, we need to note that the reason to limit the frequency of transmission is to prevent "SMS bombs", that is, malicious frequent requests to a mobile phone number to send text messages. So it is possible for this person to know this knowledge.

Below we use the "global" data limit to send frequency to the same user. Let's do some "prep" work first.

2. Define interface, entity class

The entity classes we need are as follows:

Smsentity.java

public class smsentity{
  private Integer ID;
  Private String Mobile;
  Private String IP;
  Private Integer type;
  Private Date time;
  Private String captcha;

  Omitting construction methods and getter, setter methods
}

The filtering interface is as follows:

Smsfilter.java

Public interface Smsfilter {

  /**
   * Initializes the filter *
  /void Init () throws Exception;

  /**
   * To determine whether a message can be sent.
   * @param smsentity will send the message content
   * @return can send then return true, otherwise return false
  /boolean filter (Smsentity smsentity);

  /**
   * Destroy the filter *
  /void Destroy ();

}

3. Main code

Limit the frequency of transmission, the need to record a mobile phone number (IP) and the last time the message was sent. Very suitable for map to complete, here we first use CONCURRENTMAP implementation:

Frequencyfilter.java

public class Frequencyfilter implements Smsfilter {/** * send interval, unit: milliseconds/private long sendinterval;

  Private concurrentmap<string, long> sendaddressmap = new concurrenthashmap<> (); Omitted part of the unwanted Code @Override public boolean filter (Smsentity smsentity) {if Setsendtime (Smsentity.getmobile ()) &AMP;&A mp
    Setsendtime (Smsentity.getip ()) {return true;
  return false;
   /** * Changes the sending time to the current time. * Set the sending time to the current time if the distance from last send is greater than {@link #sendInterval}.
   Otherwise, no content is modified. * * @param ID send mobile number or IP * @return returns TRUE if the sending time is successfully modified to the current time.

    Otherwise return 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);

 }
}

Here, the main logic is implemented in the Setsendtime method :

第25-28 Line: First of all assume that the user is the first time to send text messages, then should put the current time into the Sendaddressmap. If putifabsent returns NULL, then the user is indeed the first to send the text message, and now the time has been placed in the map, can be sent.

第30-33: If the user is not the first time to send a text message, then you need to determine whether the last time the message was sent and now the interval is less than the send time interval. If it is less than the send interval, it cannot be sent.

Line 35th: If the time interval is large enough, then you need to try to set the send time to the current time.

    • If the replacement succeeds, you can send a text message.
    • If the replacement fails, there is another thread that has been replaced by 26-35 lines on this thread, which means that a text message has been sent just now.

1), then you can repeat the execution of 25-35 lines to ensure that it is absolutely correct.
2, you can also directly think that can not send, because although the theoretical "execution of 26-35 lines" time may be greater than the "send Interval", but the probability of how much? Basically you can ignore it.
This code is implemented as a frequency limit, but if only "in" and not "out" so sendaddressmap occupy more and more content will be larger until the OutOfMemoryError exception. Next we add code to periodically clean up expired data.

4, clean up expired data

Frequencyfilter.java

/**
 * On the basis of the above code, add the following code/public
class Frequencyfilter implements Smsfilter {
  private long Cleanmapinterval;
  Private Timer timer = new Timer ("Sms_frequency_filter_clear_data_thread");

  @Override public
  void init () {timer.schedule () {
    new TimerTask () {
      @Override public
      void Run (
        ) { Cleansendaddressmap ();
      }
    , Cleanmapinterval, cleanmapinterval);

  /**
   * Delete all expired data in 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 ();
  }
}

This program is not complex, start a timer, every cleanmapinterval milliseconds to perform a cleansendaddressmap method to clean up expired data.

The Cleansendaddressmap method first obtains the current time and obtains a time value based on the current time: All messages sent after this time are not allowed to send text messages again. Then remove all key value pairs that are less than this time value from the entire map.

Of course, after adding the above code, the first code has a bug: When the last line of Sendaddressmap.replace (ID, sendtime, currenttime) fails, it is not necessarily the other thread that has been replaced, it is possible that the cleanup thread deleted the data . So we need to modify the last few lines of the Setsendtime method:

Frequencyfilter.java

Private Boolean setsendtime (String ID) {
  //omitting the preceding code
  if (Sendaddressmap.replace (ID, sendtime, currenttime)) { return
    true;
  }
  return sendaddressmap.putifabsent (ID, currenttime) = = null;
}

If the replacement succeeds here, return true directly.

If the substitution is unsuccessful. Then it may be that other line enters upgradeable replaced (the first case); It is also possible that the cleaned thread was deleted (the second case); It can even be deleted by the cleanup thread, and another thread inserts a new time value (the third case).

    • If this is the first or third case, then the situation, like the one at the beginning, can be thought of as being unable to send.
    • If this is the second case, it should be sent.
    • In order to confirm what kind of situation we can perform a putifabsent, if successful, the description is the second case that can be sent; Otherwise, the first or third condition cannot be sent.

At this point, the code that restricts sending time is complete. Of course, this program also has a small bug, or "feature":

If, IP for "192.168.0.1" customer request to mobile phone number "12345678900" Send text message, and then in Sendinterval in IP for "192.168.0.2" machine request to mobile phone number "12345678900" Send SMS. The SMS will not be sent out, and the last time the phone number "12345678900" has been sent is the current time.

5, the use of examples

Here we provide a server layer that shows how to integrate the code from the previous article and this one:

Smsservice.java

public class smsservice{
  private SMS SMS;
  private list<smsfilter> filters;
  private Properties template;

  Omitted some code

  /** *
   Send verification code *
   * @param smsentity send SMS Basic data
   * @return If the commit succeeds, return 0. Otherwise, other values are returned.
   */Public
  int Sendcaptcha (smsentity smsentity) {for
    (Smsfilter filter:filters) {
      if!filter.filter ( smsentity)) {return
        1;
      }
    }
    if (SmsEntity.REGISTER_TYPE.equals (Smsentity.gettype ())) {
      sendregistersms (smsentity);
    }
    else{return
      2;
    }
    return 0;
  }

  /**
   * Send Registration Verification Code
   *
   * @param smsentity Send SMS Basic data *
   *
  private void sendregistersms (smsentity smsentity) {
    sms.sendmessage (Smsentity.getmobile (),
        template.getproperty ("register"). Replace ("{ CAPTCHA} ", Smsentity.getcaptcha ()));
  }



The Frequencyfilter and the Asyncsmsimpl in the previous article are then "injected" through the set method.

The above is the entire content of this article, I hope to learn Java program to help you.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.