From 2d8b66e256dc49dd1e62b6f94ff7a27cd74304f0 Mon Sep 17 00:00:00 2001 From: zlt2000 Date: Tue, 5 May 2020 21:38:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E5=B8=83=E5=BC=8F=E9=94=81=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=96=B9=E5=BC=8F=E6=94=B9=E4=B8=BARedisson?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E4=BC=98=E5=8C=96=E6=8A=BD=E8=B1=A1=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/SysRoleController.java | 2 +- .../user/controller/SysUserController.java | 10 +- .../central/user/service/ISysRoleService.java | 9 +- .../central/user/service/ISysUserService.java | 7 +- .../user/service/impl/SysRoleServiceImpl.java | 6 +- .../user/service/impl/SysUserServiceImpl.java | 4 +- .../user/service/SysUserServiceTest.java | 17 +++ .../common/lock/AbstractDistributedLock.java | 35 ------ .../central/common/lock/DistributedLock.java | 103 +++++------------- .../central/common/service/ISuperService.java | 43 ++++---- .../common/service/impl/SuperServiceImpl.java | 74 +++---------- .../redis/lock/RedisDistributedLock.java | 28 ++++- .../redis/lock/RedissonDistributedLock.java | 88 +++++++++++++++ .../redis/util/RedisObjectSerializer.java | 40 ------- .../main/resources/META-INF/spring.factories | 2 +- .../oauth/controller/ClientController.java | 5 +- .../central/oauth/service/IClientService.java | 5 +- .../oauth/service/impl/ClientServiceImpl.java | 7 +- 18 files changed, 229 insertions(+), 256 deletions(-) delete mode 100644 zlt-commons/zlt-common-core/src/main/java/com/central/common/lock/AbstractDistributedLock.java create mode 100644 zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedissonDistributedLock.java delete mode 100644 zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/util/RedisObjectSerializer.java diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysRoleController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysRoleController.java index 9cccefc..80de7d2 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysRoleController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysRoleController.java @@ -61,7 +61,7 @@ public class SysRoleController { * @return */ @PostMapping("/roles/saveOrUpdate") - public Result saveOrUpdate(@RequestBody SysRole sysRole) { + public Result saveOrUpdate(@RequestBody SysRole sysRole) throws Exception { return sysRoleService.saveOrUpdateRole(sysRole); } diff --git a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java index 0db93f8..0b0b95c 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java +++ b/zlt-business/user-center/src/main/java/com/central/user/controller/SysUserController.java @@ -19,6 +19,8 @@ import com.central.search.model.LogicDelDto; import com.central.search.model.SearchDto; import com.central.user.model.SysUserExcel; import org.apache.commons.collections4.MapUtils; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; @@ -57,6 +59,9 @@ public class SysUserController { @Autowired private IQueryService queryService; + @Autowired + private RedissonClient redisson; + /** * 当前登录用户 LoginAppUser * @@ -65,6 +70,9 @@ public class SysUserController { @ApiOperation(value = "根据access_token当前登录用户") @GetMapping("/users/current") public Result getLoginAppUser(@LoginUser(isFull = true) SysUser user) { + RLock lock = redisson.getLock("test"); + lock.lock(); + return Result.succeed(appUserService.getLoginAppUser(user)); } @@ -236,7 +244,7 @@ public class SysUserController { @CacheEvict(value = "user", key = "#sysUser.username") @PostMapping("/users/saveOrUpdate") @AuditLog(operation = "'新增或更新用户:' + #sysUser.username") - public Result saveOrUpdate(@RequestBody SysUser sysUser) { + public Result saveOrUpdate(@RequestBody SysUser sysUser) throws Exception { return appUserService.saveOrUpdateUser(sysUser); } diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/ISysRoleService.java b/zlt-business/user-center/src/main/java/com/central/user/service/ISysRoleService.java index 716a48a..2d29f85 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/ISysRoleService.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/ISysRoleService.java @@ -9,10 +9,13 @@ import com.central.common.model.SysRole; import com.central.common.service.ISuperService; /** -* @author zlt + * @author zlt + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ public interface ISysRoleService extends ISuperService { - void saveRole(SysRole sysRole); + void saveRole(SysRole sysRole) throws Exception; void deleteRole(Long id); @@ -28,7 +31,7 @@ public interface ISysRoleService extends ISuperService { * @param sysRole * @return Result */ - Result saveOrUpdateRole(SysRole sysRole); + Result saveOrUpdateRole(SysRole sysRole) throws Exception; /** * 查询所有角色 diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/ISysUserService.java b/zlt-business/user-center/src/main/java/com/central/user/service/ISysUserService.java index 26adcb5..aaf899f 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/ISysUserService.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/ISysUserService.java @@ -13,7 +13,10 @@ import com.central.common.model.SysRole; import com.central.common.model.SysUser; /** -* @author zlt + * @author zlt + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ public interface ISysUserService extends ISuperService { /** @@ -98,7 +101,7 @@ public interface ISysUserService extends ISuperService { */ List findAllUsers(Map params); - Result saveOrUpdateUser(SysUser sysUser); + Result saveOrUpdateUser(SysUser sysUser) throws Exception; /** * 删除用户 diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysRoleServiceImpl.java b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysRoleServiceImpl.java index 4d28373..8550e08 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysRoleServiceImpl.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysRoleServiceImpl.java @@ -29,7 +29,7 @@ import javax.annotation.Resource; @Slf4j @Service public class SysRoleServiceImpl extends SuperServiceImpl implements ISysRoleService { - private final static String LOCK_KEY_ROLECODE = CommonConstant.LOCK_KEY_PREFIX+"rolecode:"; + private final static String LOCK_KEY_ROLECODE = "rolecode:"; @Resource private SysUserRoleMapper userRoleMapper; @@ -42,7 +42,7 @@ public class SysRoleServiceImpl extends SuperServiceImpl @Transactional(rollbackFor = Exception.class) @Override - public void saveRole(SysRole sysRole) { + public void saveRole(SysRole sysRole) throws Exception { String roleCode = sysRole.getCode(); super.saveIdempotency(sysRole, lock , LOCK_KEY_ROLECODE+roleCode, new QueryWrapper().eq("code", roleCode), "角色code已存在"); @@ -67,7 +67,7 @@ public class SysRoleServiceImpl extends SuperServiceImpl @Override @Transactional - public Result saveOrUpdateRole(SysRole sysRole) { + public Result saveOrUpdateRole(SysRole sysRole) throws Exception { if (sysRole.getId() == null) { this.saveRole(sysRole); } else { diff --git a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java index ce66739..a52d173 100644 --- a/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java +++ b/zlt-business/user-center/src/main/java/com/central/user/service/impl/SysUserServiceImpl.java @@ -37,7 +37,7 @@ import javax.annotation.Resource; @Slf4j @Service public class SysUserServiceImpl extends SuperServiceImpl implements ISysUserService { - private final static String LOCK_KEY_USERNAME = CommonConstant.LOCK_KEY_PREFIX+"username:"; + private final static String LOCK_KEY_USERNAME = "username:"; @Autowired private PasswordEncoder passwordEncoder; @@ -219,7 +219,7 @@ public class SysUserServiceImpl extends SuperServiceImpl @Transactional(rollbackFor = Exception.class) @Override - public Result saveOrUpdateUser(SysUser sysUser) { + public Result saveOrUpdateUser(SysUser sysUser) throws Exception { if (sysUser.getId() == null) { if (StringUtils.isBlank(sysUser.getType())) { sysUser.setType(UserType.BACKEND.name()); diff --git a/zlt-business/user-center/src/test/java/com/central/user/service/SysUserServiceTest.java b/zlt-business/user-center/src/test/java/com/central/user/service/SysUserServiceTest.java index 372d793..5b10a46 100644 --- a/zlt-business/user-center/src/test/java/com/central/user/service/SysUserServiceTest.java +++ b/zlt-business/user-center/src/test/java/com/central/user/service/SysUserServiceTest.java @@ -1,5 +1,6 @@ package com.central.user.service; +import com.central.common.lock.DistributedLock; import com.central.common.model.LoginAppUser; import static org.assertj.core.api.Assertions.*; @@ -7,12 +8,14 @@ import com.central.common.model.PageResult; import com.central.common.model.SysUser; import org.junit.Test; import org.junit.runner.RunWith; +import org.redisson.api.RLock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; /** * SysUserServiceTest单元测试用例 @@ -25,6 +28,20 @@ public class SysUserServiceTest { @Autowired private ISysUserService sysUserService; + @Autowired + private DistributedLock locker; + + @Test + public void testLock() throws Exception { + Object lock = null; + try { + lock = locker.tryLock("test", 1000, TimeUnit.MILLISECONDS, true); + Thread.sleep(5000); + } finally { + locker.unlock(lock); + } + } + @Test public void testFindByUsername() { LoginAppUser loginAppUser = sysUserService.findByUsername("admin"); diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/lock/AbstractDistributedLock.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/lock/AbstractDistributedLock.java deleted file mode 100644 index f2863f9..0000000 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/lock/AbstractDistributedLock.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.central.common.lock; - -/** - * 分布式锁抽象类 - * - * @author zlt - * @date 2018/5/29 14:14 - */ -public abstract class AbstractDistributedLock implements DistributedLock{ - - @Override - public boolean lock(String key) { - return lock(key, TIMEOUT_MILLIS, RETRY_TIMES, SLEEP_MILLIS); - } - - @Override - public boolean lock(String key, int retryTimes) { - return lock(key, TIMEOUT_MILLIS, retryTimes, SLEEP_MILLIS); - } - - @Override - public boolean lock(String key, int retryTimes, long sleepMillis) { - return lock(key, TIMEOUT_MILLIS, retryTimes, sleepMillis); - } - - @Override - public boolean lock(String key, long expire) { - return lock(key, expire, RETRY_TIMES, SLEEP_MILLIS); - } - - @Override - public boolean lock(String key, long expire, int retryTimes) { - return lock(key, expire, retryTimes, SLEEP_MILLIS); - } -} diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/lock/DistributedLock.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/lock/DistributedLock.java index b44043a..e3f0ae8 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/lock/DistributedLock.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/lock/DistributedLock.java @@ -1,93 +1,48 @@ package com.central.common.lock; +import java.util.concurrent.TimeUnit; + /** * 分布式锁顶级接口 - * 例如: - * RETRY_TIMES=100,SLEEP_MILLIS=100 - * RETRY_TIMES * SLEEP_MILLIS = 10000 意味着如果一直获取不了锁,最长会等待10秒后抛超时异常 * * @author zlt * @date 2018/5/29 14:12 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ public interface DistributedLock { - - /** - * 默认超时时间 - */ - long TIMEOUT_MILLIS = 5000; - - /** - * 重试次数 - */ - int RETRY_TIMES = 100; - - /** - * 每次重试后等待的时间 - */ - long SLEEP_MILLIS = 100; - - /** - * 获取锁 - * - * @param key key - * @return 成功/失败 - */ - boolean lock(String key); - - /** - * 获取锁 - * - * @param key key - * @param retryTimes 重试次数 - * @return 成功/失败 - */ - boolean lock(String key, int retryTimes); - - /** - * 获取锁 - * - * @param key key - * @param retryTimes 重试次数 - * @param sleepMillis 获取锁失败的重试间隔 - * @return 成功/失败 - */ - boolean lock(String key, int retryTimes, long sleepMillis); - - /** - * 获取锁 - * - * @param key key - * @param expire 获取锁超时时间 - * @return 成功/失败 - */ - boolean lock(String key, long expire); - /** - * 获取锁 - * - * @param key key - * @param expire 获取锁超时时间 - * @param retryTimes 重试次数 - * @return 成功/失败 + * 获取锁,如果获取不成功则一直等待直到lock被获取 + * @param key 锁的key + * @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁; + * 如果leaseTime为-1,则保持锁定直到显式解锁 + * @param unit {@code leaseTime} 参数的时间单位 + * @param isFair 是否公平锁 + * @return 锁对象 */ - boolean lock(String key, long expire, int retryTimes); + Object lock(String key, long leaseTime, TimeUnit unit, boolean isFair) throws Exception; + Object lock(String key, long leaseTime, TimeUnit unit) throws Exception; + Object lock(String key, boolean isFair) throws Exception; + Object lock(String key) throws Exception; /** - * 获取锁 - * - * @param key key - * @param expire 获取锁超时时间 - * @param retryTimes 重试次数 - * @param sleepMillis 获取锁失败的重试间隔 - * @return 成功/失败 + * 尝试获取锁,如果锁不可用则等待最多waitTime时间后放弃 + * @param key 锁的key + * @param waitTime 获取锁的最大尝试时间(单位毫秒) + * @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁; + * 如果leaseTime为-1,则保持锁定直到显式解锁 + * @param unit {@code waitTime} 和 {@code leaseTime} 参数的时间单位 + * @return 锁对象,如果获取锁失败则为null */ - boolean lock(String key, long expire, int retryTimes, long sleepMillis); + Object tryLock(String key, long waitTime, long leaseTime, TimeUnit unit, boolean isFair) throws Exception; + Object tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws Exception; + Object tryLock(String key, long waitTime, TimeUnit unit, boolean isFair) throws Exception; + Object tryLock(String key, long waitTime, TimeUnit unit) throws Exception; /** * 释放锁 - * - * @param key key值 - * @return 释放结果 + * @param lock 锁对象 */ - boolean releaseLock(String key); + void unlock(Object lock) throws Exception; } diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/service/ISuperService.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/service/ISuperService.java index 95e258b..97af475 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/service/ISuperService.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/service/ISuperService.java @@ -9,51 +9,46 @@ import com.central.common.lock.DistributedLock; * * @author zlt * @date 2019/1/10 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ public interface ISuperService extends IService { /** * 幂等性新增记录 + * 例子如下: + * String username = sysUser.getUsername(); + * boolean result = super.saveIdempotency(sysUser, lock + * , LOCK_KEY_USERNAME+username + * , new QueryWrapper().eq("username", username)); * * @param entity 实体对象 - * @param lock 锁实例 + * @param locker 锁实例 * @param lockKey 锁的key * @param countWrapper 判断是否存在的条件 * @param msg 对象已存在提示信息 * @return */ - boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper, String msg); + boolean saveIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper countWrapper, String msg) throws Exception; - /** - * 幂等性新增记录 - * - * @param entity 实体对象 - * @param lock 锁实例 - * @param lockKey 锁的key - * @param countWrapper 判断是否存在的条件 - * @return - */ - boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper); + boolean saveIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper countWrapper) throws Exception; /** * 幂等性新增或更新记录 + * 例子如下: + * String username = sysUser.getUsername(); + * boolean result = super.saveOrUpdateIdempotency(sysUser, lock + * , LOCK_KEY_USERNAME+username + * , new QueryWrapper().eq("username", username)); * * @param entity 实体对象 - * @param lock 锁实例 + * @param locker 锁实例 * @param lockKey 锁的key * @param countWrapper 判断是否存在的条件 * @param msg 对象已存在提示信息 * @return */ - boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper, String msg); + boolean saveOrUpdateIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper countWrapper, String msg) throws Exception; - /** - * 幂等性新增或更新记录 - * - * @param entity 实体对象 - * @param lock 锁实例 - * @param lockKey 锁的key - * @param countWrapper 判断是否存在的条件 - * @return - */ - boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper); + boolean saveOrUpdateIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper countWrapper) throws Exception; } diff --git a/zlt-commons/zlt-common-core/src/main/java/com/central/common/service/impl/SuperServiceImpl.java b/zlt-commons/zlt-common-core/src/main/java/com/central/common/service/impl/SuperServiceImpl.java index 0eab2a5..250c167 100644 --- a/zlt-commons/zlt-common-core/src/main/java/com/central/common/service/impl/SuperServiceImpl.java +++ b/zlt-commons/zlt-common-core/src/main/java/com/central/common/service/impl/SuperServiceImpl.java @@ -16,41 +16,31 @@ import com.central.common.service.ISuperService; import java.io.Serializable; import java.util.Objects; +import java.util.concurrent.TimeUnit; /** * service实现父类 * * @author zlt * @date 2019/1/10 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ public class SuperServiceImpl, T> extends ServiceImpl implements ISuperService { - /** - * 幂等性新增记录 - * 例子如下: - * String username = sysUser.getUsername(); - * boolean result = super.saveIdempotency(sysUser, lock - * , LOCK_KEY_USERNAME+username - * , new QueryWrapper().eq("username", username)); - * - * @param entity 实体对象 - * @param lock 锁实例 - * @param lockKey 锁的key - * @param countWrapper 判断是否存在的条件 - * @param msg 对象已存在提示信息 - * @return - */ @Override - public boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper, String msg) { - if (lock == null) { + public boolean saveIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper countWrapper, String msg) throws Exception { + if (locker == null) { throw new LockException("DistributedLock is null"); } if (StrUtil.isEmpty(lockKey)) { throw new LockException("lockKey is null"); } + Object lock; try { //加锁 - boolean isLock = lock.lock(lockKey); - if (isLock) { + lock = locker.tryLock(lockKey, 10, 60, TimeUnit.SECONDS); + if (lock != null) { //判断记录是否已存在 int count = super.count(countWrapper); if (count == 0) { @@ -65,41 +55,17 @@ public class SuperServiceImpl, T> extends ServiceImpl countWrapper) { + public boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper) throws Exception { return saveIdempotency(entity, lock, lockKey, countWrapper, null); } - /** - * 幂等性新增或更新记录 - * 例子如下: - * String username = sysUser.getUsername(); - * boolean result = super.saveOrUpdateIdempotency(sysUser, lock - * , LOCK_KEY_USERNAME+username - * , new QueryWrapper().eq("username", username)); - * - * @param entity 实体对象 - * @param lock 锁实例 - * @param lockKey 锁的key - * @param countWrapper 判断是否存在的条件 - * @param msg 对象已存在提示信息 - * @return - */ @Override - public boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper, String msg) { + public boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper, String msg) throws Exception { if (null != entity) { Class cls = entity.getClass(); TableInfo tableInfo = TableInfoHelper.getTableInfo(cls); @@ -120,22 +86,8 @@ public class SuperServiceImpl, T> extends ServiceImpl().eq("username", username)); - * - * @param entity 实体对象 - * @param lock 锁实例 - * @param lockKey 锁的key - * @param countWrapper 判断是否存在的条件 - * @return - */ @Override - public boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper) { + public boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper countWrapper) throws Exception { return this.saveOrUpdateIdempotency(entity, lock, lockKey, countWrapper, null); } } diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedisDistributedLock.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedisDistributedLock.java index a4abd18..9b305e4 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedisDistributedLock.java +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedisDistributedLock.java @@ -1,14 +1,13 @@ package com.central.common.redis.lock; -import com.central.common.lock.AbstractDistributedLock; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.data.redis.connection.RedisStringCommands; import org.springframework.data.redis.connection.ReturnType; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.types.Expiration; -import org.springframework.stereotype.Component; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -18,9 +17,16 @@ import java.util.concurrent.TimeUnit; * * @author zlt * @date 2018/5/29 14:16 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + * + * @deprecated 建议使用Redisson的实现方式 {@link RedissonDistributedLock} */ @Slf4j -public class RedisDistributedLock extends AbstractDistributedLock { +@ConditionalOnClass(RedisTemplate.class) +@Deprecated +public class RedisDistributedLock { @Autowired private RedisTemplate redisTemplate; @@ -45,7 +51,15 @@ public class RedisDistributedLock extends AbstractDistributedLock { this.redisTemplate = redisTemplate; } - @Override + /** + * 获取锁 + * + * @param key 锁的key + * @param expire 获取锁超时时间 + * @param retryTimes 重试次数 + * @param sleepMillis 获取锁失败的重试间隔 + * @return 成功/失败 + */ public boolean lock(String key, long expire, int retryTimes, long sleepMillis) { boolean result = setRedis(key, expire); // 如果获取锁失败,按照传入的重试次数进行重试 @@ -79,7 +93,11 @@ public class RedisDistributedLock extends AbstractDistributedLock { return false; } - @Override + /** + * 释放锁 + * @param key 锁的key + * @return 成功/失败 + */ public boolean releaseLock(String key) { // 释放锁的时候,有可能因为持锁之后方法执行时间大于锁的有效期,此时有可能已经被另外一个线程持有锁,所以不能直接删除 try { diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedissonDistributedLock.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedissonDistributedLock.java new file mode 100644 index 0000000..94b1d98 --- /dev/null +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/lock/RedissonDistributedLock.java @@ -0,0 +1,88 @@ +package com.central.common.redis.lock; + +import com.central.common.constant.CommonConstant; +import com.central.common.exception.LockException; +import com.central.common.lock.DistributedLock; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; + +import java.util.concurrent.TimeUnit; + +/** + * redisson分布式锁实现,基本锁功能的抽象实现 + * 本接口能满足绝大部分的需求,高级的锁功能,请自行扩展或直接使用原生api + * + * @author zlt + * @date 2020/5/5 + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 + */ +@ConditionalOnClass(RedissonClient.class) +public class RedissonDistributedLock implements DistributedLock { + @Autowired + private RedissonClient redisson; + + private RLock getLock(String key, boolean isFair) { + if (isFair) { + return redisson.getFairLock(CommonConstant.LOCK_KEY_PREFIX + key); + } + return redisson.getLock(CommonConstant.LOCK_KEY_PREFIX + key); + } + + @Override + public RLock lock(String key, long leaseTime, TimeUnit unit, boolean isFair) { + RLock lock = getLock(key, isFair); + lock.lock(leaseTime, unit); + return lock; + } + @Override + public RLock lock(String key, long leaseTime, TimeUnit unit) { + return lock(key, leaseTime, unit, false); + } + @Override + public RLock lock(String key, boolean isFair) { + return lock(key, -1, null, isFair); + } + @Override + public RLock lock(String key) { + return lock(key, -1, null, false); + } + + @Override + public RLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit, boolean isFair) throws InterruptedException { + RLock lock = getLock(key, isFair); + if (lock.tryLock(waitTime, leaseTime, unit)) { + return lock; + } + return null; + } + @Override + public RLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException { + return tryLock(key, waitTime, leaseTime, unit, false); + } + @Override + public RLock tryLock(String key, long waitTime, TimeUnit unit, boolean isFair) throws InterruptedException { + return tryLock(key, waitTime, -1, unit, isFair); + } + @Override + public RLock tryLock(String key, long waitTime, TimeUnit unit) throws InterruptedException { + return tryLock(key, waitTime, -1, unit, false); + } + + @Override + public void unlock(Object lock) { + if (lock != null) { + if (lock instanceof RLock) { + RLock rLock = (RLock)lock; + if (rLock.isLocked()) { + rLock.unlock(); + } + } else { + throw new LockException("requires RLock type"); + } + } + } +} diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/util/RedisObjectSerializer.java b/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/util/RedisObjectSerializer.java deleted file mode 100644 index 3fe888c..0000000 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/java/com/central/common/redis/util/RedisObjectSerializer.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.central.common.redis.util; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.serializer.support.DeserializingConverter; -import org.springframework.core.serializer.support.SerializingConverter; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.data.redis.serializer.SerializationException; - -/** - * 此时定义的序列化操作表示可以序列化所有类的对象,当然,这个对象所在的类一定要实现序列化接口 - * - * @author zlt - */ -public class RedisObjectSerializer implements RedisSerializer { - // 做一个空数组,不是null - private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - // 为了方便进行对象与字节数组的转换,所以应该首先准备出两个转换器 - private Converter serializingConverter = new SerializingConverter(); - private Converter deserializingConverter = new DeserializingConverter(); - - @Override - public byte[] serialize(Object obj) { - // 这个时候没有要序列化的对象出现,所以返回的字节数组应该就是一个空数组 - if (obj == null) { - return EMPTY_BYTE_ARRAY; - } - // 将对象变为字节数组 - return this.serializingConverter.convert(obj); - } - - @Override - public Object deserialize(byte[] data) { - // 此时没有对象的内容信息 - if (data == null || data.length == 0) { - return null; - } - return this.deserializingConverter.convert(data); - } - -} \ No newline at end of file diff --git a/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories b/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories index 924601e..c0dc55e 100644 --- a/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/zlt-commons/zlt-redis-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -1,4 +1,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.central.common.redis.RedisAutoConfigure,\ -com.central.common.redis.lock.RedisDistributedLock,\ +com.central.common.redis.lock.RedissonDistributedLock,\ com.central.common.redis.template.RedisRepository \ No newline at end of file diff --git a/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java b/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java index 0f22e64..4dd8097 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java +++ b/zlt-uaa/src/main/java/com/central/oauth/controller/ClientController.java @@ -18,6 +18,9 @@ import java.util.Map; * 应用相关接口 * * @author zlt + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ @Api(tags = "应用") @RestController @@ -53,7 +56,7 @@ public class ClientController { @PostMapping("/saveOrUpdate") @ApiOperation(value = "保存或者修改应用") - public Result saveOrUpdate(@RequestBody ClientDto clientDto) { + public Result saveOrUpdate(@RequestBody ClientDto clientDto) throws Exception { return clientService.saveClient(clientDto); } } diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java b/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java index 02f653b..d8d4f27 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/IClientService.java @@ -9,9 +9,12 @@ import java.util.Map; /** * @author zlt + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ public interface IClientService extends ISuperService { - Result saveClient(Client clientDto); + Result saveClient(Client clientDto) throws Exception; /** * 查询应用列表 diff --git a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java index 16968c3..8e04cfd 100644 --- a/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java +++ b/zlt-uaa/src/main/java/com/central/oauth/service/impl/ClientServiceImpl.java @@ -23,11 +23,14 @@ import java.util.Map; /** * @author zlt + *

+ * Blog: https://zlt2000.gitee.io + * Github: https://github.com/zlt2000 */ @Slf4j @Service public class ClientServiceImpl extends SuperServiceImpl implements IClientService { - private final static String LOCK_KEY_CLIENTID = CommonConstant.LOCK_KEY_PREFIX+"clientId:"; + private final static String LOCK_KEY_CLIENTID = "clientId:"; @Autowired private RedisRepository redisRepository; @@ -39,7 +42,7 @@ public class ClientServiceImpl extends SuperServiceImpl im private DistributedLock lock; @Override - public Result saveClient(Client client) { + public Result saveClient(Client client) throws Exception { client.setClientSecret(passwordEncoder.encode(client.getClientSecretStr())); String clientId = client.getClientId(); super.saveOrUpdateIdempotency(client, lock -- GitLab