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);
    }

}

 

posted @ 2022-01-10 16:48  明年上初中  阅读(1009)  评论(0编辑  收藏  举报