依赖版本
- spring-boot-starter 2.6.3
- redisson
<dependency>
<groupId>org.redissongroupId>
<artifactId>redisson-spring-boot-starterartifactId>
<version>3.17.1version>
dependency>
springboot配置单机版redisson
spring:
redis:
redisson:
config: |
singleServerConfig:
idleConnectionTimeout: 1000
connectTimeout: 1000
timeout: 2000
retryAttempts: 3
retryInterval: 500
password: 'xxx'
subscriptionsPerConnection: 5
clientName: redissonClient
address: "redis://127.0.0.1:6379"
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 3
connectionMinimumIdleSize: 4
connectionPoolSize: 8
database: 1
dnsMonitoringInterval: 5000
threads: 2
nettyThreads: 4
codec: ! {}
transportMode: "NIO"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
新增redisson工具类,避免释放锁的时候锁已过期导致抛异常
public class RedissonUtil {
public static boolean tryLockNoThrow(RLock lock, long waitTime, long leaseTime, TimeUnit unit) {
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
public static void unLockNoThrow(RLock lock) {
if (!lock.isHeldByCurrentThread()) {
return;
}
try {
lock.unlock();
} catch (Exception ex) {}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
新增分布式锁注解
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DistributedLock {
String lockKey();
long waitTimeInMill() default 0;
long leaseTimeInMill() default 10_000;
String errMsg() default "获取分布式锁失败";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 分布式锁参数注解,声明方法参数为分布式锁的key变量值
@Target(ElementType.PARAMETER)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface LockKey {
}
新增分布式锁注解切面,实现注解式分布式锁功能
@Aspect
@ConditionalOnClass(DistributedLock.class)
@Component
@RequiredArgsConstructor
@Slf4j
public class DistributedLockAop {
private final RedissonClient redissonClient;
@Pointcut("@annotation(com.chimelong.common.cache.support.DistributedLock)")
public void pointCut() {}
@Around("pointCut() && @annotation(lockAnno))")
public Object handle(ProceedingJoinPoint joinPoint, DistributedLock lockAnno) throws Throwable {
String lockKey = bindLockKey(joinPoint, lockAnno);
RLock lock = redissonClient.getLock(lockKey);
boolean flag = RedissonUtil.tryLockNoThrow(lock, lockAnno.waitTimeInMill(), lockAnno.leaseTimeInMill(), TimeUnit.MILLISECONDS);
if (!flag) {
log.error("分布式锁[{}]获取失败", lockAnno.lockKey());
throw new IllegalStateException(lockAnno.errMsg());
}
try {
return joinPoint.proceed();
} finally {
RedissonUtil.unLockNoThrow(lock);
}
}
private String bindLockKey(ProceedingJoinPoint joinPoint, DistributedLock lockAnno) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Annotation[][] annoArr = methodSignature.getMethod().getParameterAnnotations();
List<Boolean> flagList = new ArrayList<>(4);
for (Annotation[] annotations : annoArr) {
if (annotations == null || annotations.length == 0) {
continue;
}
boolean find = Stream.of(annotations).filter(item -> LockKey.class.equals(item.annotationType())).findFirst().isPresent();
flagList.add(find);
}
int flagSize = flagList.size();
if (flagSize < 1) {
return lockAnno.lockKey();
}
StringBuilder lockKeyBuilder = new StringBuilder(lockAnno.lockKey());
Object[] paramValList = joinPoint.getArgs();
for (int i = 0; i < paramValList.length; i++) {
if (i >= flagSize) {
break;
}
if (!flagList.get(i).booleanValue()) {
continue;
}
lockKeyBuilder.append(":")
.append(paramValList[i]);
}
return lockKeyBuilder.toString();
}
}

- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
使用
@PostMapping("/close")
@ApiOperation("关闭订单")
@DistributedLock(lockKey = RedisLockConst.ORDER_PREFIX)
public R<Boolean> closeUnpaidCompletedOrder(@ApiParam(value = "订单号", required = true) @LockKey @RequestParam String orderCode) {
return R.ok(true);
}