ddd的工具之一--接口的幂等(防止接口重复提交)

273 阅读2分钟

1. 问题

如果我们在短时间内多次点击提交的接口,一般的情况是如下的流程:

image.png

正常流程

image.png

找到用户后提示信息

单个信息是正常的,但如果用户在短时间内多次点击,如下图,两个相同的信息同时过来,第一个还没有来得及保存,第二个已经同时开始查询了,这里就会出现同一个数据会被多次保存。

image.png

多次提交的示意图

2. 解决思路

image.png 这里可能有人会问到,那这个主键是不是记录到了redis中会一直存在吗?不会的,因为这里使用到的redis的特性,记录的过期时间,设定好30秒过期时间就可以,这里也就是说,如果30秒内,用户提交的数据主键是相同的,我们就认为是重复提交的无用数据,给用户相关的提示就可以了

image.png

3. 代码解读 如下图,这里是自定义了一个注解@RepeattAnnoatation,可以放到api的方法上面。RepeatSubmitInterceptor是拦截类,用于做注解的解析。从注解那里获取到有用的定义的主健是什么,从入参那里取到相应的数据,并可以根据 这个来判断是否有重复,并确认重复后应当如何处理。 这里有一点要说明一下

为什么会有一个BodayReaderWrapper的类

这是因为inputStream的特殊之处,只要在fiter中已经读过一次了,它会将读取的指针指向流的最后,就没有办法再将指针放回到最前面(有人说这里有一个reset可以复位,但我试了一下,没有成功),所以需要copy一个相同的对象出来,给监听器interceptor解析入参中是否有重复的数据。

image.png 4. 代码

代码地址参考:gitee.com/wuabc0954/f… 中redislock就是相关的组件,可以直接下载使用,这里如何打成相关的包,我还不会,正在学习中。 image.png

使用的方法

image.png 遗留问题

这里是还是完美的解决了所有的问题的,答案是否定的,这里其实是还有一个问题没有解决,如果你的方法在过期的时间内还没有完成呢事务呢?但redis中的主键已经过期了,下一个相同的数据过来了,可能又会有重复的数据了。这种可能性可能很低,但也是有可能的,这个后面我再来讲如何处理,提示一下可以使用切面来处理