SpringBoot防止重复请求,重复表单提交超级简单注解实现之四(终极版II)
- 原文链接:[https://www.lskyf.com/post/213](https://www.lskyf.com/post/213)
- 前言:
- 防重复提交业务流程图如下
- 1.简化DuplicateSubmitToken.java代码,只留下标记接口,新增超时设置接口
- 2.改造DuplicateSubmitAspect.java新增超时判断代码
- 3.TestController.java测试:包含restful请求,get请求,post请求
- 4.浏览器测试
原文链接:https://www.lskyf.com/post/213
前言:
根据最新spring boot:2.5.0版本和在《SpringBoot防止重复请求,重复表单提交超级简单的注解实现之四(终极版I)》之上化繁为简抽取更实用的代码,新增超时机制
防重复提交业务流程图如下
1.简化DuplicateSubmitToken.java代码,只留下标记接口,新增超时设置接口
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DuplicateSubmitToken {
boolean save() default true;
long timeOut() default 5000 ;
}
2.改造DuplicateSubmitAspect.java新增超时判断代码
@Aspect
@Component
@Slf4j
public class DuplicateSubmitAspect {
public static final String DUPLICATE_TOKEN_KEY = "duplicate_token_key";
@Pointcut("execution(public * com.yuanfenge.springboot.duplicatesubmit.controller..*(..))")
public void webLog() {
}
@Before("webLog() && @annotation(token)")
public void before(final JoinPoint joinPoint, DuplicateSubmitToken token) throws DuplicateSubmitException {
if (token != null) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
boolean isSaveSession = token.save();
if (isSaveSession) {
String key = getDuplicateTokenKey(joinPoint);
Object t = request.getSession().getAttribute(key);
if (null == t) {
createKey(request, key);
} else if (valid(t,token.timeOut())){
throw new DuplicateSubmitException(TextConstants.REQUEST_REPEAT);
} else {
createKey(request, key);
}
}
}
}
private void createKey(HttpServletRequest request, String key) {
String uuid = UUIDUtil.randomUUID();
long now = System.currentTimeMillis();
String value = uuid + "_" + now;
request.getSession().setAttribute(key, value);
log.info("token-key={};token-value={}",key, value);
}
private boolean valid(Object t, long timeOut) {
String token = t.toString();
String[] arr = token.split("_");
long before = Long.parseLong(arr[1]);
long now = System.currentTimeMillis();
if (now-before<timeOut){
return true;
}
return false;
}
public String getDuplicateTokenKey(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
String args = Arrays.asList(joinPoint.getArgs()).stream().map(i -> String.valueOf(i)).collect(Collectors.joining());
StringBuilder key = new StringBuilder(DUPLICATE_TOKEN_KEY);
key.append("_").append(methodName).append(args);
return key.toString();
}
@AfterThrowing(pointcut = "webLog()&& @annotation(token)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e, DuplicateSubmitToken token) {
if (null != token
&& e instanceof DuplicateSubmitException == false) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
boolean isSaveSession = token.save();
if (isSaveSession) {
String key = getDuplicateTokenKey(joinPoint);
Object t = request.getSession().getAttribute(key);
if (null != t) {
request.getSession(false).removeAttribute(key);
log.info("异常情况--移除标记!");
}
}
}
}
}
3.TestController.java测试:包含restful请求,get请求,post请求
@RestController
public class TestController {
@DuplicateSubmitToken
@RequestMapping(value = "/restful/{num}", method = RequestMethod.GET)
public Map<String, Object> restful(@PathVariable(value = "num") int num) throws Exception {
Map<String, Object> map=new HashMap<>();
if (num == 2) {
throw new Exception("====system exception haha !===");
}
map.put("welcome","hello word !");
map.put("method","restful:num="+num);
return map;
}
@DuplicateSubmitToken
@RequestMapping(value = "/getParam", method = RequestMethod.GET)
public Map<String, Object> getParam(@RequestParam(value = "num") int num) throws Exception {
Map<String, Object> map=new HashMap<>();
if (num == 2) {
throw new Exception("====system exception haha !===");
}
map.put("welcome","hello word !");
map.put("method","get带参数:num="+num);
return map;
}
@DuplicateSubmitToken
@RequestMapping(value = "/get", method = RequestMethod.GET)
public Map<String, Object> get() throws Exception {
Map<String, Object> map=new HashMap<>();
map.put("welcome","hello word !");
map.put("method","get无参");
return map;
}
@DuplicateSubmitToken(timeOut = 30*1000)
@RequestMapping(value = "/post", method = RequestMethod.POST)
public Map<String, Object> post(@RequestParam(value = "num") int num) throws Exception {
Map<String, Object> map=new HashMap<>();
map.put("welcome","hello word !");
map.put("method","post:num="+num);
return map;
}
}
4.浏览器测试
http://localhost:8080/restful/1
http://localhost:8080/get?num=1
http://localhost:8080/getParam?num=1
http://localhost:8080/post
源码下载链接
原文链接: https://www.lskyf.com/post/213
作者:猿份哥,版权所有,欢迎保留原文链接进行转载:)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)