1.添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.添加配置类:
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfig {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private String redisPost;
@Value("${spring.redis.password}")
private String redisPassword;
@Bean(destroyMethod = "shutdown")
public RedissonClient createRedissonClient(){
Config config = new Config();
SingleServerConfig singleServerConfig = config.useSingleServer();
singleServerConfig.setAddress("redis://" + redisHost + ":" + redisPost);
singleServerConfig.setPassword(redisPassword);
singleServerConfig.setTimeout(3000);
singleServerConfig.setDatabase(1);
return Redisson.create(config);
}
@Bean
public RedissonDistributedLockImpl redissonLocker(RedissonClient redissonClient) {
RedissonDistributedLockImpl locker = new RedissonDistributedLockImpl(redissonClient);
return locker;
}
}
3.添加自定义注解类:
3.1annotation:
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedissonLock {
}
3.2aspect:
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.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
@Slf4j
public class RedissonLockAspect {
public static final int WAIT_GET_LOCK_TIME = 3000;
public static final int WAIT_RELEASE_LOCK_TIME = 5000;
@Autowired
private IRedissonDistributedLock iRedissonDistributedLock;
@Value("${spring.application.name}")
private String serverName;
@Pointcut("@annotation(com.xx.xx.xx.redis.redisson.aspect.annotation.RedissonLock)")
public void redissonLockPoint() {
}
@Around("redissonLockPoint()")
public Object checkLock(ProceedingJoinPoint point) throws Throwable {
String threadName = Thread.currentThread().getName();
Object className = point.getTarget().getClass().getName();
String methodName = point.getSignature().getName();
log.info("当前线程:{}------进入分布式锁AOP------", threadName);
String lockRedisKey = serverName + ":" + className + ":" + methodName;
log.info("当前线程:{},分布式锁的key:{}", threadName, lockRedisKey);
if (iRedissonDistributedLock.tryLock(lockRedisKey, WAIT_GET_LOCK_TIME, WAIT_RELEASE_LOCK_TIME, TimeUnit.MILLISECONDS)) {
try {
log.info("当前线程:{},获取锁成功", threadName);
return point.proceed();
} catch (Throwable throwable) {
throw new Exception(throwable);
} finally {
if (iRedissonDistributedLock.isLocked(lockRedisKey)) {
log.info("当前线程:{}, key:{},对应的锁被线程持有", threadName, lockRedisKey);
if (iRedissonDistributedLock.isHeldByCurrentThread(lockRedisKey)) {
log.info("当前线程:{},key:{},保持锁定", threadName, lockRedisKey);
iRedissonDistributedLock.unlock(lockRedisKey);
log.info("当前线程:{},key:{},释放锁", threadName, lockRedisKey);
}
}
}
} else {
log.info("当前线程:{},获取锁失败", threadName);
return Result.error(AppErrorCodeEnum.SYSTEM_BUSY.getMessage());
}
}
}
4.添加redisson客户端类:
4.1接口:
import java.util.concurrent.TimeUnit;
public interface IRedissonDistributedLock {
void lock(String lockKey);
void lock(String lockKey, int timeout);
void lock(String lockKey, int timeout, TimeUnit unit);
void unlock(String lockKey);
boolean tryLock(String lockKey);
boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit)
throws InterruptedException;
boolean isLocked(String lockKey);
boolean isHeldByCurrentThread(String lockKey);
}
4.2实现:
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
public class RedissonDistributedLockImpl implements IRedissonDistributedLock {
private final RedissonClient redissonClient;
public RedissonDistributedLockImpl(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@Override
public void lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
}
@Override
public void lock(String lockKey, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.MILLISECONDS);
}
@Override
public void lock(String lockKey, int timeout, TimeUnit unit) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
}
@Override
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
@Override
public boolean tryLock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
return lock.tryLock();
}
@Override
public boolean tryLock(String lockKey, long waitTime, long leaseTime,
TimeUnit unit) throws InterruptedException {
RLock lock = redissonClient.getLock(lockKey);
return lock.tryLock(waitTime, leaseTime, unit);
}
@Override
public boolean isLocked(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
return lock.isLocked();
}
@Override
public boolean isHeldByCurrentThread(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
return lock.isHeldByCurrentThread();
}
}