赞
踩
一、定义一个注解用于标注需要校验重复提交的方法
- package com.xwolf.boot.annotation;
-
- import java.lang.annotation.*;
-
- /**
- * 避免重复提交
- * @author xwolf
- * @version 1.0
- * @since 1.8
- */
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface AvoidRepeatableCommit {
-
- /**
- * 指定时间内不可重复提交,单位毫秒
- * @return
- */
- long timeout() default 30000 ;
-
- }

二、添加一个切面用于校验来自同一IP地址的重复提交请求
- package com.xwolf.boot.aspect;
-
- import com.xwolf.boot.annotation.AvoidRepeatableCommit;
- import com.xwolf.boot.config.Constants;
- import com.xwolf.boot.utils.IPUtil;
- import com.xwolf.boot.utils.StringUtils;
- import com.xwolf.boot.utils.UUIDUtil;
- import lombok.extern.slf4j.Slf4j;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.core.annotation.Order;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
-
- import javax.servlet.http.HttpServletRequest;
- import java.lang.reflect.Method;
- import java.util.concurrent.TimeUnit;
-
- /**
- * 重复提交aop
- * @author xwolf
- * @version 1.0
- * @since 1.8
- */
- @Order
- @Aspect
- @Component
- @Slf4j
- public class AvoidRepeatableCommitAspect {
-
- @Autowired
- private RedisTemplate redisTemplate;
-
- /**
- * @param point
- */
- @Around("@annotation(com.xwolf.boot.annotation.AvoidRepeatableCommit)")
- public Object around(ProceedingJoinPoint point) throws Throwable {
-
- HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
- String ip = IPUtil.getIP(request);
- //获取注解
- MethodSignature signature = (MethodSignature) point.getSignature();
- Method method = signature.getMethod();
- //目标类、方法
- String className = method.getDeclaringClass().getName();
- String name = method.getName();
- String ipKey = String.format("%s#%s",className,name);
- int hashCode = Math.abs(ipKey.hashCode());
- String key = String.format("%s_%d",ip,hashCode);
- log.info("ipKey={},hashCode={},key={}",ipKey,hashCode,key);
- AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);
- long timeout = avoidRepeatableCommit.timeout();
- if (timeout < 0){
- timeout = Constants.AVOID_REPEATABLE_TIMEOUT;
- }
- String value = (String) redisTemplate.opsForValue().get(key);
- if (StringUtils.isNotBlank(value)){
- return "请勿重复提交";
- }
- redisTemplate.opsForValue().set(key, UUIDUtil.uuid(),timeout,TimeUnit.MILLISECONDS);
- //执行方法
- Object object = point.proceed();
- return object;
- }
-
- }
-

三、对需要检验重复提交的方法添加注解
- /**
- * 添加用户
- * @param user
- * @return
- */
- @PostMapping(value = "add")
- @AvoidRepeatableCommit(timeout = 50000)
- public String insert(@Valid User user){
- // user.setBirth(new Date());
- log.info("请求参数:{}",user);
- return userService.insert(user);
- }
方案出自:https://github.com/fkandy/boot/tree/master/src/main/java/com/xwolf/boot
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。