• 后端防止重复点击


    请直接看原文:

     后端防止重复点击设计_后端如何防止重复点击-CSDN博客

    ---------------------------------------------------------------------------------------------------------------------------------

    一、背景

        想了解的都懂,不再描述。

    二、解决的主要思想

        重复调用会存在在以下几种情况中:

        1、点击一次后无遮罩可进行二次点击。(可通过前端进行设置)

        2、在出现遮罩之前,可能由于屏幕的特殊性,而自行进行了多次点击。(主要是避免此种问题)

        在同一时刻,调用同一个方法,且入参一致则认定为是重复点击,此时不在执行后续方法。

    三、思路

        1、为了方法的通用性以及和业务系统进行解耦,在此使用aop的环绕增强。

        2、在增强中判断当前的类名+方法名+入参转换为(json)组装成的key是否已经在redis中存在

    (参数里要加上useId)

        3、利用redis的setNx(此方法为原子性,不建议判断后再进行set,避免出现线程安全问题)

        4、返回为true,则说明未提交。调用pjp.proceed方法执行。

            4.1、方法执行后删除当前redis值

        5、返回为false,则说明为重复点击,则直接返回。

    四、代码实现

        1、定义注解类

        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public @interface ForbidRepeatClick { }

        2、定义切面

        @Component
        @Aspect
        @Order(1)
        public class ForbidRepeatClickInterceptor {
            private static final Logger LOGGER = LoggerFactory.getLogger(ForbidRepeatClickInterceptor.class);
            @Pointcut("@annotation(ForbidRepeatClick)")
           public void pointcut() {
           }
            @Around("pointcut()")
            public Object forbidRepeatClick(ProceedingJoinPoint pjp) throws Throwable {
                //1、根据入参方法名获取组装的redis的key值
                String redisKey = getRedisKey(pjp);
                LOGGER.info("ForbidRepeatClickInterceptor->forbidRepeatClick->redisKey:{}", redisKey);
               
                if(RedisUtil.setIfAbsent(redisKey, "exist")) {
                    LOGGER.info("ForbidRepeatClickInterceptor->forbidRepeatClick->redisKey:notexist");
                    //2、当前方法同一时间段无完全同参数调用,则继续往下执行
                   Object res = pjp.proceed();
                    //2.1 执行后将数据从redis删除
                    RedisUtil.delete(redisKey);
                    return res;
                }
            
               //3、当前方法同一时间段具有相同参数执行,则不再执行,直接返回错误标识
               LOGGER.info("ForbidRepeatClickInterceptor->forbidRepeatClick->redisKey:exist");
               CommonResponse commonResponse = new CommonResponse();
               commonResponse.setCode(ResultEnum.REPEAT_CLICK.getNo());
               return commonResponse;      
           }
        
            /**
             * 获取存储的redis的key值
             * @param pjp
             * @return
             */
            private String getRedisKey(ProceedingJoinPoint pjp) {
               
                // 1、获取被代理的对象类型
                String className = pjp.getTarget().getClass().getName();
                
                // 2、获取当前代理的方法名
               String methodName = pjp.getSignature().getName();
               
                // 3、获取入参并转换成jason串
                String convertJson = convertArgsToJson(pjp.getArgs());
               
                String redisKey = className + "->" + methodName + "->" + convertJson;
                
                return redisKey;
            }
        
           /**
             * 将传入的参数拼接成json类型的字符串
             * @param args
             * @return
             */
            private String convertArgsToJson(Object[] args) {
                StringBuilder convertJson = new StringBuilder();
                for (Object object : args) {
                   if(!(object instanceof HttpServletRequest)) {  // 此处判断不能舍去
                        convertJson.append(JSON.toJSONString(object));
                   }
                }
               return convertJson.toString();
            }

    注:本次设计主要是利用到了redis是线程安全的以及redis进行处理分布式问题。

    方法返回值的设计在此不再赘述,如果后端方法使用的是同类型的返回值,可直接返回该类型,如果不同类型,请参考策略模式进行设计。

  • 相关阅读:
    重组的脱氧核糖核酸酶 I,生物工艺级相关研究
    如何基于Next.js、Prisma、Postgres和Fastfy构建全栈APP?
    电网运行信息检索系统的设计与实现
    沃尔玛Walmart EDI 850订单详解
    CornerNet-Lite训练自己的数据集
    Python 工匠:一个关于模块的小故事
    Lesson14——NumPy 字符串函数之 Par3:字符串信息函数
    CS5266BN说明书|CS5266BN QFN48封装规格书|CS5266BN设计资料
    【机器学习】7 ——k近邻算法
    【看表情包学Linux】软硬链接 | 软连接数 | 创建软硬链接 | 动静态库 | 生成静态库 | 生成动态库
  • 原文地址:https://blog.csdn.net/weixin_70280523/article/details/136152351