当前位置 博文首页 > Monsterof的博客:Springboot框架防止前台重复提交(锁)
防止重复提交,主要是使用锁的形式来处理,如果是单机部署,可以使用本地缓存锁(Guava)即可。
一、本地锁(Guava)
1、导入依赖
<!--本地 缓存锁 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
2、自定义锁注解
package org.example.common.tool;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface LocalLock {
String key() default "";
//过期时间,使用本地缓存可以忽略,如果使用redis做缓存就需要
int expire() default 5;
}
3、锁注解实现
package org.example.common.tool;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springblade.core.tool.api.R;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
@Aspect
@Configuration
public class LockMethodInterceptor {
//定义缓存,设置最大缓存数及过期日期
private static final Cache<String,Object> CACHE = CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(20, TimeUnit.SECONDS).build();
@Around("execution(public * *(..)) && @annotation(org.springblade.common.tool.LocalLock)")
public Object interceptor(ProceedingJoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LocalLock localLock = method.getAnnotation(LocalLock.class);
String key = getKey(localLock.key(),joinPoint.getArgs());
if(!StringUtils.isEmpty(key)){
if(CACHE.getIfPresent(key) != null){
return R.fail("请勿重复请求!");
}
CACHE.put(key,key);
}
try{
return joinPoint.proceed();
}catch (Throwable throwable){
throw new RuntimeException("服务器异常!");
}finally {
}
}
private String getKey(String keyExpress, Object[] args){
for (int i = 0; i < args.length; i++) {
keyExpress = keyExpress.replace("arg[" + i + "]", args[i].toString());
}
return keyExpress;
}
}
4、Controller层
@ResponseBody
@ApiOperation(value="防重复提交验证测试")
@LocalLock(key = "localLock:test:arg[0]")
@PostMapping(value = "/localLock", consumes = {"application/json"})
public String localLock(String name){
return "返回成功!";
}
5、测试
6、结束语
希望能帮助大家,谢谢支持!
cs