@Slf4j
@Aspect
@Component
public class IdempotentAOP {
/** Redis前缀 */
private final String API_IDEMPOTENT_CHECK = "API_IDEMPOTENT_CHECK:";
@Resource
private HttpServletRequest request;
@Resource
private RedisUtil redisUtil;
/**
* 定义切面
*/
@Pointcut("@annotation(com.uinnova.product.eam.web.aop.NotRepeat)")
public void notRepeat() {
}
/**
* 在接口原有的方法执行前,将会首先执行此处的代码
*/
@Before("notRepeat()")
public void doBefore(JoinPoint joinPoint) {
String uri = request.getRequestURI();
// 登录后才做校验
SysUser loginUser = SysUtil.getCurrentUserInfo();
if (loginUser != null) {
assert uri != null;
String key = loginUser.getLoginCode() + "_" + uri;
log.info(">>>>>>>>>> 【IDEMPOTENT】开始幂等性校验,加锁,account: {},uri: {}", loginUser.getLoginCode(), uri);
// 加分布式锁
boolean lockSuccess = redisUtil.setnx(API_IDEMPOTENT_CHECK + key, "1", 60, TimeUnit.SECONDS);
log.info(">>>>>>>>>> 【IDEMPOTENT】分布式锁是否加锁成功:{}", lockSuccess);
if (!lockSuccess) {
if (uri.contains("/uploadContextFile")) {
log.error(">>>>>>>>>> 【IDEMPOTENT】文件保存中,请稍候");
throw new IllegalArgumentException("文件保存中,请稍候");
} else if (uri.contains("contract/saveContract")) {
log.error(">>>>>>>>>> 【IDEMPOTENT】文件发起中,请稍后");
throw new IllegalArgumentException("文件发起中,请稍后");
}
}
}
}
/**
* 在接口原有的方法执行后,都会执行此处的代码(final)
*/
@After("notRepeat()")
public void doAfter(JoinPoint joinPoint) {
// 释放锁
String uri = request.getRequestURI();
assert uri != null;
SysUser loginUser = SysUtil.getCurrentUserInfo();
if (loginUser != null) {
String key = loginUser.getLoginCode()+ "_" + uri;
log.info(">>>>>>>>>> 【IDEMPOTENT】幂等性校验结束,释放锁,account: {},uri: {}", loginUser.getLoginCode(), uri);
redisUtil.del(API_IDEMPOTENT_CHECK + key);
}
}
}
用分布式锁解决