1.添加依赖
<!--springboot startWeb -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<!-- redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.2</version>
</dependency>
<!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.12.3</version>
</dependency>
2.配置属性
spring:
redis:
host: 127.0.0.1
port: 8999
database: 1
password: 12356
3.编写RedissonConfig
/**
*@ClassName RedissonConfig
*@Description Redisson框架集成
*@Author
*@Date
*@Time
*@Version v1.0
*/
@Configuration
public class RedissonConfig {
@Value("${spring.redis.host}")
private String redisServerIp;
@Value("${spring.redis.port}")
private String redisServerPort;
@Value("${spring.redis.password}")
private String redisPassword;
@Bean
Config getConfig(){
Config config = new Config();
String address = "redis://"+redisServerIp+":"+redisServerPort;
//单节点模式,更多模式见官方文档 https://github.com/redisson/redisson/wiki
config.useSingleServer().setAddress(address).setPassword(redisPassword);
return config;
}
@Bean
RedissonClient getRedisClient(Config config){
RedissonClient redissonClient = Redisson.create(config);
return redissonClient;
}
}
4.使用redisson加锁 防止连续点击
@Autowired
RedissonClient redissonClient;
//防止重复点击
RLock fairLock = redissonClient.getLock(PuhuiyunRedisKeyConstants.PUHUIYUN_SAVE_USERADDRESS_LOCK + userId);
try {
if (!fairLock.tryLock(0, 60, TimeUnit.SECONDS)) {
return ApiRes.getErrorInstance(ResultEnum.REQUEST_LIMIT_ERROR);
}
return puhuiyunUserAddressService.savePuhuiyunUserAddress(id,userId,userName,userMoblie,userAddress);
}catch (Exception e){
log.error("保存/编辑 收货地址错误",e);
} finally {
if (fairLock.isHeldByCurrentThread() && fairLock.isLocked()) {
//判断是当前线程加的锁就释放 并且 锁未释放
fairLock.unlock();
}
}
5.封装一个Redis分布式锁工具类
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @author
* @title: RedisLok
* @description: Redis分布式锁工具类
* @date
*/
@Component
@Slf4j
public class RedisLok {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 枷锁 自定义秒
*
* @param key
* @param value
* @return
*/
public boolean tryLock(String key, String value, Long timeout) {
return tryLockPackage(key, value, timeout);
}
/**
* 枷锁 默认60秒
*
* @param key
* @param value
* @return
*/
public boolean tryLock(String key, String value) {
return tryLockPackage(key, value, 60L);
}
private boolean tryLockPackage(String key, String value, Long timeout) {
DefaultRedisScript<Long> defaultRedisScript = new DefaultRedisScript<>();
defaultRedisScript.setResultType(Long.class);
defaultRedisScript.setScriptText("if redis.call('get',KEYS[1]) then return 1 else redis.call('set',KEYS[1],ARGV[1],'ex',ARGV[2],'NX') return 0 end");
List<String> keys = new ArrayList<>();
keys.add(key);
Long result = redisTemplate.execute(defaultRedisScript, keys, value, String.valueOf(timeout));
log.info("key:{} value:{} 失效时间:{} 脚本返回结果为:{}", key, value, timeout, result.intValue());
return result.equals(0L);
}
/**
* 封装执行 Lua脚本方法
* @param luaScript 要执行的 lua 脚本
* @param resultType 返回类型
* @param keys key集合
* @param argv arg集合
* @param <T> 返回泛型
* @return 泛型返回
*/
public <T> T executeRedisLuaScript(String luaScript,Class<T> resultType,List<String> keys, List<?> argv){
DefaultRedisScript<T> defaultRedisScript = new DefaultRedisScript<>();
defaultRedisScript.setResultType(resultType);
defaultRedisScript.setScriptText(luaScript);
T execute = redisTemplate.execute(defaultRedisScript, keys, argv.toArray());
log.info("执行Lua脚本,KEYS:[ {} ],ARGV:[ {} ]返回结果:{}", JSONObject.toJSONString(keys),JSONObject.toJSONString(argv),execute);
return execute;
}
/**
* 解锁
*
* @param key
*/
public void unLock(String key) {
log.info("删除的key为:{}", key);
redisTemplate.delete(key);
}
//------------------------------------redisson 相关操作-----------------------
/**
* redisson 解锁
*
* @param lock
*/
public void redissonUnLock(RLock lock) {
if (lock.isHeldByCurrentThread() && lock.isLocked()) {
lock.unlock();
}
}
public boolean tryRedissonLock(RLock lock) {
return tryRedissonLock(lock, 0, 60, TimeUnit.SECONDS);
}
public boolean tryRedissonLock(RLock lock, long waitTime, long leaseTime, TimeUnit unit) {
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
log.error("获取锁:{}失败", lock.getName(), e);
return false;
}
}
public boolean tryWaitTimeRedissonLock(RLock lock, long waitTime, TimeUnit unit) {
return tryRedissonLock(lock, waitTime, 60, unit);
}
public boolean tryLeaseTimeRedissonLock(RLock lock, long leaseTime, TimeUnit unit) {
return tryRedissonLock(lock, 0, leaseTime, unit);
}
}