sxwz2.0/src/main/java/art/kexue/sxwz/aspect/PreventDuplicateSubmissionAspect.java
wangzhiwei 5f5c0759ce feat(notification): 实现通知功能,支持角色层级发送和课程群发
1. 修改 SysNotification 实体,新增 senderId, senderName, targetType 字段

2. 新增 SendNotificationRequest 请求DTO

3. 扩展通知类型至6种(新增用户通知、课程通知)

4. 实现角色层级权限控制,支持多级管理员通知下级

5. 支持老师群发课程通知给学生

6. 新增批量发送接口和权限配置
2026-05-15 16:57:07 +08:00

78 lines
3.2 KiB
Java

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<String, Long> 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;
}
}