java 限制发送频率_java发送短信系列之限制日发送次数
在前两篇文章中, 我们实现了同步/异步发送短信以及限制发送短信频率.这一篇, 我们介绍一下限制每日向同一个用户(根据手机号和ip判断)发送短信的次数
1、数据表结构
由于需要记录整天的发送记录, 因此这里我们将数据保存到数据库中. 数据表结构如下:
type为验证码的类型, 比如注册, 重置密码等.
sendtime的默认值为当前时间.
2、限制日发送次数
我们这里需要用到上一篇中提到的接口和实体类.
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;
}
}
主要代码很简单, 首先判断向指定的手机号发送的次数是否达到了日最大发送次数, 之后再判断指定的ip请求发送的次数是否达到了最大次数. 如果都没有, 则将本次发送的手机号, ip等信息保存到数据库中.
当然, 这个类存在一定的问题: 在判断是否超过最大次数到保存实体数据之间可能已经有其他线程保存了新的数据. 造成上面的两个判断并不是绝对的准确.
我们可以使用序列化等级的事务保证不会发生错误, 但是代价太高. 因此我们这里不做处理. 因为我们前面已经实现了限制发送频率. 如果先使用frequencyfilter过滤一次, 限制发送频率, 那么基本上不可能出现前面说的问题.
还有一个问题: 随着时间的推移, 这个表会越来越大, 造成查询的性能相当的差. 我们可以向上一篇中那样, 每隔一段时间就删除无用的数据; 也可以动态的创建表, 然后向新表中插入数据.
3、使用动态表
这里我们采用第二种方案: 数据表的名字为"sms_四位年_两位月", 比如"sms_2016_02". 插入数据时根据现在的时间获得表名, 然后再插入. 另外使用quartz在每月的20号2点生成下个月以及下下个月的数据表:
我们首先修改dailycountfilter类, 在这个类中添加任务计划, 定时生成数据表:
dailycountfilter.java
// 在上面代码的基础上, 再添加如下代码
public class dailycountfilter implements smsfilter {
private scheduler sched;
@override
public void init() throws schedulerexception {
smsdao.createtable(0); // 创建这个月的数据表
smsdao.createtable(1); // 创建下个月的数据表
schedulerfactory sf = new stdschedulerfactory();
sched = sf.getscheduler(); // 创建quartz容器
jobdatamap jobdatamap = new jobdatamap();
jobdatamap.put("smsdao", smsdao); // 创建运行任务时需要使用的数据map
// 创建job对象, 该对象执行实际的任务
jobdetail job = jobbuilder.newjob(createsmstablejob.class)
.usingjobdata(jobdatamap)
.withidentity("create sms table job").build();
// 创建trigger对象, 该对象用来描述触发执行job的时间规则
// 比如这里的每月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); // 注册任务和触发规则
sched.start(); // 启动调度
}
@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); // 创建下个月的数据表
smsdao.createtable(2); // 创建下下个月的数据表
}
}
}
接下来, 我们看看smsdao的部分代码:
smsdao.java
public class smsdao {
/**
* 创建新的日志表
*
* @param monthexcursion 偏移的月数
*/
public void createtable(int monthexcursion){
string sql = "create table if not exists "
+ gettablename(monthexcursion) + " like sms";
// 执行sql语句
}
/**
* 保存smsentity实体对象
*/
public void saveentity(smsentity smsentity){
string sql = "insert into "
+ getnowtablename() + " (mobile, ip, type) values(?, ?, ?)";
// 执行sql语句
}
/**
* 获得指定手机号今天请求发送短信的次数
*
* @param mobile 用户手机号
* @return 今天请求发送短信的次数
*/
public long getmobilecount(string mobile){
string sql = "select count(id) from "
+ getnowtablename() + " where mobile=? and time >= curdate()";
// 执行sql语句, 返回查询结果
}
// 省略了getipcount方法
/**
* 获得现在使用的表的名字
*/
private string getnowtablename() {
return gettablename(0);
}
private dateformat dateformat = new simpledateformat("yyyy_mm");
/**
* 获得相对现在偏移monthexcursion月的表名
*
* @param monthexcursion 偏移的月数
* @return 对应月的表名
*/
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数据表. createtable方法会复制sms表的结构创建新的数据表.
我们保留发送短信的数据(手机号, ip, 时间等), 而不是直接删除, 是因为以后可能需要分析这些数据, 获取我们想要的信息, 比如判断服务商短信的到达率、是否有人恶意发送短信等. 甚至可能获得意外的"惊喜".
以上就是本文的全部内容,希望大家可以继续关注。
希望与广大网友互动??
点此进行留言吧!
java 限制发送频率_java发送短信系列之限制日发送次数相关推荐
- java 限制发送频率_java发送短信如何限制发送频率例子代码
本篇文章主要是详细介绍了java发送短信系列之怎么限制发送频率示例解析,在此为大家介绍一下怎么样限制向同一个用户(根据手机号和ip)发送短信的频率. 1.使用session 要是web程序那在sess ...
- UNIAPP实战项目笔记57 发送手机验证码 接入短信SDK
UNIAPP实战项目笔记57 发送手机验证码 接入短信SDK 注册时候需要发送验证 通过验阿里云或腾讯云等短信sdk供应商 实际案例图片 后端接口文件 index.js var express = r ...
- Java短信频率_java发送短信系列之限制发送频率
本篇是发送短信的第二部分, 这里我们介绍一下如何限制向同一个用户(根据手机号和ip)发送短信的频率. 1.使用session 如果是web程序, 那么在session中记录上次发送的时间也可以, 但是 ...
- Java+Demo对接中国移动 云MAS短信发送(http协议详解,新测成功!)
一.登录官网,下载http接入文档(随着官网不断更新,可参考官网的文档) 官网地址为:云mas业务平台 进入云MAS管理平台,找到 管理-接口管理 的列表页. (必读:本文对接方式是 java引用ja ...
- Java调用SMSLib用单口短信猫发送短信详解
技术园地 当前位置:短信猫网站主页 > 技术园地 > [转载]Java调用SMSLib用单口短信猫发送短信详解 发布时间:2017/02/09 点击量:620 SMSLib是Apache的 ...
- java实现短信验证码发送(基于阿里云短信sdk)
随着互联网的兴起,各行各业的需求都在不断的增加.随着业务的扩大,企业给用户发送短信验证码的业务,也是如火如荼.在这里,calvin给各位开发者推荐阿里云短信平台.原因有二:1.接入较简单,开发成本低 ...
- Android短信发送流程之普通短信发送(原)
我们先来看最简单的流程入手分析,即收件人只有一个,而且不是长短信的情况. 一.地址有效性检测 当点击发送按钮时,触发onClick事件: [java] view plaincopy @ComposeM ...
- Android监听SMS发送状态并获取短信服务中心号码
监听SMS发送状态的例子网上虽然有,但还是太杂了不完全.自己写了个. 短信服务中心号码的获取是通过SmsMessage.getServiceCenterAddress()方法获得.也就是只能从已经存储 ...
- 短信广告中虚拟网关发送与电信网关发送的区别
虚拟网关 移动的号码池 短信广告中虚拟网关发送与电信网关发送的区别 曾经有许多的客户都会问到一个问题?虚拟网关发送与电信网关发送有什么区别?为什么价格不一样?我来说说短信广告中虚拟网关发送与电信网关发 ...
最新文章
- eclipse 出现user operation is waiting
- 《Java 核心技术卷1 第10版》学习笔记 ------ 泛型【基础】
- Shell for循环
- 拥抱.NET Core,学习.NET Core的基础知识补遗
- C语言试题十一之计算并输出下列多项式值:sn=(1-1/2)+(1/3-1/4)+…+(1/(2n-1)1/2n).
- CFileDialog获取文件与文件夹路径
- WPF设计の自定义窗体
- Arcgis Engine矢量裁剪栅格,调用Mask工具相关代码
- android 列表上拉加载更多,Android 下拉刷新,上拉加载更多控件–支持ListView,GridView和ScrollView...
- Day14 字符编码
- 字节跳动年底再招 10000 人,前端工程师非常紧缺!
- 制作小游戏贪吃蛇即解决将python制作成exe
- QT程序自动拷贝所需动态库批处理
- OBS无延迟视频直播完整教程(组图)
- 百度云个人服务器搭建
- 团队项目成员与题目(本地地铁查询app)
- Android 利用V4L2 调用camera
- 多麦克风做拾音的波束_乱侃外设 篇四十二:一浪更比一浪强!HyperX Quadcast S 声浪加强版麦克风浅评...
- SWUSTOJ #77 计算员工周工资
- 飞鸽传书——短信接口