0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

推荐一种非侵入式幂等性的Java实现

jf_ro2CN3Fa 来源:芋道源码 2022-12-22 10:57 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

  • 幂等性
  • 什么场景下需要用到幂等
  • 幂等的实现原理
  • 幂等的代码实现
    • 幂等的使用

幂等性

今天我们来谈谈什么是幂等性

引用百度百科的解析如下:

幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。

编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“setTrue()”函数就是一个幂等函数,无论多次执行,其结果都是一样的.更复杂的操作幂等保证是利用唯一交易号(流水号)实现。

这解析,确实有点了,大家话看看就行了!!!(●'◡'●)

那对于我们程序员来说,我们关心的更多是下面这些问题:

什么地方,什么场景下需要用到幂等?

幂等,我们需要怎么做,如何实现幂等呢?

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

什么场景下需要用到幂等

  • 前端表单重复提交问题
  • 用户订单支付问题
  • 银行业务办理取号问题
  • 用户恶意进行调接口问题
  • 接口超时重复提交问题
  • MQ消息进行重复消费
  • ...

当然了,还有很多场景会用到幂等,这里咱们就不一一列举出来了。

那我们要如何设计一个幂等功能呢,而且还是代码非侵入式

代码非侵入式的意思,就是,我们的业务逻辑代码,不需要处理幂等校验的逻辑。

业务功能不处理?那交给谁处理呢?别着急,听哥们一一道来。^_^

这里,要实现代码非侵入式的幂等校验,我们就要使用到切面编程了(@Aspect

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

幂等的实现原理

在系统中一些接口需要增加幂等处理,幂等的概念是一个业务请求只能执行一次。类似银行业务办理,首先需要取一个号,然后用户使用这个号去柜台办理业务。这个号只能使用一次,如果过期或者已办理这个号就无效了。

我们的幂等也是使用这种原理。

  • 1.首先客户端调用通过我们的系统获取一个号,我们称之为幂等号,这个号已经存在我们的系统中。
  • 2.客户端使用这个号,调用我们的接口。
  • 3.我们系统判断这个号在我们的系统中已经存在,如果存在则允许业务办理,如果不存在,则表示这是一个非法的号,我们直接抛出异常。
  • 4.当业务处理完成,我们会将这个号从我们的系统中删除掉。

好了,这实现步骤,也是十分清晰了呀!!!^_^

那么我们下面就来看代码如何实现了

幂等的代码实现

  • 定义一个幂等处理接口
publicinterfaceIdempotence{
/**
*检查是否存在幂等号
*@paramidempotenceId幂等号
*@return是否存在
*/
booleancheck(StringidempotenceId);

/**
*记录幂等号
*@paramidempotenceId幂等号
*/
voidrecord(StringidempotenceId);

/**
*记录幂等号
*@paramidempotenceId幂等号
*@paramtime过期时间
*/
voidrecord(StringidempotenceId,Integertime);

/**
*删除幂等号
*@paramidempotenceId幂等号
*/
voiddelete(StringidempotenceId);

}
  • 定义一个幂等处理接口实现类
@Component
publicclassRedisIdempotenceimplementsIdempotence{
@Autowired
privateRedisRepositoryredisRepository;

@Override
publicbooleancheck(StringidempotenceId){
returnredisRepository.exists(idempotenceId);
}

@Override
publicvoidrecord(StringidempotenceId){
redisRepository.set(idempotenceId,"1");
}

@Override
publicvoidrecord(StringidempotenceId,Integertime){
redisRepository.setExpire(idempotenceId,"1",time);
}

@Override
publicvoiddelete(StringidempotenceId){
redisRepository.del(idempotenceId);
}
}

这个实现类,咱们就用redis存储这个幂等号 实现4个方法:

检查是否存在幂等号

记录幂等号

记录幂等号(带过期时间)

删除幂等号

  • 幂等工具类
@Component
publicclassIdempotenceUtil{
@Autowired
privateRedisRepositoryredisRepository;
/**
*生成幂等号
*@return
*/
publicStringgenerateId(){
Stringuuid=UUID.randomUUID().toString();
StringuId=Base64Util.encode(uuid).toLowerCase();
redisRepository.setExpire(uId,"1",1800);
returnuId;
}

/**
*从Header里面获取幂等号
*@return
*/
publicStringgetHeaderIdempotenceId(){
ServletRequestAttributesattributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequestrequest=attributes.getRequest();
StringidempotenceId=request.getHeader("idempotenceId");
returnidempotenceId;
}
}

这个工具类,提供两个方法。

1.生成一个幂等号,咱们就用uuid

2.从Header里面获取幂等号

  • 定义一个注解
/**
*接口增加幂等性
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interfaceIdempotenceRequired{

}
  • 切面
@Aspect
@Slf4j
@Component
publicclassIdempotenceSupportAdvice{
@Autowired
privateIdempotenceidempotence;
@Autowired
IdempotenceUtilidempotenceUtil;

/**
*拦截有@IdempotenceRequired注解的方法。
*/
@Pointcut("@annotation(xxx.xxx.IdempotenceRequired)")
publicvoididempotenceMethod(){}

@AfterThrowing(value="idempotenceMethod()()",throwing="e")
publicvoidafterThrowing(Throwablee){
if(!(einstanceofIdempotencyException)){
//从HTTPheader中获取幂等号idempotenceId
StringidempotenceId=idempotenceUtil.getHeaderIdempotenceId();
idempotence.record(idempotenceId,1800);
}
}

@Around(value="idempotenceMethod()")
publicObjectaround(ProceedingJoinPointjoinPoint)throwsThrowable{
//从HTTPheader中获取幂等号idempotenceId
StringidempotenceId=idempotenceUtil.getHeaderIdempotenceId();
if(StringUtils.isEmpty(idempotenceId)){
//不存在幂等号则不进行额外操作
returnjoinPoint.proceed();
}
//前置操作幂等号是否存在
booleanexisted=idempotence.check(idempotenceId);
if(!existed){
thrownewIdempotencyException("{success:false,message:"操作重复,请重新输入幂等号重试!",data:-2}");
}
//删除幂等号
idempotence.delete(idempotenceId);
Objectresult=joinPoint.proceed();

returnresult;
}
}
  • 定义个controller
@RequestMapping("/idempotence")
publicclassIdempotenceController{
/**
*生成幂等号
*@return
*/
@GetMapping("/generateId")
publicJsonResultgenerateId(){
IdempotenceUtilidempotenceUtil=SpringUtil.getBean(IdempotenceUtil.class);
StringuId=idempotenceUtil.generateId();
returnJsonResult.success("成功生成!").setData(uId);
}
}

好了,实现的代码,就是这些了,理解起来也是比较简单,没有过多复杂的逻辑。

接下来,就是如何使用的问题了,

这个使用,也是十分的简单啦!!!

幂等的使用

「服务端:」

不是所有的方法都需要切面拦截 ,只有 IdempotenceRequired 注解的方法才会被拦截。

例如下面接口:

@IdempotenceRequired
@PostMapping("/getUsers")
publicJsonResultgetUsers(){

//执行正常业务逻辑
...
}

在开发幂等接口时,只需要在方法上简单增加一个 IdempotenceRequired 注解即可。

这基本上就是代码非侵入式了呀!!!

「客户端:」

服务端处理好后,在客户端访问接口的时候需要执行以下步骤:

  • 需要先获取幂等号
  • 然后将幂等号添加到请求头中

  • 1.获取幂等号http://服务地址/idempotence/generateIdhttp://xn--zfry9hnb732h/idempotence/generateId
3d585d26-8135-11ed-8abf-dac502259ad0.jpg获取幂等号
  • 2.请求调用

往header中添加幂等号

3d7cbdf6-8135-11ed-8abf-dac502259ad0.jpg往header中添加幂等号

好了,到这里幂等的实现,就已经完成了!!!^_^

那我们就可以愉快的编写代码了!!!^_^


审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    20

    文章

    2997

    浏览量

    115700
  • 编程
    +关注

    关注

    90

    文章

    3708

    浏览量

    96777
  • 代码
    +关注

    关注

    30

    文章

    4942

    浏览量

    73160

原文标题:推荐一种非侵入式幂等性的Java实现

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    侵入局放监测革命:上海云瞳绿能科技的融合创新实践

    在电力设备智能运维领域,侵入安装与多技术融合正成为局放在线监测的核心突破点。上海云瞳绿能科技有限公司(以下简称“云瞳绿能”)通过 “特高频电磁波检测+ TEV(暂态地电压)+声波定位+温度监测” 的协同创新,重新定义了设备绝
    的头像 发表于 09-24 18:21 453次阅读
    <b class='flag-5'>非</b><b class='flag-5'>侵入</b><b class='flag-5'>式</b>局放监测革命:上海云瞳绿能科技的融合创新实践

    如何秒级实现接口间“”补偿:款轻量级仿数据校正处理辅助工具

    导语 本文分析了在网络超时场景下,RPC服务调用数据一致性的问题,对于接口无、接口失效情况下,对异常数据快速处理做了分析思考和尝试,
    的头像 发表于 09-15 16:55 618次阅读
    如何秒级<b class='flag-5'>实现</b>接口间“<b class='flag-5'>幂</b><b class='flag-5'>等</b>”补偿:<b class='flag-5'>一</b>款轻量级仿<b class='flag-5'>幂</b><b class='flag-5'>等</b>数据校正处理辅助工具

    行业洞察:聚焦超声在美容治疗中的应用

    持久的手术效果,部分疗程甚至在单次治疗后就能实现高达30%的皮肤紧致提升。2.侵入&停机时间极短与传统的美容手术不同,FUS提供了
    的头像 发表于 08-14 10:55 496次阅读
    行业洞察:聚焦超声在美容治疗中的应用

    鸿蒙侵入弹窗新解法,企查查正式开源“QuickDialog”弹窗组件库

    近日,企查查将其自研的鸿蒙弹窗组件库“QuickDialog”开源,并上线至 OpenHarmony 三方库中心仓。这是鸿蒙生态首个支持“弹窗堆栈暂存能力”的侵入弹窗解决方案,凭借其灵活、高效
    的头像 发表于 07-31 10:40 541次阅读
    鸿蒙<b class='flag-5'>非</b><b class='flag-5'>侵入</b><b class='flag-5'>式</b>弹窗新解法,企查查正式开源“QuickDialog”弹窗组件库

    文读懂:嵌入Linux实时进阶

    在工业控制、机器人、汽车电子关键领域,嵌入系统对实时性要求极高。 Linux作为强大的通用操作系统,其原生实时性能难以满足最严苛的硬实时需求。为突破这限制,PREEMPT_RT补丁
    发表于 07-10 15:26

    嵌入和单片机,是同个东西吗?

    设计用来执行特定的任务,并且通常嵌入在更大的系统中,比如家电、汽车电子、医疗设备。嵌入系统的特点是专用、资源受限和实时。 嵌入系统
    发表于 07-09 10:20

    深圳市回映电子科技公司简介/回映——侵入脑机接口与神经调控行业推动者

    深圳市回映电子科技有限公司深圳市回映电子科技有限公司,是专注于侵入脑机接口(BCI)技术与神经调控闭环系统的国家级高新技术企业。拥有多年底层技术研发、设计及生产制造的能力。我们致力于智能可穿
    的头像 发表于 06-24 21:57 1335次阅读
    深圳市回映电子科技公司简介/回映——<b class='flag-5'>非</b><b class='flag-5'>侵入</b><b class='flag-5'>式</b>脑机接口与神经调控行业推动者

    侵入经皮脊髓电刺激(tSCS)的神经机制与脊髓损伤康复临床应用

    经皮脊髓电刺激(transcutaneousspinalcordstimulation,tSCS)经皮脊髓电刺激是一种通过皮肤表面电极向脊髓背根传递低频脉冲电流、实现神经调控的侵入
    的头像 发表于 06-17 19:21 4448次阅读
    <b class='flag-5'>非</b><b class='flag-5'>侵入</b><b class='flag-5'>性</b>经皮脊髓电刺激(tSCS)的神经机制与脊髓损伤康复临床应用

    迪米科技接触红外测温应用:赋能养生壶智能化升级

    、迪米智能养生壶-接触红外测温介绍 传统温控技术依赖接触温度传感器,存在响应滞后、测温精度不足问题,难以满足用户对智能化与精准化的需求;在此,迪米科技测温模组利用
    发表于 05-20 21:43

    接触液位传感器在电池液液位检测中的技术实践与创新

    在电池技术不断发展的今天,电池的性能和安全备受关注。其中,电池液液位的准确检测对于保证电池的正常运行和延长使用寿命至关重要。接触液位传感器作为一种先进的检测技术,正逐渐在电池液液
    的头像 发表于 04-11 11:21 696次阅读
    论<b class='flag-5'>非</b>接触<b class='flag-5'>式</b>液位传感器在电池液液位检测中的技术实践与创新

    Java的SPI机制详解

    作者:京东物流 杨苇苇 1.SPI简介 SPI(Service Provicer Interface)是Java语言提供的一种接口发现机制,用来实现接口和接口实现的解耦。简单来说,就是
    的头像 发表于 03-05 11:35 1123次阅读
    <b class='flag-5'>Java</b>的SPI机制详解

    Meta AI推出Brain2Qwerty:侵入大脑信号转文本系统

    。 Brain2Qwerty系统主要依赖于侵入的技术手段来捕捉和解析大脑活动。具体而言,它结合了脑电图(EEG)和脑磁图(MEG)这两先进的神经科学工具,以精确记录志愿者在思考过
    的头像 发表于 02-11 13:37 877次阅读

    侵入路面状况传感器的技术优势

    在现代化的交通管理体系中,侵入路面状况传感器正以其接触检测原理,成为道路安全监测领域的新宠。
    的头像 发表于 02-10 11:51 520次阅读

    一种新型的晶态NbP半金属薄膜

    来自斯坦福大学和韩国Ajou大学的科学家们在《Science》杂志上发表了项开创的研究成果。他们发现了一种新型的晶态NbP半金属薄膜,其电阻率随着薄膜厚度的减小而显著降低,这
    的头像 发表于 02-07 10:08 1147次阅读
    <b class='flag-5'>一种</b>新型的<b class='flag-5'>非</b>晶态NbP半金属薄膜

    加州理工学院:研究一种无创监测女性激素的可穿戴生物传感器

    、摘要     女性激素(尤其是雌二醇)的个性化监测在生育和女性健康领域备受关注。然而,现有的方法通常需要侵入血液抽取和/或大型分析实验室设备,难以在家中实施。在此, 作者报告了一种
    的头像 发表于 01-22 09:22 2163次阅读
    加州理工学院:研究<b class='flag-5'>一种</b>无创监测女性激素的可穿戴生物传感器