Pārlūkot izejas kodu

系统模块-重复提交切面

ZhangWenQiang 5 gadi atpakaļ
vecāks
revīzija
55b45cb078

+ 30 - 0
happy-boot-base-common/src/main/java/org/jeecg/common/aspect/annotation/LimitSubmit.java

@@ -0,0 +1,30 @@
+package org.jeecg.common.aspect.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2020/8/13 17:02
+ * @Description: 自定义注解限制重复提交
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface LimitSubmit {
+
+    String key();
+
+    /**
+     * 默认 3s
+     */
+    int limit() default 3;
+
+    /**
+     * 请求完成后 是否一直等待
+     * true则等待
+     *
+     * @return
+     */
+    boolean needAllWait() default true;
+}

+ 90 - 0
happy-boot-module-system/src/main/java/org/jeecg/modules/system/aspect/LimitSubmitAspect.java

@@ -0,0 +1,90 @@
+package org.jeecg.modules.system.aspect;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.SecurityUtils;
+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.jeecg.common.aspect.annotation.LimitSubmit;
+import org.jeecg.common.exception.JeecgBootException;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.common.util.RedisUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+
+/**
+ * @Author: zwq
+ * @Date: Create in 2020/8/13 17:04
+ * @Description:
+ */
+@Slf4j
+@Aspect
+@Component
+public class LimitSubmitAspect {
+
+    @Autowired
+    private RedisUtil redisUtil;
+
+    @Pointcut("@annotation(org.jeecg.common.aspect.annotation.LimitSubmit)")
+    private void pointcut() {
+    }
+
+    @Around("pointcut()")
+    public Object handleSubmit(ProceedingJoinPoint joinPoint) throws Throwable {
+        //由于需要获取用户信息,故只在满足shiro登录态的情况下使用该切面方法
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
+
+        //获取注解信息
+        LimitSubmit limitSubmit = method.getAnnotation(LimitSubmit.class);
+        int submitTimeLimiter = limitSubmit.limit();
+        String redisKey = limitSubmit.key();
+        boolean needAllWait = limitSubmit.needAllWait();
+
+        String key = getRedisKey(sysUser, joinPoint, redisKey);
+        Object result = redisUtil.get(key);
+        if (result != null) {
+            throw new JeecgBootException("请勿重复操作!");
+        }
+        redisUtil.set(key, sysUser.getId(), submitTimeLimiter);
+        try {
+            Object proceed = joinPoint.proceed();
+            return proceed;
+        } catch (Throwable e) {
+            log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(),
+                    joinPoint.getSignature().getName(), e.getCause() != null ? e.getCause() : "NULL", e.getMessage(), e);
+            throw e;
+        } finally {
+            if (!needAllWait) {
+                redisUtil.del(redisKey);
+            }
+        }
+    }
+
+    /**
+     * 支持多参数,从请求参数进行处理
+     */
+    private String getRedisKey(LoginUser sysUser, ProceedingJoinPoint joinPoint, String key) {
+        if (key.contains("%s")) {
+            key = String.format(key, sysUser.getId());
+        }
+        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
+
+        LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
+        String[] parameterNames = discoverer.getParameterNames(method);
+        if (parameterNames != null) {
+            for (int i = 0; i < parameterNames.length; i++) {
+                String item = parameterNames[i];
+                if (key.contains("#" + item)) {
+                    key = key.replace("#" + item, joinPoint.getArgs()[i].toString());
+                }
+            }
+        }
+        return key.toString();
+    }
+}