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<Boolean>) 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  阅读(106)  评论(0)    收藏  举报