一、大概思路如下:
(1)、后台有一个单独获取token接口 A,token是一个随机唯一字符串,可以是uuid,每次调用获取返回不一样;
(token也可以前端生成,减少一次前后台交互);
还有一个提交业务数据的接口B(就是为了防止这个接口B,重复操作提交);
(2)、在进入需要提交页面时,调用后台接口A,例如获取token = 123,并且返回给前端token
(3)、前端点击提交按钮时,只调用提交接口B,此处不能再次调用获取token接口A,提交业务数据,并且把之前接口A获取的token = 123 带到后台过去,
需要保证在当前页面重复点击过来传递的token是同一个值;
(4)、后台接口B,获取到前端传递过来的业务数据和token,setNx token如果成功,//setnx成功以后返回1并设有效期继续执行,否则返回0;
(5)、后续用户在原页面操作反复提交,调用提交接口B时,后台此时setNx token失败,所以不会处理,并给前端相应提示;
(6)、这种方案,只能防止用户,在当前页面,单位时间expireTime内,反复点击提交按钮的重复操作;如果用户从该页面返回,再次进入提交页面时,则无法防止重复;
二、流程图:
三、部分代码:
(1)、接口A:web/getToken,返回token的伪代码:
import java.util.UUID;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/web")
public class AdminController {
@RequestMapping(value = "/getToken")
public String getToken() {
return UUID.randomUUID().toString();
}
}
(2)、接口B,判断重复请求的伪代码如下:
package redis.test;
import redis.clients.jedis.Jedis;
public class AvoidRepeatRequest {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1",6379);
jedis.auth("your password");
jedis.select(2);
//String token=UUID.randomUUID().toString();
String token = "mytoken";
int expireTime = 120;
//setnx成功以后返回1,否则返回0
if (1==jedis.setnx(token, "123")) { //第一次处理
jedis.expire(token, expireTime);
System.out.println("允许处理,过期时间为:"+expireTime);
} else {
System.out.println("不允许处理"); //重复不处理
}
jedis.disconnect();
}
}
四、测试:
第一次请求结果:
有了该token以后,在expireTime 时间段内,发送重复的请求,被拒绝: