• 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

  • 相关阅读:
    主机与虚拟机通信:以主机VS2010连接虚拟机MySql为例
    Json与类对象转换
    VS附加到进程调试的方法及应用场景
    地图API使用文档-以腾讯地图为例
    JS使用ActiveXObject读取数据库代码示例(只支持IE)
    css文件内引用外部资源文件的相对路径
    ::after,::before使用
    高德地图API应用
    LogNet4学习笔记
    MvcPager分页控件的使用
  • 原文地址:https://www.cnblogs.com/eternityz/p/14751667.html
Copyright © 2020-2023  润新知