zoukankan      html  css  js  c++  java
  • 使用aop防止重复提交

    在开发期间,我们总会遇到重复提交的操作,比如: 下单时用户手抖,有人故意频繁的请求某个api,这种情况下除了前端进行处理,

    后端也需要处理的,这里使用的是aop的方式,也可以使用redis分布式锁来实现,这个自行上网查找哈!

    实现方法: 通过注解类找到对应的切面类,根据存储用户的唯一标识(用户id)到缓存中来限制它的重复提交。

    注解类:

    import java.lang.annotation.*;
    
    /**
     * 防止用户下单重复提交注解类
     *
     * @author serence
     * @date 2021/11/7 20:49
     */
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface PlaceAnOrderRepeatSubmit {
    
        String name() default "name:";
    }

    切面类

    /**
         * 切入点
         * <p>
         * execution:  使用execution给批量方法添加切面, 定义的包名要在注解类的上一级
         *
         * @param point 连接点
         * @param nrs   防止重复提交
         * @return
         * @throws Throwable
         */
        @Around(value = "execution(* com.serene..*.*(..)) && @annotation(nrs)")
        public Object placeAnOrderAround(ProceedingJoinPoint point, PlaceAnOrderRepeatSubmit nrs) throws Throwable {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            assert attributes != null;
            HttpServletRequest request = attributes.getRequest();
            try {
                //访问目标方法的参数:
                Object[] args = point.getArgs();
                if (args != null && args.length > 0) {
                    //获取参数对象
                    Orders or = (Orders) point.getArgs()[0];
                    Long memberId = new Long(AESEncryptUtils.decrypt(or.getEncryptionId()));
                    //获取请求路径url
                    String key = memberId + "-" + request.getServletPath();
                    // 如果缓存中有这个url视为重复提交, 否则通过执行存储key
                    if (!redisService.haskey(key)) {
                        System.out.println("获取 入参前的参数:" + point.getArgs()[0]);
                        String str = Arrays.toString(point.getArgs());
                        //执行目标方法
                        Object ob = point.proceed();
                        System.out.println("获取 调用方法:" + point.getSignature().getName());
                        System.out.println("获取 目标对象:" + point.getTarget());
                        System.out.println("获取 入参后的参数:" + point.getArgs()[0]);
                        Orders entity = (Orders) point.getArgs()[0];
                        System.out.println("获取 对象实体: " + entity);
                        redisService.setCacheObject(key, 0, 3, TimeUnit.SECONDS);
                        return ob;
                    } else {
                        log.info("请勿重复提交");
                        //请求了同样的url继续限制
                        redisService.setCacheObject(key, 0, 3, TimeUnit.SECONDS);
                        return AjaxResult.error("请勿重复提交或者操作过于频繁");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            throw new CustomException("系统开了点小差,请稍后重试");
        }

    这里定义3秒,这里的缓存key: 用户唯一标识+api请求url

    然后在你控制器上自定义注解就好了

    @PlaceAnOrderRepeatSubmit
        @GetMapping("test")
        public AjaxResult test(){
            return AjaxResult.success("成功");
        }

    redis存储代码如下:

     /**
         * 缓存基本的对象,Integer、String、实体类等
         *
         * @param key      缓存的键值
         * @param value    缓存的值
         * @param timeout  时间
         * @param timeUnit 时间颗粒度
         * @return 缓存的对象
         */
        public <T> ValueOperations<String, T> setCacheObjectAop(String key, T value, Integer timeout, TimeUnit timeUnit) {
            ValueOperations<String, T> operation = redisTemplate.opsForValue();
            operation.set(key, value, timeout, timeUnit);
            return operation;
        }
    
        /**
         * 获取键值数据
         *
         * @param key 键值
         * @return
         */
        public boolean haskey(String key) {
            return redisTemplate.hasKey(key);
        }
  • 相关阅读:
    杜教筛
    虚树
    带修莫队
    线性基
    区间修改区间求和cdq分治
    矩阵快速幂求斐波那契数列
    点分治成品
    Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 1) C(二分+KMP)
    线性筛
    矩阵快速幂
  • 原文地址:https://www.cnblogs.com/ckfeng/p/15526210.html
Copyright © 2011-2022 走看看