zoukankan      html  css  js  c++  java
  • Java防止重复提

    具体代码

    注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AvoidRepeatableCommit {
    
        /**
         * 指定时间内不可重复提交,单位秒
         *
         * @return
         */
        long timeout() default 5;
    
    }
    

    具体业务逻辑

    @Aspect
    @Component
    public class AvoidRepeatableCommitAspect {
    
        private Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        //controller包的子包里面任何方法
        @Pointcut("execution(public * com.fridge.controller.*.*.*(..))")
        public void checkToken() {
        }
    
        @Around("checkToken()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            WebResult webResult = new WebResult();
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ip = getIpAddr(request);
    
            //获取注解
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);
            if (avoidRepeatableCommit != null) {
                //目标类、方法
                String className = method.getDeclaringClass().getName();
                String name = method.getName();
                String args = Arrays.toString(point.getArgs());
                String ipKey = String.format("%s#%s#%s", className, name, args);
                int hashCode = Math.abs(ipKey.hashCode());
                String key = String.format("%s_%d", ip, hashCode);
    
                long timeout = avoidRepeatableCommit.timeout();
                if (timeout < 0) {
                    //过期时间5分钟
                    timeout = 5;
                }
                boolean success = redisTemplate.opsForValue().setIfAbsent(key, UUID.randomUUID().toString(), timeout, TimeUnit.SECONDS);
                if (!success) {
                    return webResult.failResult("请勿重复提交");
                }
            }
            //执行方法
            Object object = point.proceed();
            return object;
        }
    
        /**
         * 获取请求用户的IP地址
         *
         * @param request
         * @return
         */
        public String getIpAddr(HttpServletRequest request) {
            String ip = request.getHeader("x-forwarded-for");
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            return ip;
        }
    }
    

    讲解

    主要是利用redis实现防止重复提交

    对于同一次请求,进行redis记录,在redis有记录的情况下,进行拦截,没有的情况下请求放行

    setIfAbsent 是java中的方法,如果返回false则说明值已经存在则进行拦截,如果返回true则说明没有值,设置值并返回true

  • 相关阅读:
    IDEA Tomcat控制台乱码
    使用Vue写一个登录页面
    vue如何新建一个项目并使用webstorm运行
    关于无线充电的三大标准和四种实现方式的介绍
    使用aria2搭建离线下载服务器
    OnPaint和OnDraw的区别
    PE文件中的DllCharacteristics属性
    ACM/IOI 历年国家集训队论文集和论文算法分类整理
    安装完最小化 RHEL/CentOS 7 后需要做的 30 件事情7. 安装 PHP PHP 是用于 web 基础服务的服务器端脚本语言。它也经常被用作通用编程语言。在最小化安装的 CentOS 中安
    堆栈—冲刺十三模拟赛 外星密码
  • 原文地址:https://www.cnblogs.com/eternityz/p/14751667.html
Copyright © 2011-2022 走看看