注解实现防止重复提交(Aop)

一、前言

书接上回,上次实现了springboot整合redis,在使用过程中就避免不了重复提交的场景。springboot整合redis_crazyK.的博客-优快云博客

重复提交的场景:

  • 用于用户误操作,多次点击表单提交按钮
  • 由于网速等原因造成页面卡顿,用户重复刷新提交页面
  • 恶用户如利用postman等工具重复恶意提交表单

为了防止以上情况的出现需要自定义一个注解来完成防止重复提交操作

二、实现

1.创建一个注解

/**
 * 自定义注解防止表单重复提交
 */
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {
    int lockTime() default 5;
}

注解参数不懂的小伙伴可以移步这篇文章:java自定义注解_crazyK.的博客-优快云博客  

2.创建Http请求工具类,用于在切面时获取token使用

public class HttpContextUtils {
    public static HttpServletRequest httpServletRequest(){
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
    }
}

3.项目中加入SpringAop依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

4.创建切面,将切点注册为自定义的注解,唯一表示采用接口url+token的形式,户每发起第一次添加请求,会经过界面,在切面获取信息后组装起来存入Redis,当用户后续发起请求时,首先判断Redis中是否缓存了这个key,如果缓存了,则证明已经提交,于是反馈给前端,如果不存在,证明没有提交,则存入Redis。

@Component
@Aspect
public class NoRepeatSubmitAspect {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Pointcut("@annotation(repeatSubmit)")
    public void pointcutNoRepeat(NoRepeatSubmit repeatSubmit){};
    @Around("pointcutNoRepeat(noRepeatSubmit)")
    public Object doNoRepeat(ProceedingJoinPoint point, NoRepeatSubmit noRepeatSubmit) throws Throwable {
        int i=noRepeatSubmit.lockTime();
        HttpServletRequest httpServletRequest = HttpContextUtils.httpServletRequest();
        String token = httpServletRequest.getHeader("token");
        String url = httpServletRequest.getRequestURL().toString();
        String sign = url+"/"+token;
        Boolean key=redisTemplate.hasKey(sign);
        if (key){
            throw new Exception("请勿重复提交");
        }
        redisTemplate.opsForValue().set(sign,sign,i, TimeUnit.SECONDS);
        return  point.proceed();
    }
}

三、测试

将我们自定义的注解加到对应方法上

先向redis中插入一条key为crazyk,value为csdn的数据

 

提交成功,然后在向redis中存入相同的数据后端会抛出我们在切面自定义的异常

代码已同步至Gitee:RedisBoot: springboot集成redis

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值