springboot表单重复提交校验(基于注解和AOP)

  • Post author:
  • Post category:其他


自我记录,有用得到的拿去用,有问题私信我

  • 定义注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NoRepeatSubmit {

    /**
     * 默认1s钟以内算重复提交
     * @return
     */
    long timeout() default 1;
    
}
  • 定义切面

@Aspect
@Component
public class NoRepeatSubmitAop {
    @Resource
    private RedisUtils redisUtils;
    /**
     * 	定义切入点
     */
    @Pointcut("@annotation(app.annotation.NoRepeatSubmit)")
    public void noRepeat() {}

    /**
     * 	前置通知:在连接点之前执行的通知
     * @param point
     * @throws Throwable
     */
    @Before("noRepeat()")
    public void before(JoinPoint point) throws Exception{
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        String token = IpUtils.getIpAddr(request);
        String path = request.getServletPath();
        String key = getKey(token, path);
        String clientId = getClientId();
        String accessToken = (String)redisUtils.get(key);
        // 获取注解,拿到自定义时间(timeout)
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        NoRepeatSubmit annotation = method.getAnnotation(NoRepeatSubmit.class);
        long timeout = annotation.timeout();
        boolean isSuccess = false;
        if (StringUtils.isBlank(accessToken)) {
            isSuccess = redisUtils.set(key,clientId,timeout);
        }
        if (!isSuccess) {
            redisUtils.set(key,clientId,timeout);
            // 自定义BizExeption,不会的往下看
            throw new BizException("请勿重复提交");
        }
    }

    private String getKey(String token, String path) {
        return token + path;
    }

    private String getClientId() {
        return UUID.randomUUID().toString();
    }
}
  • 直接方法上写加上注解就可以用了,timeout可自定义

    @NoRepeatSubmit(timeout = 2)
  • 自定义异常

@Data
public class BizException extends RuntimeException{
    /**
     * 错误码
     */
    public Integer errorCode;
    /**
     * 错误信息
     */
    public String errorMsg;

    public BizException() {
        super();
    }

    public BizException(Integer code ,String errorMsg) {
        super(errorMsg);
        this.errorCode = code;
        this.errorMsg = errorMsg;
    }

    public BizException(String errorMsg) {
        super(errorMsg);
        this.errorMsg = errorMsg;
    }

    public BizException(Integer errorCode, String errorMsg, Throwable cause) {
        super(errorMsg, cause);
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    @Override
    public Throwable fillInStackTrace() {
        return this;
    }
}
  • 全局异常处理类

@RestControllerAdvice
public class GlobalExceptionHandler {
   
    @ExceptionHandler(BizException.class)
    public Packet runtimeException(BizException e) throws Exception {
        return ItemPacket.fail(e.getErrorMsg());
    }
}

完事了



版权声明:本文为kaola_l原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。