Springboot框架防止前台重复提交(锁)

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、测试
第一次请求
重复请求

猜你喜欢

转载自blog.csdn.net/Monsterof/article/details/107951747
今日推荐