package art.kexue.sxwz.aspect; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import art.kexue.sxwz.annotation.PreventDuplicateSubmission; import art.kexue.sxwz.exception.BizException; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import jakarta.servlet.http.HttpServletRequest; import java.util.concurrent.TimeUnit; /** * @author 维哥 * @Description * @create 2025-02-25 15:33 */ @Aspect @Component public class PreventDuplicateSubmissionAspect { private static final Cache requestCache = CacheBuilder.newBuilder() .expireAfterWrite(1, TimeUnit.MINUTES) // 缓存1分钟 .build(); // 处理方法级别注解 @Around("@annotation(art.kexue.sxwz.annotation.PreventDuplicateSubmission)") public Object preventDuplicateSubmissionMethod(ProceedingJoinPoint joinPoint) throws Throwable { return preventDuplicateSubmissionImpl(joinPoint); } // 处理类级别注解 @Around("@within(art.kexue.sxwz.annotation.PreventDuplicateSubmission)") public Object preventDuplicateSubmissionClass(ProceedingJoinPoint joinPoint) throws Throwable { return preventDuplicateSubmissionImpl(joinPoint); } // 实际的防重复提交逻辑 private Object preventDuplicateSubmissionImpl(ProceedingJoinPoint joinPoint) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String key = generateKey(request, joinPoint.getSignature().toShortString()); // 从joinPoint获取方法签名和注解 org.aspectj.lang.reflect.MethodSignature signature = (org.aspectj.lang.reflect.MethodSignature) joinPoint.getSignature(); // 先从方法上获取注解 PreventDuplicateSubmission preventDuplicateSubmission = signature.getMethod().getAnnotation(PreventDuplicateSubmission.class); // 如果方法上没有,再从类上获取 if (preventDuplicateSubmission == null) { preventDuplicateSubmission = (PreventDuplicateSubmission)signature.getDeclaringType().getAnnotation(PreventDuplicateSubmission.class); } // 确保注解存在 if (preventDuplicateSubmission == null) { throw new BizException("无法获取PreventDuplicateSubmission注解"); } Long lastRequestTime = requestCache.getIfPresent(key); long currentTime = System.currentTimeMillis(); if (lastRequestTime != null && (currentTime - lastRequestTime) < preventDuplicateSubmission.timeout()) { throw new BizException("瞬间操作过于频繁,请稍后再试"); } requestCache.put(key, currentTime); return joinPoint.proceed(); } private String generateKey(HttpServletRequest request, String methodSignature) { return request.getSession().getId() + ":" + methodSignature; } }