1,在application.properties中配置redis主机:
spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password=XXX2,添加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); }