SPRING-AOP/Redis防止表单重复提交操作

1、新建防止表单重复提交注解:

@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface RequestLock {

String prefix() default "";

long expire();

TimeUnit timeUnit();

String delimiter() default "&";
}

2、AOP环绕通知监控注解 获取到登录姓名(un) + url地址

@Aspect
@Configuration
@Order(2)
public class RedisRequestLockAspect {

private final RedisTemplate stringRedisTemplate;

@Autowired
public RedisRequestLockAspect(RedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}

@Pointcut("@within(io.hk.common.annotation.RequestLock) || @annotation(io.hk.common.annotation.RequestLock)")
public void aopPointCut() {

}

@Around("aopPointCut()")
public Object interceptor(ProceedingJoinPoint joinPoint) {
//获取自定义key

// 使用RedisCallback接口执行set命令,设置锁键;设置额外选项:过期时间和SET_IF_ABSENT选项
// stringRedisTemplate.opsForValue().set(lockKey, joinPoint.getArgs(), requestLock.expire(),requestLock.timeUnit());
try {

MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String methodName = methodSignature.getName();
if(methodName.equals("getUtilComboxList")||methodName.equals("getSubBusinessType")||methodName.equals("getUdiList")||methodName.equals("getMdparaconfig")||methodName.equals("getProject")){
return joinPoint.proceed();
}
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String un=request.getParameter("un")==null?"SYSTEM":request.getParameter("un").toString();
String uri=request.getRequestURI();
RequestLock requestLock = AnnotationUtils.findAnnotation(joinPoint.getTarget().getClass(), RequestLock.class);
// Object[] args = joinPoint.getArgs();
String lockKey =uri+"&"+un;

final Boolean success = (Boolean) stringRedisTemplate.execute(
(RedisCallback) connection -> connection.set(lockKey.getBytes(), new byte[0],
Expiration.from(requestLock.expire(), requestLock.timeUnit()),
RedisStringCommands.SetOption.SET_IF_ABSENT));

if (!success) {
LogUtil.writelog("存在key:" + lockKey, "防重复提交");
throw new RRException( "您的操作太快了,请稍后重试","1");
//return R.error("您的操作太快了,请稍后重试").put("message","您的操作太快了,请稍后重试");
}else {
Object retVal = this.execute(joinPoint, lockKey);
return retVal;
}

} catch (Throwable throwable) {
throw new RRException( throwable.getMessage(),"1");
//return R.error("系统异常,请联系管理员!").put("message","系统异常,请联系管理员!");
}
}

public Object execute(ProceedingJoinPoint pjp, String lockKey) throws Throwable {
Object var5;
try {
Object retVal = pjp.proceed();
var5 = retVal;
} catch (Exception var9) {
throw new Exception(var9);
} finally {
LogUtil.writelog("删除key:" + lockKey, "防重复提交");
stringRedisTemplate.delete(lockKey);
}

return var5;
}
}

三、将注解放到要防止重复提交的类上面

@RequestLock(expire=5,timeUnit= TimeUnit.MINUTES)
public class TestController {}

posted @ 2024-11-04 19:49  skystrivegao  阅读(140)  评论(0)    收藏  举报