背景

后端业务中,不能相信任何一个用户,永远不知道这个用户能做出来什么事情,他可能一个表单一秒点了好多次,在程序懵逼中就插进数据库了!

措施

这里采用redis锁的方式来实现
核心用 锁的名称+userid+方法名 做rediskey

code

这里采用AOP的方式来实现,实现耦合性降低到最小,零侵入,这就是java语言的妙处!

完整代码

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventRepeat {
    /**
     * 锁的名称,可不填
     *
     * @return
     */
    String key() default "";

    /**
     * 锁住的秒数
     *
     * @return
     */
    int second() default 1;
}
@Aspect
@Component
@Slf4j
public class PreventRepeatAspect {

    @Resource
    private RedisUtil redisUtil;

    @Pointcut("@annotation(com.xx.xx.api.annotation.PreventRepeat)")
    public void commitPointCut() {
    }

    @Around("commitPointCut()")
    public Object around(JoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Class<?> clazz = joinPoint.getTarget().getClass();
        //获取方法签名(通过此签名获取目标方法信息)
        MethodSignature ms=(MethodSignature)joinPoint.getSignature();
        Method method = clazz.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
        PreventRepeat annotation = method.getAnnotation(PreventRepeat.class);
        if (ObjectUtils.isNotEmpty(annotation)) {
            String userId = xxxx;

            String lockKey = StringUtils.isNotEmpty(annotation.key()) ? annotation.key() : userId + ":" + methodName;
            if (!redisUtil.lock(lockKey, lockKey, annotation.second())) {
                return Result.errorResult("请不要重复提交");
            }
        }
        return ((ProceedingJoinPoint) joinPoint).proceed();
    }
}
分类: java

站点统计

  • 文章总数:309 篇
  • 分类总数:19 个
  • 标签总数:190 个
  • 运行天数:975 天
  • 访问总数:72824 人次

浙公网安备33011302000604

辽ICP备20003309号