前端使用防抖动+lock,后端使用Spring Aop实现防连点


前言

在前后端开发中,我们常常需要做出一些功能来防止数据异常,例如客户端对按钮的重复点击,可能会添加重复的数据,这时候就需要做出防连点的功能,而简单的防抖动等又不能完全解决这种问题,因此就要做前端和后端的双重防连点。


一、前端实现

1.1 防抖动

我们前端采用防抖动(定义一个计时器,当点击按钮后开始计时,而不会立即放松请求,如果在这个时间段再次点击,计时器将重新计时,只有当计时器计时完成后才会发送请求),如果项目中添加按钮比较多,我们可以将防抖动方法封装成一个组件,在使用的组件中引进即可

在这里插入图片描述

let timeout = null;
function debounce(func, wait) {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(function () {
            func();
    }, wait);
}
export default debounce

引入组件

在这里插入图片描述

防抖动遇到的问题

当只使用防抖动实现方法,进行测试时我发现了一个问题:当点击按钮发送第一个请求到达后端,被服务器接受处理的过程中,再次点击按钮发送请求,后端就会收到两个携带相同数据的请求,还是不能够完全的解决防连点的问题。

1.2 采用lock锁

为了解决这个问题,我想到了点击按钮后加上一个lock锁

在这里插入图片描述

二、后端Spring Aop实现

2.1 定义一个注解

使用Spring Aop可以定义一个注解

import java.lang.annotation.*;

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

}

2.2 使用@Around在方法前检验请求是否重复

获取请求的路径信息,将其存储在服务器session中,当请求到达时,先查看session中是否存在方法请求,如果存在则不让其通行,最后一定要在添加方法执行结束后清除掉session中的请求信息

import com.jz.system.common.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
@Slf4j
public class RepeatSubmitAspect {
    @Pointcut("@annotation(com.jz.system.aspect.RepeatSubmit)")
    public void repeatSubmit() {
    }

    @Around("repeatSubmit()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            String path = request.getServletPath()+"_"+ request.getMethod() + "_REPEAT_REQUEST";
            Object attribute = request.getSession().getAttribute(path);
            if (attribute != null) {
                return ResultVO.error("请求重复");
            } else {
                request.getSession().setAttribute(path,path);
                try {
                    return joinPoint.proceed();
                } finally {
                    request.getSession().removeAttribute(path);
                }
            }
        }
        return joinPoint.proceed();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值