我们在做web应用的时候通常会遇到前端提交按钮重复点击的场景,在某些新增操作上就需要做幂等性限制来保证数据的可靠性。下面来用java aop实现幂等性校验。

一:首先我们需要一个自定义注解

packagecom.yuku.yuku_erp.annotation;import java.lang.annotation.*;/***@author名一
* @ClassName IdempotentAnnotation
* @description: 用来标记需要校验幂等性的接口
* @datetime 2024年 02月 03日 14:48
*
@version: 1.0*/@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interfaceIdempotentAnnotation {
String idempotentType();
}

二:创建一个幂等校验的切面类

packagecom.yuku.yuku_erp.aop;importcom.yuku.yuku_erp.annotation.IdempotentAnnotation;importcom.yuku.yuku_erp.constant.RedisKeyConstant;importcom.yuku.yuku_erp.exception.MyException;importcom.yuku.yuku_erp.utils.RedisShardedPoolUtil;importcom.yuku.yuku_erp.utils.TokenUtil;importlombok.extern.slf4j.Slf4j;importorg.aspectj.lang.JoinPoint;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Before;importorg.aspectj.lang.annotation.Pointcut;importorg.aspectj.lang.reflect.MethodSignature;importorg.springframework.stereotype.Component;importjava.lang.reflect.Method;/***@author名一
* @ClassName CheckIdempotentAop
* @description: 幂等性校验
* @datetime 2024年 02月 03日 14:59
*
@version: 1.0*/@Slf4j
@Aspect
@Component
public classCheckIdempotentAop {

@Pointcut(
"execution(* com.yuku.yuku_erp.controller..*.*(..))")public voidcheckCut(){
}

@Before(
"checkCut()")public voidcheckIdempotent(JoinPoint joinPoint){
MethodSignature signature
=(MethodSignature) joinPoint.getSignature();
Method method
=signature.getMethod();if (method.isAnnotationPresent(IdempotentAnnotation.class)){
IdempotentAnnotation annotation
= method.getAnnotation(IdempotentAnnotation.class);
String idempotentType
=annotation.idempotentType();
String idempotentToken
= TokenUtil.getRequest().getHeader("idempotentToken");
String idemToken
= idempotentType +idempotentToken;
log.info(
"checkIdempotent idempotentType:{}, idempotentToken:{}", idempotentType, idempotentToken);

Boolean flag
=RedisShardedPoolUtil.sismember(RedisKeyConstant.IDEMPOTENT_TOKEN_LIST, idemToken);if (!flag){
log.error(
"checkIdempotent error idempotentType:{}, idempotentToken:{}, flag:{}", idempotentType, idempotentToken, flag);throw new MyException("该接口已提交过,请不要重复提交");
}
RedisShardedPoolUtil.delSetByValue(RedisKeyConstant.IDEMPOTENT_TOKEN_LIST, idemToken);
log.info(
"checkIdempotent idempotentType:{}, idempotentToken:{}, flag:{}", idempotentType, idempotentToken, flag);
}
}
}

三:在需要切面的接口上使用幂等校验注解

@IdempotentAnnotation(idempotentType = "checkIdempotentToken")
@GetMapping(
"/checkIdempotentToken")
@ApiOperation(value
= "校验幂等性示例")public CommonResult<String>checkIdempotentToken(){returnCommonResult.success();
}

到此幂等校验就完成了

标签: none

添加新评论