本文共 3267 字,大约阅读时间需要 10 分钟。
org.springframework.boot spring-boot-starter-aop
redis配置此处略过
@Service@Slf4jpublic class RedisService { @Resource private StringRedisTemplate stringRedisTemplate; public boolean existKey(String key) { log.debug("existKey().params:" + key); return stringRedisTemplate.hasKey(key); } public Boolean delKey(String key) { log.debug("delKey().params:" + key); Boolean delete = stringRedisTemplate.delete(key); return delete; } public boolean addString(String key, String value) { BoundValueOperationsops = stringRedisTemplate.boundValueOps(key); try { ops.set(value); return true; } catch (Exception e) { log.error("redis添加异常." + e.getMessage(), e); e.printStackTrace(); return false; } } public boolean addString(String key, String value, long timeout, TimeUnit timeUnit) { BoundValueOperations ops = stringRedisTemplate.boundValueOps(key); try { ops.set(value, timeout, timeUnit); return true; } catch (Exception e) { log.error("redis添加异常." + e.getMessage(), e); e.printStackTrace(); return false; } }}
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface FormLock { /** * 指定时间内不可重复提交,单位毫秒 * @return */ long timeout() default 3000;}
@Slf4j@Aspect@Componentpublic class FormLockAspect { @Autowired private RedisService redisService; @Pointcut("@annotation(com.wetran.codex.business.avoid_repetition.AFormLock)") public void reqLock() { } /** * @param point */ @Around("reqLock()") public Object constructionSite(ProceedingJoinPoint point) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); //获取注解 MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); //目标类、方法 String className = method.getDeclaringClass().getName(); String methodName = method.getName(); //由于使用方法名+用户ID创建的Key,,,必须要有用户id参数 Long userId = Long.parseLong(request.getParameter("id")); log.info("防止表单重复提交类:{}. 方法:{}.用户ID:{}.", className, methodName, userId); String key = RedisConstants.BLACKlIST_LOCK_KEY + methodName + ":" + userId; FormLock formLock = method.getAnnotation(FormLock.class); long timeout = formLock.timeout(); if (timeout < 0) { //过期时间3000毫秒 timeout = 3000; } //校验该方法该用户的key是否存在,存在直接返回错误 if (redisService.existKey(key)) { return RespUtils.fail("请勿重复提交"); } boolean b = redisService.addString(key, DateUtils.getNow(), timeout, TimeUnit.MILLISECONDS); log.info("创建锁结果:{}. key:{}.", b, key); //执行方法 Object object = point.proceed(); //整理施工现场 Boolean aBoolean = redisService.delKey(key); log.info("删除redis锁结果:{}.", aBoolean); return object; }}
redis有效时间根据自身业务需求进行调整即可
在需要防止表单重复提交的方法上添加@FormLock注解即可,可根据不同方法指定相应的有效时间
转载地址:http://gncgn.baihongyu.com/