AOP防止接口重复提交

实现原理

  • 通过自定义注解标记哪些接口需要防范重复提交问题,并定义保持时间;
  • 在Aspect中定义切点,织入所有被自定义注解标记的方法;
  • 在Aspect中定义通知方法,通过PointCut获取类全名、被标记的方法名、参数名Json后的字符串,链接后MD5获取唯一签名,以签名为key,利用Redis的setNX实现重复校验。

自定义注解

package com.yxx.survey.foundation.aop;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatSubmitCheck {
    int keepSeconds() default 1;
}

Aspect

package com.yxx.survey.foundation.aop;

import com.alibaba.fastjson.JSON;
import com.yxx.survey.foundation.exception.ErrorEnum;
import com.yxx.survey.foundation.exception.excetion.BusinessException;
import com.yxx.survey.foundation.redis.RedisService;
import com.yxx.survey.foundation.util.encryption.HashUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;


@Aspect
@Component
@Slf4j
public class RepeatSubmitAspect {
    @Resource
    private RedisService redisService;

    @Pointcut("@annotation(RepeatSubmitCheck)")
    public void requestPointcut() {
    }

    @Before("requestPointcut() && @annotation(repeatSubmitCheck)")
    public void aroundCheck(JoinPoint joinPoint, RepeatSubmitCheck repeatSubmitCheck) {
        String className = joinPoint.getTarget().getClass().getName();

        String methodName = joinPoint.getSignature().getName();

        Object[] args = joinPoint.getArgs();
        String paramsJsonStr = JSON.toJSONString(args);

        String srcStr = className + "_" + methodName + "_" + paramsJsonStr;
        log.info(srcStr);

        String signStr = HashUtil.MD5(srcStr);

        if (!redisService.setIfNotExists(signStr, "1", repeatSubmitCheck.keepSeconds())) {
            throw BusinessException.with(ErrorEnum.INTERFACE_INVOKE_FREQUENTLY);
        }
    }
}

应用

    @PostMapping("/public/verificationCode")
    @RepeatSubmitCheck(keepSeconds = 30)
    public ResponseEntity> sendVerificationCode(@Valid @RequestBody LoadVerifyCodeReq req) {
}

你可能感兴趣的:(AOP防止接口重复提交)