1,在application.properties中配置redis主机:
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=XXX
2,添加redis配置文件:
cache/RadisLock.java
import org.springframework.data.redis.core.RedisTemplate;
public class RedisLock {
private RedisTemplate<String, String> redisTemplate;
/**
* 重试时间
*/
private static final int DEFAULT_ACQUIRY_RETRY_MILLIS = 100;
/**
* 锁的后缀
*/
private static final String LOCK_SUFFIX = "_redis_lock";
/**
* 锁的key
*/
private String lockKey;
/**
* 锁超时时间,防止线程在入锁以后,防止阻塞后面的线程无法获取锁
*/
private int expireMsecs = 60 * 1000;
/**
* 线程获取锁的等待时间
*/
private int timeoutMsecs = 10 * 1000;
/**
* 是否锁定标志
*/
private volatile boolean locked = false;
/**
* 构造器
*
* @param redisTemplate
* @param lockKey 锁的key
*/
public RedisLock(RedisTemplate<String, String> redisTemplate, String lockKey){
this.redisTemplate = redisTemplate;
this.lockKey = lockKey + LOCK_SUFFIX;
}
/**
* 构造器
*
* @param redisTemplate
* @param lockKey 锁的key
* @param timeoutMsecs 获取锁的超时时间
*/
public RedisLock(RedisTemplate<String, String> redisTemplate, String lockKey, int timeoutMsecs){
this(redisTemplate, lockKey);
this.timeoutMsecs = timeoutMsecs;
}
/**
* 构造器
*
* @param redisTemplate
* @param lockKey 锁的key
* @param timeoutMsecs 获取锁的超时时间
* @param expireMsecs 锁的有效期
*/
public RedisLock(RedisTemplate<String, String> redisTemplate, String lockKey, int timeoutMsecs, int expireMsecs){
this(redisTemplate, lockKey, timeoutMsecs);
this.expireMsecs = expireMsecs;
}
public String getLockKey() {
return lockKey;
}
/**
* 封装和jedis方法
*
* @param key
* @return
*/
private String get(final String key) {
Object obj = redisTemplate.opsForValue().get(key);
return obj != null ? obj.toString() : null;
}
/**
* 封装和jedis方法
*
* @param key
* @param value
* @return
*/
private boolean setNX(final String key, final String value) {
return redisTemplate.opsForValue().setIfAbsent(key, value);
}
/**
* 封装和jedis方法
*
* @param key
* @param value
* @return
*/
private String getSet(final String key, final String value) {
Object obj = redisTemplate.opsForValue().getAndSet(key, value);
return obj != null ? (String) obj : null;
}
/**
* 获取锁
*
* @return 获取锁成功返回ture,超时返回false
* @throws InterruptedException
*/
public boolean lock() throws InterruptedException {
int timeout = timeoutMsecs;
while (timeout >= 0) {
long expires = System.currentTimeMillis() + expireMsecs + 1;
String expiresStr = String.valueOf(expires); // 锁到期时间
if (this.setNX(lockKey, expiresStr)) {
locked = true;
return true;
}
// redis里key的时间
String currentValue = this.get(lockKey);
// 判断锁是否已经过期,过期则重新设置并获取
if (currentValue != null && Long.parseLong(currentValue) < System.currentTimeMillis()) {
// 设置锁并返回旧值
String oldValue = this.getSet(lockKey, expiresStr);
// 比较锁的时间,如果不一致则可能是其他锁已经修改了值并获取
if (oldValue != null && oldValue.equals(currentValue)) {
locked = true;
return true;
}
}
timeout -= DEFAULT_ACQUIRY_RETRY_MILLIS;
// 延时
Thread.sleep(DEFAULT_ACQUIRY_RETRY_MILLIS);
}
return false;
}
/**
* 释放获取到的锁
*/
public void unlock() {
if (locked) {
redisTemplate.delete(lockKey);
locked = false;
}
}
}
3,在代码中使用redis:
/**
* 新建sdk组织
*
* @param request
* @param result
*/
@RequestMapping(value = "/sdk", method = RequestMethod.POST)
public ResponseResult createBizSDKGroups(HttpServletRequest request,
@RequestBody @Validated final SdkGroupAO sdkGroupAO, BindingResult result) {
ResultDelegate delegate = new ResultDelegate() {
@Override
public Object getResultObject() {
RedisLock redisLock = new RedisLock(redisTemplate, "create#sdkgroup#" + sessionUser);
try {
if (redisLock.lock()) {
try {
bizGroupService.createBizSDKGroup(sessionUser, sdkGroupAO);
} finally {
redisLock.unlock();
}
} else {
return "请不要多次点击";
}
} catch (InterruptedException e) {
return "创建失败";
}
return 1;
}
};
return getResponseResult(request, delegate, result);
}