新建一个AOP接口 NoRepeatSubmit
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* NoRepeatSubmit
*
* @author lzt
* @version 1.0
* @description 重复点击的切面
* @date 2022-01-07
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {
/**
* 锁过期的时间
*/
int seconds() default 5;
/**
* 锁的位置
*/
String location() default "NoRepeatSubmit";
/**
* 要扫描的参数位置
*/
int argIndex() default 0;
/**
* 参数名称
*/
String name() default "";
}
创建一个切面类:NoRepeatSubmitAspect
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.company.project.common.aop.annotation.NoRepeatSubmit;
import com.company.project.common.exception.ApiException;
import com.company.project.common.utils.Constant;
import com.company.project.common.utils.DataResult;
import com.company.project.service.RedisService;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author Administrator
*/
@Slf4j
@Aspect
@Component
public class NoRepeatSubmitAspect {
private static final String SUFFIX = "SUFFIX";
@Autowired
RedisService redisService;
/**
* 横切点
*/
@Pointcut("@annotation(noRepeatSubmit)")
public void repeatPoint(NoRepeatSubmit noRepeatSubmit) {
}
/**
* 接收请求,并记录数据
*/
@Around(value = "repeatPoint(noRepeatSubmit)")
public Object doBefore(ProceedingJoinPoint joinPoint, NoRepeatSubmit noRepeatSubmit) {
String key = Constant.NO_REPEAT_LOCK_PREFIX + noRepeatSubmit.location();
Object[] args = joinPoint.getArgs();
String name = noRepeatSubmit.name();
int argIndex = noRepeatSubmit.argIndex();
String suffix;
if (StrUtil.isBlank(name)) {
String empId = "";
try {
JSONObject emp = JSONUtil.parseObj(args[argIndex]);
empId = emp.getStr("empId");
} catch (Exception e) {
}
if (StrUtil.isBlank(empId)) {
suffix = String.valueOf(args[argIndex]);
} else {
suffix = empId;
}
} else {
Map<String, Object> keyAndValue = getKeyAndValue(args[argIndex]);
Object valueObj = keyAndValue.get(name);
if (valueObj == null) {
suffix = SUFFIX;
} else {
suffix = String.valueOf(valueObj);
}
}
key = key + ":" + suffix;
int seconds = noRepeatSubmit.seconds();
if (redisService.setIfAbsent(key, key, seconds, TimeUnit.SECONDS)) {
return DataResult.fail("操作过于频繁,请稍后重试");
}
try {
Object proceed = joinPoint.proceed();
return proceed;
} catch (Throwable throwable) {
log.error("运行业务代码出错", throwable);
throw new ApiException(throwable.getMessage());
}
}
public static Map<String, Object> getKeyAndValue(Object obj) {
Map<String, Object> map = Maps.newHashMap();
// 得到类对象
Class userCla = (Class) obj.getClass();
/* 得到类中的所有属性集合 */
Field[] fs = userCla.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
Field f = fs[i];
// 设置些属性是可以访问的
f.setAccessible(true);
Object val = new Object();
try {
val = f.get(obj);
// 得到此属性的值
// 设置键值
map.put(f.getName(), val);
} catch (IllegalArgumentException e) {
log.error("getKeyAndValue IllegalArgumentException", e);
} catch (IllegalAccessException e) {
log.error("getKeyAndValue IllegalAccessException", e);
}
}
log.info("扫描结果:" + JSONUtil.toJsonStr(map));
return map;
}
}
示例: