zoukankan      html  css  js  c++  java
  • java使用redis防止表单重复提交,点击过快的问题

    思路也很简单,用户访问某一接口一般都有唯一标识,前缀+唯一标识+uri存入redis,为了防止死锁问题,一定要设置该key的有效期我这里是3秒,重复点击间隔为1秒,用户点击没有key则存入redis,如果存在则判断时间是否小于间隔时间,小于则返回错误提示,大于则重新设置该key到redis。

    上代码!!!

    import com.sjyf.gym.exception.BusinessException;
    import com.sjyf.gym.utils.HttpContextUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    import java.util.Objects;
    import java.util.concurrent.TimeUnit;
    
    @Slf4j
    @Aspect
    @Component
    public class RepeatSubmitAspect {
    
        private static final String PREFIX = "repeat:user:";
    
        /**
         * 防重复点击间隔时间(毫秒)
         */
        private static final long REPEAT_TIME = 1000;
    
        @Resource
        private RedisTemplate redisTemplate;
    
        /**
         * 切入点
         */
        @Pointcut("execution(* com.sjyf.gym.*.controller.*.*.*(..))")
        public void repeat(){}
    
        /**
         * 方法执行前执行
         */
        @Before("repeat()")
        public void repeat(JoinPoint point) {
            // 获取token
            String token = HttpContextUtils.getHttpServletRequest().getHeader("Authorization");
            if(StringUtils.isBlank(token)){
                return;
            }
    
            // 拼接
            StringBuilder label = new StringBuilder(PREFIX + token + HttpContextUtils.getHttpServletRequest().getRequestURI());
    
            // 判断key是否存在
            if(redisTemplate.hasKey(label.toString())){
                operate(label.toString());
            }else {
                set(label.toString());
            }
        }
    
        private void operate(String label) {
            // 上次提交时间
            Long lastTime = Long.valueOf(redisTemplate.opsForValue().get(label).toString());
            if(Objects.isNull(lastTime)){
                return;
            }
            if(System.currentTimeMillis() - lastTime < REPEAT_TIME){
                throw new BusinessException("点击的太快了啦,请慢一点!");
            }else {
                // 限制间隔点击时间已过,重新设置时间
                set(label);
            }
        }
    
        // 设置key
        public void set(String label){
            redisTemplate.opsForValue().set(label, System.currentTimeMillis(),3, TimeUnit.SECONDS);
        }
    
    }
  • 相关阅读:
    Ubuntu安装tomcat
    mongodb配置数据库文件夹,创建服务
    chrome 49 版本bug: flex父元素设置flex:1 , 子元素用height:100%无法充满父元素
    angularjs指令中的require赋值含义
    flex布局在垂直居中里,元素超过容器大小后,不能通过滚动条滚动到顶端,这是个flex的bug
    redux中的compose源码分析
    js中的reduce()函数
    redux-thunk中间件源码
    HTML, CSS. JS的各种奇淫技巧
    JS在项目中用到的AOP, 以及函数节流, 防抖, 事件总线
  • 原文地址:https://www.cnblogs.com/hjieone/p/15785107.html
Copyright © 2011-2022 走看看