分布式锁--防止重复提交
分布式锁,防重复提交
·
1.准备好Redisson的配置类,提供RedissonClient实例
package com.ynby.mis.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* Redisson的配置类,提供RedissonClient实例
*
* @author my
*/
@Configuration
public class RedissonConfiguration {
@Value("#{'${spring.redis.cluster.nodes}'.split(',')}")
private List<String> nodes;
@Value("${spring.redis.password}")
private String password;
@Bean
public RedissonClient getRedissonClient() {
Config config = new Config();
config.useClusterServers().setPassword(password);
//集群模式,集群节点的地址须使用“redis://”前缀,否则将会报错。
//此例集群为3节点,各节点1主1从
for (String node : nodes) {
String redisNode = "redis://" + node;
config.useClusterServers().addNodeAddress(redisNode);
}
return Redisson.create(config);
}
}
锁时间–默认锁五秒,可自由配置
package com.ynby.mis.util;
import java.lang.annotation.*;
/**
* @author xzt85
* @description 防止重复提交
* @date 2022/6/6 21:30
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatCommit {
long lockTime() default 5;
}
写一个切面
package com.ynby.mis.util;
import com.ynby.mis.config.MyException;
import com.ynby.mis.config.RedissonConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ObjectUtils;
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.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
@Slf4j
/**
* @description 防止重复提交
* @date 2022/6/6 21:30
*/
public class NoRepeatSubmitAspect {
private final static Logger logger = LoggerFactory.getLogger(NoRepeatSubmitAspect.class);
@Resource
private RedissonClient redissonClient;
@Autowired
private RedissonConfiguration redissonConfiguration;
@Pointcut("@annotation(repeatSubmit)")
public void pointcutNoRepeatSubmit(NoRepeatCommit repeatSubmit){
}
@Around("pointcutNoRepeatSubmit(noRepeatSubmit)")
public Object around(ProceedingJoinPoint joinPoint, NoRepeatCommit noRepeatSubmit) throws Throwable {
HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token=request.getHeader("token");
String path=request.getServletPath();
long lockTime=noRepeatSubmit.lockTime();
// String key="REPEAT_SUBMIT_" + path + token;
String key="REPEAT_SUBMIT_" + path;
// 分布式锁
RLock lock = redissonConfiguration.getRedissonClient().getLock(key);
logger.info("获取锁 = {}",lock);
// 尝试加锁,最多等待0秒,上锁以后5秒自动解锁[lockTime默认为5s, 用户可以自定义]
boolean res = lock.tryLock(0, lockTime, TimeUnit.SECONDS);
if(!res){
throw MyException.build("30001", "请勿重复提交");
}
Object object=joinPoint.proceed();
return object;
}
}
在需要防止重复提交的接口的Controller中加注解
@NoRepeatCommit(lockTime = 5)
@PutMapping("updateMakerLevel")
@NoRepeatCommit(lockTime = 5)
public CommonClientResponse<Boolean> updateMakerLevel(@RequestBody Map map) throws Exception {
更多推荐
已为社区贡献2条内容
所有评论(0)