package com.rdj.distributelock.lock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.core.types.Expiration;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
//AutoCloseable jdk1.7 后增加的 自动关闭特性
@Slf4j
public class RedisLock implements AutoCloseable{
private RedisTemplate redisTemplate;
private String key;
private String value;
private int expireTime;//过期时间,单位秒
public RedisLock(RedisTemplate redisTemplate, String key,int expireTime){
this.redisTemplate = redisTemplate;
this.key = key;
this.expireTime = expireTime;
this.value = UUID.randomUUID().toString();
}
/**
* 获取分布式锁
* @return
*/
public boolean getLock(){
RedisCallback<Boolean> redisCallback = connection -> {
RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();
Expiration expiration = Expiration.seconds(expireTime);
byte[] redisKey = redisTemplate.getKeySerializer().serialize(key);
byte[] redisValue = redisTemplate.getKeySerializer().serialize(value);
Boolean result = connection.set(redisKey, redisValue, expiration, setOption);
return result;
};
boolean lock = (boolean) redisTemplate.execute(redisCallback);
return lock;
}
public boolean unLock(){
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
RedisScript<Boolean> redisScript = RedisScript.of(script,Boolean.class);
List<String> keys = Arrays.asList(key);
Boolean res = (Boolean) redisTemplate.execute(redisScript, keys, value);
log.info("释放锁的结果 {}",res);
return res;
}
@Override
public void close() throws Exception {
unLock();
}
}
package com.rdj.distributelock.controller;
import com.rdj.distributelock.lock.RedisLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class RedisLockController {
@Autowired
private RedisTemplate redisTemplate;
@RequestMapping("/redisLock")
public String redisLock(){
log.info("进入了方法");
try(RedisLock redisLock = new RedisLock(redisTemplate,"redisKey",30)){
if (redisLock.getLock()) {
log.info("进入了锁.............");
Thread.sleep(15000);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
log.info("方法执行完成");
return "方法执行完成";
}
}