1. 修改 SysNotification 实体,新增 senderId, senderName, targetType 字段 2. 新增 SendNotificationRequest 请求DTO 3. 扩展通知类型至6种(新增用户通知、课程通知) 4. 实现角色层级权限控制,支持多级管理员通知下级 5. 支持老师群发课程通知给学生 6. 新增批量发送接口和权限配置
78 lines
3.2 KiB
Java
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;
|
|
}
|
|
}
|