防止重复提交,通过AOP注解

53 阅读1分钟

NoRepeatSubmitAop


import java.lang.annotation.*;

/**
 * [防重复提交注解]</p >
 * @author chenp
 * @date 2024/1/8
 */
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented
public @interface NoRepeatSubmit {
    /**
     * 缓存的key
     * @return {@link String}
     */
    String key() default "";
    /**
     * 参数名称集合
     *
     * @return {@link String}
     */
    String[] args() default "";


    ResultCodesEnum defaultMsg() default ResultCodesEnum.ERROR_DEVICE_DAY_BEING_ERROR;
    /**
     * 存活时间
     */
    long survivalTime() default  60;
}

NoRepeatSubmit



import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author chenp
 * @date 2024/1/8
 */
@Component
@Aspect
@Slf4j
public class NoRepeatSubmitAop {

    @Resource
    private RedissonClient redissonClient;


    /**
     * @Title: queryCachePointcut
     * @Description: 定义切点为缓存注解
     * @return void
     **/
    @Pointcut("@annotation(com.......NoRepeatSubmit)")
    public void queryCachePointcut(){
    }

    @Around(value = "queryCachePointcut()&&@annotation(noRepeatSubmit)")
    public Object Interceptor(ProceedingJoinPoint joinPoint, NoRepeatSubmit noRepeatSubmit) throws Throwable{

            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            //参数名
            String[] parameterNames = signature.getParameterNames();
            //参数值
            Object[] method_args = joinPoint.getArgs();
            String[] args =   noRepeatSubmit.args();
            String params = ":";
            if(Objects.nonNull(args) && args.length>0 && Objects.nonNull(parameterNames) && parameterNames.length>0){
                for(int i=0;i<args.length;i++){
                    String[] split = args[i].split("\.");
                    for(int j=0;j<parameterNames.length;j++){
                        if(split[0].equals(parameterNames[j])){
                            if(split.length>1){
                                JSONObject jsonObject = (JSONObject) JSON.toJSON(method_args[j]);
                                params = params+jsonObject.get(split[1]);
                            }else{
                                params = params+method_args[j];
                            }

                        }
                    }
                }
            }else{
                params = params+method_args;
            }
            String key =  noRepeatSubmit.key() + params;
            long survivalTime = noRepeatSubmit.survivalTime();
            // 获取分布式锁
            RLock lock = redissonClient.getLock(key);
            try {
                if (lock.tryLock(1,survivalTime,TimeUnit.SECONDS)) {
                    // 执行关键业务逻辑
                    log.info("获取到锁{},key:{}", lock.getName(),key);
                    return joinPoint.proceed();
                } else {
                    // 未获取到锁,处理失败逻辑
                    log.info("未获取到锁");
                    return ResultVOUtil.error(noRepeatSubmit.defaultMsg());
                }
            }catch (Exception e){
                return ResultVOUtil.error();
            } finally {
                if (null != lock && lock.isLocked()) { // 是否还是锁定状态
                    if (lock.isHeldByCurrentThread()) {//是否是当前执行线程的锁
                        log.info("释放锁{}", lock.getName());
                        lock.unlock(); // 释放锁
                    }
                }
            }
    }
}