前言
在项目的使用使用过程中,经常会出现某些操作在短时间内频繁提交。
例如:用户鼠标点击过快而重复保存,从而创建了2笔一模一样的单据。针对类似情况,我们就可以全局地控制接口不允许重复提交。
实现思路
- 创建拦截器 interceptor,拦截所有api请求
- 将用户唯一标识(token或者jsessionid)+接口地址进行拼接,作为后续步骤的 redis-key
- 判断redis是否存在该key值,存在说明重复提交,不存在就存入redis,过期时间1秒
代码示例
- 创建拦截器 repeatsubmitinterceptor
@component public class repeatsubmitinterceptor extends handlerinterceptoradapter { @autowired private stringredistemplate stringredistemplate; //防重时间间隔(秒) private final int duration = 1; @override public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) throws exception { if (request.getdispatchertype() == dispatchertype.error){ return true; } string token = request.getheader("token"); string lockkey = "repeatsubmit:" + token + ":" + request.getservletpath(); boolean result = stringredistemplate.opsforvalue().setifabsent(lockkey, "", duration, timeunit.seconds); if (!result){ throw new exception("请勿重复提交"); } return true; } }
- 注入拦截器
@configuration public class mvcconfig implements webmvcconfigurer { @autowired private repeatsubmitinterceptor repeatsubmitinterceptor; @override public void addinterceptors(interceptorregistry registry) { registry.addinterceptor(repeatsubmitinterceptor); } }
测试
建个 controller 并创建个简单的测试接口,打开 postman 快速点击2次请求,结果如下:
总结
这边只是提供一种简单的方案,还可以有其他扩展,例如:
- 增加参数的校验,只做相同参数的重复判定,参数不同可以重复提交
- 增加aop自定义注解,只有注解标识的接口才会重复判定
- 使用session替代redis进行存储和校验(不适用于tomcat集群)
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论