亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java發(fā)送短信系列之限制日發(fā)送次數(shù)

 更新時間:2016年02月21日 10:34:13   作者:BK  
這篇文章主要為大家詳細介紹了java發(fā)送短信系列之限制日發(fā)送次數(shù),詳細介紹了限制每日向同一個用戶(根據(jù)手機號和ip判斷)發(fā)送短信次數(shù)的方法,感興趣的小伙伴們可以參考一下

在前兩篇文章中, 我們實現(xiàn)了同步/異步發(fā)送短信以及限制發(fā)送短信頻率.這一篇, 我們介紹一下限制每日向同一個用戶(根據(jù)手機號和ip判斷)發(fā)送短信的次數(shù)

1、數(shù)據(jù)表結(jié)構(gòu)

由于需要記錄整天的發(fā)送記錄, 因此這里我們將數(shù)據(jù)保存到數(shù)據(jù)庫中. 數(shù)據(jù)表結(jié)構(gòu)如下:

type為驗證碼的類型, 比如注冊, 重置密碼等.
sendTime的默認值為當前時間.

2、限制日發(fā)送次數(shù)

我們這里需要用到上一篇中提到的接口和實體類.

DailyCountFilter.java

public class DailyCountFilter implements SmsFilter {

  private int ipDailyMaxSendCount;
  private int mobileDailyMaxSendCount;
  private SmsDao smsDao;

  // 省略了部分無用代碼

  @Override
  public boolean filter(SmsEntity smsEntity) {
    if (smsDao.getMobileCount(smsEntity.getMobile()) >= mobileDailyMaxSendCount) {
      return false;
    }
    if (smsDao.getIPCount(smsEntity.getIp()) >= ipDailyMaxSendCount) {
      return false;
    }
    smsDao.saveEntity(smsEntity);
    return true;
  }

}

主要代碼很簡單, 首先判斷向指定的手機號發(fā)送的次數(shù)是否達到了日最大發(fā)送次數(shù), 之后再判斷指定的ip請求發(fā)送的次數(shù)是否達到了最大次數(shù). 如果都沒有, 則將本次發(fā)送的手機號, ip等信息保存到數(shù)據(jù)庫中.

當然, 這個類存在一定的問題: 在判斷是否超過最大次數(shù)到保存實體數(shù)據(jù)之間可能已經(jīng)有其他線程保存了新的數(shù)據(jù). 造成上面的兩個判斷并不是絕對的準確.

我們可以使用序列化等級的事務(wù)保證不會發(fā)生錯誤, 但是代價太高. 因此我們這里不做處理. 因為我們前面已經(jīng)實現(xiàn)了限制發(fā)送頻率. 如果先使用FrequencyFilter過濾一次, 限制發(fā)送頻率, 那么基本上不可能出現(xiàn)前面說的問題.

還有一個問題: 隨著時間的推移, 這個表會越來越大, 造成查詢的性能相當?shù)牟? 我們可以向上一篇中那樣, 每隔一段時間就刪除無用的數(shù)據(jù); 也可以動態(tài)的創(chuàng)建表, 然后向新表中插入數(shù)據(jù).

3、使用動態(tài)表

這里我們采用第二種方案: 數(shù)據(jù)表的名字為"sms_四位年_兩位月", 比如"sms_2016_02". 插入數(shù)據(jù)時根據(jù)現(xiàn)在的時間獲得表名, 然后再插入. 另外使用Quartz在每月的20號2點生成下個月以及下下個月的數(shù)據(jù)表:

我們首先修改DailyCountFilter類, 在這個類中添加任務(wù)計劃, 定時生成數(shù)據(jù)表:

DailyCountFilter.java

// 在上面代碼的基礎(chǔ)上, 再添加如下代碼
public class DailyCountFilter implements SmsFilter {

  private Scheduler sched;

  @Override
  public void init() throws SchedulerException {
    smsDao.createTable(0); // 創(chuàng)建這個月的數(shù)據(jù)表
    smsDao.createTable(1); // 創(chuàng)建下個月的數(shù)據(jù)表

    SchedulerFactory sf = new StdSchedulerFactory();
    sched = sf.getScheduler(); // 創(chuàng)建Quartz容器

    JobDataMap jobDataMap = new JobDataMap();
    jobDataMap.put("smsDao", smsDao);  // 創(chuàng)建運行任務(wù)時需要使用的數(shù)據(jù)map 

    // 創(chuàng)建job對象, 該對象執(zhí)行實際的任務(wù)
    JobDetail job = JobBuilder.newJob(CreateSmsTableJob.class)
        .usingJobData(jobDataMap)
        .withIdentity("create sms table job").build();

    // 創(chuàng)建trigger對象, 該對象用來描述觸發(fā)執(zhí)行job的時間規(guī)則
    // 比如這里的每月20號2點
    CronTrigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("create sms table trigger")
        .withSchedule(CronScheduleBuilder.cronSchedule("0 0 2 20 * ?"))// 每月的20號2點
        .build();

    sched.scheduleJob(job, trigger);  // 注冊任務(wù)和觸發(fā)規(guī)則
    sched.start(); // 啟動調(diào)度
  }

  @Override
  public void destroy() {
    try {
      sched.shutdown();
    }
    catch (SchedulerException e) {}
  }

  public static class CreateSmsTableJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
      JobDataMap dataMap = context.getJobDetail().getJobDataMap();
      SmsDao smsDao = (SmsDao) dataMap.get("smsDao"); // 獲得傳過來的smsDao對象
      smsDao.createTable(1); // 創(chuàng)建下個月的數(shù)據(jù)表
      smsDao.createTable(2); // 創(chuàng)建下下個月的數(shù)據(jù)表
     }
  }
}

接下來, 我們看看SmsDao的部分代碼:

SmsDao.java

public class SmsDao {

  /**
   * 創(chuàng)建新的日志表
   *
   * @param monthExcursion 偏移的月數(shù)
   */
  public void createTable(int monthExcursion){
    String sql = "CREATE TABLE IF NOT EXISTS "
      + getTableName(monthExcursion) + " LIKE sms";
    // 執(zhí)行sql語句
  }

  /**
   * 保存SmsEntity實體對象
   */
  public void saveEntity(SmsEntity smsEntity){
    String sql = "INSERT INTO "
      + getNowTableName() + " (mobile, ip, type) VALUES(?, ?, ?)";
    // 執(zhí)行sql語句
  }

  /**
   * 獲得指定手機號今天請求發(fā)送短信的次數(shù)
   *
   * @param mobile 用戶手機號
   * @return 今天請求發(fā)送短信的次數(shù)
   */
  public long getMobileCount(String mobile){
    String sql = "SELECT count(id) FROM "
      + getNowTableName() + " WHERE mobile=? AND time >= CURDATE()";
    // 執(zhí)行sql語句, 返回查詢結(jié)果
  }

  // 省略了getIPCount方法

  /**
   * 獲得現(xiàn)在使用的表的名字
   */
  private String getNowTableName() {
    return getTableName(0);
  }

  private DateFormat dateFormat = new SimpleDateFormat("yyyy_MM");

  /**
   * 獲得相對現(xiàn)在偏移monthExcursion月的表名
   *
   * @param monthExcursion 偏移的月數(shù)
   * @return 對應(yīng)月的表名
   */
  private String getTableName(int monthExcursion) {
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.MONTH, monthExcursion);
    Date date = calendar.getTime();
    return "sms_" + dateFormat.format(date);
  }

}

SmsDao中的createTable方法成功運行有個前提, 就是存在sms數(shù)據(jù)表. createTable方法會復制sms表的結(jié)構(gòu)創(chuàng)建新的數(shù)據(jù)表.

我們保留發(fā)送短信的數(shù)據(jù)(手機號, ip, 時間等), 而不是直接刪除, 是因為以后可能需要分析這些數(shù)據(jù), 獲取我們想要的信息, 比如判斷服務(wù)商短信的到達率、是否有人惡意發(fā)送短信等. 甚至可能獲得意外的"驚喜".

以上就是本文的全部內(nèi)容,希望大家可以繼續(xù)關(guān)注。

相關(guān)文章

  • MyBatis-Plus如何使用枚舉自動關(guān)聯(lián)注入詳解

    MyBatis-Plus如何使用枚舉自動關(guān)聯(lián)注入詳解

    這篇文章主要給大家介紹了關(guān)于MyBatis-Plus如何使用枚舉自動關(guān)聯(lián)注入的相關(guān)資料,文中通過實例代碼介紹的非常詳細,對大家學習或者使用MyBatis-Plus具有一定的參考學習價值,需要的朋友可以參考下
    2022-03-03
  • SpringBoot中時間類型 序列化、反序列化、格式處理示例代碼

    SpringBoot中時間類型 序列化、反序列化、格式處理示例代碼

    這篇文章主要介紹了SpringBoot中時間類型 序列化、反序列化、格式處理示例代碼,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Java?Selenide?簡介與用法

    Java?Selenide?簡介與用法

    Selenium?是目前用的最廣泛的Web?UI?自動化測試框架,本文給大家介紹下Java?Selenide使用,感興趣的朋友一起看看吧
    2022-01-01
  • java使用軟引用實現(xiàn)緩存機制示例

    java使用軟引用實現(xiàn)緩存機制示例

    這篇文章主要為大家介紹了java使用軟引用實現(xiàn)緩存機制示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • springboot項目攔截前端請求中的特殊字符串(解決方案)

    springboot項目攔截前端請求中的特殊字符串(解決方案)

    springboot項目中,需要對前端請求數(shù)據(jù)進行過濾,攔截特殊字符,本文通過實例代碼給大家分享完美解決方案,感興趣的朋友一起看看吧
    2023-10-10
  • 解決Spring Mvc中對象綁定參數(shù)重名的問題

    解決Spring Mvc中對象綁定參數(shù)重名的問題

    最近在工作中遇到了參數(shù)綁定的一個問題,發(fā)現(xiàn)網(wǎng)上這方面的資料較少,索性自己來總結(jié)下,下面這篇文章主要給大家介紹了關(guān)于如何解決Spring Mvc中對象綁定參數(shù)重名問題的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-08-08
  • springMVC圖片上傳的處理方式詳解

    springMVC圖片上傳的處理方式詳解

    這篇文章主要為大家詳細介紹了springMVC圖片上傳的處理方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Java精確抽取網(wǎng)頁發(fā)布時間

    Java精確抽取網(wǎng)頁發(fā)布時間

    這篇文章主要為大家詳細介紹了Java精確抽取網(wǎng)頁發(fā)布時間的相關(guān)資料,盡量做到精確無誤,感興趣的小伙伴們可以參考一下
    2016-06-06
  • zookeeper監(jiān)聽器原理的詳解

    zookeeper監(jiān)聽器原理的詳解

    今天小編就為大家分享一篇關(guān)于zookeeper監(jiān)聽器原理的詳解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Elasticsearch模糊查詢詳細介紹

    Elasticsearch模糊查詢詳細介紹

    這篇文章主要給大家介紹了關(guān)于Elasticsearch模糊查詢的相關(guān)資料,在數(shù)據(jù)庫查詢中模糊查詢是一種強大的技術(shù),可以用來搜索與指定模式匹配的數(shù)據(jù),需要的朋友可以參考下
    2023-09-09

最新評論