zoukankan      html  css  js  c++  java
  • 方法幂等性后端解决方案设计

    问题描述:

    在实际开发中,经常会因为接口响应时间过长,导致用户多次点击(连续)提交按钮。因此会创建多条相同的数据,如此就造成了数据重复。即我们常说的方法幂等性问题(就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用)

    思路一:前段解决,通过点击按钮后制灰控制按钮不可点击。
    思路二:后端解决,通过锁定参数+计时的方式,控制相同参数调用接口的次数。
    sequenceDiagram participant w as web页面 participant c as controller(后端:接收器) participant s as service(后端:业务组件) participant r as 缓存(数据库redis) loop 多次提交数据user123 w->>c: 提交数据到后台 end c->>r: 查询缓存user123 r->>c: 返回缓存结果 alt user数据已被缓存 c->>w: 告诉前段数据已提交请等待 else 未查询到user123数据 c->>r: 缓存请求数据user123 c->>s: 处理业务 end
    涉及技术:AOP注解+redis
    步骤一:定义注解 PowerReq
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface PowerReq {
        /**
         * 锁住方法中的第几个参数(-1全部参数)
         *
         * @return
         */
        int lockIndexParam() default -1;
    
        /**
         * 锁的时间
         *
         * @return
         */
        int leaseTime() default 10;
    }
    
    步骤二:定义注解解析器
    @Aspect
    @Component
    public class PowerReqAspect {
    
        @Resource
        private RedisTemplate redisTemplate;
    
        /**
         * 环绕通知:灵活自由的在目标方法中切入代码
         */
        @Around("@annotation(powerReq)")
        public Object around(ProceedingJoinPoint joinPoint, PowerReq powerReq) throws Throwable {
            // 获取待锁定的参数index
            int lockIndexParam = powerReq.lockIndexParam();
            // 获取方法传入参数
            Object[] params = joinPoint.getArgs();
            String i = params[lockIndexParam - 1].toString();
            ValueOperations valueOperations = redisTemplate.opsForValue();
            Object o = valueOperations.get(String.valueOf(i));
            if (Objects.isNull(o)) {
                valueOperations.set(String.valueOf(i), String.valueOf(i), powerReq.leaseTime(), TimeUnit.SECONDS);
                return joinPoint.proceed();
            }
            throw new Exception("数据已提交请等待");
    
    
        }
    }
    
    
    使用方式
    @PowerReq(lockIndexParam = 1)
    @RequestMapping("/lock")
    public Boolean hello1(@RequestBody String id, Map<String, String> param) {
      redissonService.tt(param.get("id"));
      logger.info("业务已完成={}", param);
      return Boolean.TRUE;
    }
    

    项目地址:https://gitee.com/liujinliang_gitee/think-in-springboot/tree/master/think-in-redis
  • 相关阅读:
    《第三周作业》——第四小组
    《UML与设计原则》--第四小组
    《我与计算机》——第四小组
    PSP数据比较(四则运算)——计应193第6组栗亚文
    个人工作流程(地铁收费系统)——计应193第6组张淑雅
    设计模式学习总结
    行为型模式总结
    UML第二部分和创建型模式的总结(二)
    UML第二部分和创建型模式的总结
    UML第一部分和设计模式原则的总结
  • 原文地址:https://www.cnblogs.com/jinliang374003909/p/15257215.html
Copyright © 2011-2022 走看看