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

  • 相关阅读:
    常用算法编程题目学习与训练的网站
    ES6的JavaScript算法思想实现之分而治之,动态规划,贪心算法和回溯算法
    ES6的JavaScript算法实现之排序、搜索和随机算法
    ES6的JavaScript数据结构实现之图
    ES6的JavaScript数据结构实现之二叉堆和堆排序
    ES6的JavaScript数据结构实现之树(二叉搜索树、AVL树、红黑树)
    ES6的JavaScript数据结构实现之递归
    ES6的JavaScript数据结构实现之字典与散列表
    ES6的JavaScript数据结构实现之集合
    ES6的JavaScript数据结构实现之链表
  • 原文地址:https://www.cnblogs.com/eternityz/p/14751667.html
Copyright © 2011-2022 走看看