具体代码
注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AvoidRepeatableCommit {
/**
* 指定时间内不可重复提交,单位秒
*
* @return
*/
long timeout() default 5;
}
具体业务逻辑
@Aspect
@Component
public class AvoidRepeatableCommitAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private RedisTemplate redisTemplate;
//controller包的子包里面任何方法
@Pointcut("execution(public * com.fridge.controller.*.*.*(..))")
public void checkToken() {
}
@Around("checkToken()")
public Object around(ProceedingJoinPoint point) throws Throwable {
WebResult webResult = new WebResult();
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = getIpAddr(request);
//获取注解
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);
if (avoidRepeatableCommit != null) {
//目标类、方法
String className = method.getDeclaringClass().getName();
String name = method.getName();
String args = Arrays.toString(point.getArgs());
String ipKey = String.format("%s#%s#%s", className, name, args);
int hashCode = Math.abs(ipKey.hashCode());
String key = String.format("%s_%d", ip, hashCode);
long timeout = avoidRepeatableCommit.timeout();
if (timeout < 0) {
//过期时间5分钟
timeout = 5;
}
boolean success = redisTemplate.opsForValue().setIfAbsent(key, UUID.randomUUID().toString(), timeout, TimeUnit.SECONDS);
if (!success) {
return webResult.failResult("请勿重复提交");
}
}
//执行方法
Object object = point.proceed();
return object;
}
/**
* 获取请求用户的IP地址
*
* @param request
* @return
*/
public String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
讲解
主要是利用redis实现防止重复提交
对于同一次请求,进行redis记录,在redis有记录的情况下,进行拦截,没有的情况下请求放行
setIfAbsent 是java中的方法,如果返回false则说明值已经存在则进行拦截,如果返回true则说明没有值,设置值并返回true