美文网首页
token 方式处理接口幂等性

token 方式处理接口幂等性

作者: miniy_7 | 来源:发表于2019-06-04 19:16 被阅读0次

方式系统接口的重复调用,在分布式系统中A服务重复向B服务发送指令,导致B服务重复消费消息。
在单体系统中类似新增操作重复指令,导致系统参数多天重复数据。

方式一
数据库增加唯一索引,保证数据的唯一性
方式二
接口增加幂等性校验
具体方式如下:
①定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Ide {
}

②aop 实现

@Aspect
@Component
public class IdeAspect {
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private RedisTemplate redisTemplate;

    private final  String msg  ="token 失效,请刷新页面后再进行提交!";

    @Pointcut("@annotation(com.laiease.common.annotation.Ide)")
    public void idePointCut() {

    }

    @Around("idePointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        JSONObject json = JSONObject.parseObject(HttpHelper.getBodyString(request));
        Optional<JSONObject> optional = Optional.ofNullable(json);
        String ide = optional.map(item -> item.getString("ide")).orElseThrow(() -> new RuntimeException(msg));
        Map map = (Map) redisTemplate.opsForValue().get(ide);
        if (map!=null&&(methodName.equals(map.get("method"))&&1==(int)map.get("status"))) {
            map.put("status",0);
            redisTemplate.opsForValue().set(ide, map);
        } else {
            throw new RuntimeException(msg);
        }
        R r  = (R) joinPoint.proceed();
        Map result = (Map) r.get("data");
        if(null!= result.get("status") && (boolean)result.get("status")){
            redisTemplate.delete(ide);
        }else{
            map.put("status",1);
            redisTemplate.opsForValue().set(ide, map);
        }
        return r;
    }

    @AfterThrowing(pointcut = "idePointCut()", throwing = "ex")
    public void afterThrowing(Throwable ex) {
        if (!msg.equals(ex.getMessage())) {
            HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
            JSONObject json = JSONObject.parseObject(HttpHelper.getBodyString(request));
            String ide = json.getString("ide");
            Map map = (Map) redisTemplate.opsForValue().get(ide);
            if (map != null) {
                map.put("status", 1);
                redisTemplate.opsForValue().set(ide, map);
            }
        }
    }

}

③定义获取token的接口供前端调用,实现接口可以使用雪花算法或者其他

    @Override
    public String getMethodsToken(JSONObject jsonObject) {
        Map map = new HashMap();
        Optional<JSONObject> optional = Optional.ofNullable(jsonObject);
        String method = optional.map(item -> item.getString("method")).orElseThrow(() -> new RuntimeException("异常操作"));
        String ide = CmUtil.getUUID();
        map.put("method",method);
        map.put("status",1);
        redisTemplate.opsForValue().set(ide, map);
        return ide;
    }

④使用
在Controller 层 新增接口或者其他方法接口上增加注解

    @Ide
    @Lelog("保存用户")
    @ApiOperation(value = "保存用户")
    @PostMapping(value = "/save")
    public R save(@RequestBody User user) throws Exception {
        return R.ok(userService.saveOne(user));
    }

补充:HttpHelper 工具类


@Slf4j
public class HttpHelper {

    private final static String xssWhitelist = PropertiesUtil.builder("config.properties").getProperty("sys.xss.whitelist");

    public static String getBodyString(HttpServletRequest request) {
        StringBuilder sb = new StringBuilder();
        String result = "";

        try (InputStream inputStream = request.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")))) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            result = sb.toString();

            if (!isUrlPass(request.getRequestURI())) {
                // xss sql 过滤
                result = xssSqlLeach(result);
            }
        } catch (IOException e) {
            log.error(e.toString());
        }
        return result;
    }

    private static String xssSqlLeach(String body) {


        if (body == null || body.isEmpty()) {
            return body;
        }
        StringBuilder sb = new StringBuilder(body.length());
        for (int i = 0; i < body.length(); i++) {
            char c = body.charAt(i);
            switch (c) {
                case '>':
                    sb.append("》");// 转义大于号
                    break;
                case '<':
                    sb.append("《");// 转义小于号
                    break;
                case '\'':
                    sb.append("‘");// 转义单引号
                    break;
                case '\"':
                    sb.append('"');// 转义双引号
                    break;
                case '&':
                    sb.append("&");// 转义&
                    break;
                default:
                    String s1 = c + "";
                    String s = s1.replaceAll(".*([';]+|(--)+).*", "");
                    sb.append(s);
                    break;
            }

        }
        return sb.toString();
    }

    private static boolean isUrlPass(String url) {
        String[] urlList = xssWhitelist.split(";");

        return ArrayUtils.contains(urlList, url);
    }

}

使用redis 分布式锁处理接口幂等性 redis 分布式锁处理接口幂等性

相关文章

  • token 方式处理接口幂等性

    方式系统接口的重复调用,在分布式系统中A服务重复向B服务发送指令,导致B服务重复消费消息。在单体系统中类似新增操作...

  • 接口幂等性处理

    插入数据业务,设计和使用数据库的唯一索引, 重复的时候就会报错 更新的类型的接口。 可以基于Redis来做。使用A...

  • SpringBoot接口幂等性实现的4种方案!

    目录 什么是幂等性 什么是接口幂等性 为什么需要实现幂等性 引入幂等性后对系统的影响 Restful API 接口...

  • 什么是接口的幂等性,如何实现接口幂等性?一文搞定

    每天一个知识点 什么是接口的幂等性,如何实现接口幂等性? (一)幂等性概念 幂等性原本是数学上的概念,用在接口上就...

  • redis 分布式锁处理接口幂等性

    之前博文中介绍过token 机制处理 接口幂等性问题,这种方式一个问题对代码的入侵比较多,相对书写代码来讲就比较麻...

  • 架构

    1、接口幂等性的实现方式 一、数据库去重表 二、状态机 三、TOKEN机制 2、如何避免下重复订单 1、当进入商品...

  • 高并发下的接口幂等性解决方案

    高并发下的接口幂等性解决方案 1.token机制,防止页面重复提交 流程如下: 1.发送方记录token(GUID...

  • 接口幂等性

    接口幂等性 什么是接口幂等性? 最简单想到的实现接口幂等性(重复提交)的操作是什么? 最简单稍靠谱的解决方案是什么?

  • 接口的幂等性方式

    在实际的项目中我们有很多操作,如api请求,订单付款,发送消息,防重复提交等。不管我们做了多少次,其实应该产生一样...

  • 接口幂等性书目录

    1.幂等性定义 1.1 数学定义 1.2 HTTP规范的定义 2. 何种接口提供幂等性 2.1 HTTP支持幂等性...

网友评论

      本文标题:token 方式处理接口幂等性

      本文链接:https://www.haomeiwen.com/subject/krdxsqtx.html