提交 2d8b66e2 编写于 作者: zlt2000's avatar zlt2000

分布式锁的实现方式改为Redisson,并优化抽象接口

上级 4be31c40
...@@ -61,7 +61,7 @@ public class SysRoleController { ...@@ -61,7 +61,7 @@ public class SysRoleController {
* @return * @return
*/ */
@PostMapping("/roles/saveOrUpdate") @PostMapping("/roles/saveOrUpdate")
public Result saveOrUpdate(@RequestBody SysRole sysRole) { public Result saveOrUpdate(@RequestBody SysRole sysRole) throws Exception {
return sysRoleService.saveOrUpdateRole(sysRole); return sysRoleService.saveOrUpdateRole(sysRole);
} }
......
...@@ -19,6 +19,8 @@ import com.central.search.model.LogicDelDto; ...@@ -19,6 +19,8 @@ import com.central.search.model.LogicDelDto;
import com.central.search.model.SearchDto; import com.central.search.model.SearchDto;
import com.central.user.model.SysUserExcel; import com.central.user.model.SysUserExcel;
import org.apache.commons.collections4.MapUtils; 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.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.CachePut;
...@@ -57,6 +59,9 @@ public class SysUserController { ...@@ -57,6 +59,9 @@ public class SysUserController {
@Autowired @Autowired
private IQueryService queryService; private IQueryService queryService;
@Autowired
private RedissonClient redisson;
/** /**
* 当前登录用户 LoginAppUser * 当前登录用户 LoginAppUser
* *
...@@ -65,6 +70,9 @@ public class SysUserController { ...@@ -65,6 +70,9 @@ public class SysUserController {
@ApiOperation(value = "根据access_token当前登录用户") @ApiOperation(value = "根据access_token当前登录用户")
@GetMapping("/users/current") @GetMapping("/users/current")
public Result<LoginAppUser> getLoginAppUser(@LoginUser(isFull = true) SysUser user) { public Result<LoginAppUser> getLoginAppUser(@LoginUser(isFull = true) SysUser user) {
RLock lock = redisson.getLock("test");
lock.lock();
return Result.succeed(appUserService.getLoginAppUser(user)); return Result.succeed(appUserService.getLoginAppUser(user));
} }
...@@ -236,7 +244,7 @@ public class SysUserController { ...@@ -236,7 +244,7 @@ public class SysUserController {
@CacheEvict(value = "user", key = "#sysUser.username") @CacheEvict(value = "user", key = "#sysUser.username")
@PostMapping("/users/saveOrUpdate") @PostMapping("/users/saveOrUpdate")
@AuditLog(operation = "'新增或更新用户:' + #sysUser.username") @AuditLog(operation = "'新增或更新用户:' + #sysUser.username")
public Result saveOrUpdate(@RequestBody SysUser sysUser) { public Result saveOrUpdate(@RequestBody SysUser sysUser) throws Exception {
return appUserService.saveOrUpdateUser(sysUser); return appUserService.saveOrUpdateUser(sysUser);
} }
......
...@@ -9,10 +9,13 @@ import com.central.common.model.SysRole; ...@@ -9,10 +9,13 @@ import com.central.common.model.SysRole;
import com.central.common.service.ISuperService; import com.central.common.service.ISuperService;
/** /**
* @author zlt * @author zlt
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/ */
public interface ISysRoleService extends ISuperService<SysRole> { public interface ISysRoleService extends ISuperService<SysRole> {
void saveRole(SysRole sysRole); void saveRole(SysRole sysRole) throws Exception;
void deleteRole(Long id); void deleteRole(Long id);
...@@ -28,7 +31,7 @@ public interface ISysRoleService extends ISuperService<SysRole> { ...@@ -28,7 +31,7 @@ public interface ISysRoleService extends ISuperService<SysRole> {
* @param sysRole * @param sysRole
* @return Result * @return Result
*/ */
Result saveOrUpdateRole(SysRole sysRole); Result saveOrUpdateRole(SysRole sysRole) throws Exception;
/** /**
* 查询所有角色 * 查询所有角色
......
...@@ -13,7 +13,10 @@ import com.central.common.model.SysRole; ...@@ -13,7 +13,10 @@ import com.central.common.model.SysRole;
import com.central.common.model.SysUser; import com.central.common.model.SysUser;
/** /**
* @author zlt * @author zlt
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/ */
public interface ISysUserService extends ISuperService<SysUser> { public interface ISysUserService extends ISuperService<SysUser> {
/** /**
...@@ -98,7 +101,7 @@ public interface ISysUserService extends ISuperService<SysUser> { ...@@ -98,7 +101,7 @@ public interface ISysUserService extends ISuperService<SysUser> {
*/ */
List<SysUserExcel> findAllUsers(Map<String, Object> params); List<SysUserExcel> findAllUsers(Map<String, Object> params);
Result saveOrUpdateUser(SysUser sysUser); Result saveOrUpdateUser(SysUser sysUser) throws Exception;
/** /**
* 删除用户 * 删除用户
......
...@@ -29,7 +29,7 @@ import javax.annotation.Resource; ...@@ -29,7 +29,7 @@ import javax.annotation.Resource;
@Slf4j @Slf4j
@Service @Service
public class SysRoleServiceImpl extends SuperServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService { public class SysRoleServiceImpl extends SuperServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {
private final static String LOCK_KEY_ROLECODE = CommonConstant.LOCK_KEY_PREFIX+"rolecode:"; private final static String LOCK_KEY_ROLECODE = "rolecode:";
@Resource @Resource
private SysUserRoleMapper userRoleMapper; private SysUserRoleMapper userRoleMapper;
...@@ -42,7 +42,7 @@ public class SysRoleServiceImpl extends SuperServiceImpl<SysRoleMapper, SysRole> ...@@ -42,7 +42,7 @@ public class SysRoleServiceImpl extends SuperServiceImpl<SysRoleMapper, SysRole>
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public void saveRole(SysRole sysRole) { public void saveRole(SysRole sysRole) throws Exception {
String roleCode = sysRole.getCode(); String roleCode = sysRole.getCode();
super.saveIdempotency(sysRole, lock super.saveIdempotency(sysRole, lock
, LOCK_KEY_ROLECODE+roleCode, new QueryWrapper<SysRole>().eq("code", roleCode), "角色code已存在"); , LOCK_KEY_ROLECODE+roleCode, new QueryWrapper<SysRole>().eq("code", roleCode), "角色code已存在");
...@@ -67,7 +67,7 @@ public class SysRoleServiceImpl extends SuperServiceImpl<SysRoleMapper, SysRole> ...@@ -67,7 +67,7 @@ public class SysRoleServiceImpl extends SuperServiceImpl<SysRoleMapper, SysRole>
@Override @Override
@Transactional @Transactional
public Result saveOrUpdateRole(SysRole sysRole) { public Result saveOrUpdateRole(SysRole sysRole) throws Exception {
if (sysRole.getId() == null) { if (sysRole.getId() == null) {
this.saveRole(sysRole); this.saveRole(sysRole);
} else { } else {
......
...@@ -37,7 +37,7 @@ import javax.annotation.Resource; ...@@ -37,7 +37,7 @@ import javax.annotation.Resource;
@Slf4j @Slf4j
@Service @Service
public class SysUserServiceImpl extends SuperServiceImpl<SysUserMapper, SysUser> implements ISysUserService { public class SysUserServiceImpl extends SuperServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
private final static String LOCK_KEY_USERNAME = CommonConstant.LOCK_KEY_PREFIX+"username:"; private final static String LOCK_KEY_USERNAME = "username:";
@Autowired @Autowired
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
...@@ -219,7 +219,7 @@ public class SysUserServiceImpl extends SuperServiceImpl<SysUserMapper, SysUser> ...@@ -219,7 +219,7 @@ public class SysUserServiceImpl extends SuperServiceImpl<SysUserMapper, SysUser>
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public Result saveOrUpdateUser(SysUser sysUser) { public Result saveOrUpdateUser(SysUser sysUser) throws Exception {
if (sysUser.getId() == null) { if (sysUser.getId() == null) {
if (StringUtils.isBlank(sysUser.getType())) { if (StringUtils.isBlank(sysUser.getType())) {
sysUser.setType(UserType.BACKEND.name()); sysUser.setType(UserType.BACKEND.name());
......
package com.central.user.service; package com.central.user.service;
import com.central.common.lock.DistributedLock;
import com.central.common.model.LoginAppUser; import com.central.common.model.LoginAppUser;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
...@@ -7,12 +8,14 @@ import com.central.common.model.PageResult; ...@@ -7,12 +8,14 @@ import com.central.common.model.PageResult;
import com.central.common.model.SysUser; import com.central.common.model.SysUser;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
/** /**
* SysUserServiceTest单元测试用例 * SysUserServiceTest单元测试用例
...@@ -25,6 +28,20 @@ public class SysUserServiceTest { ...@@ -25,6 +28,20 @@ public class SysUserServiceTest {
@Autowired @Autowired
private ISysUserService sysUserService; 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 @Test
public void testFindByUsername() { public void testFindByUsername() {
LoginAppUser loginAppUser = sysUserService.findByUsername("admin"); LoginAppUser loginAppUser = sysUserService.findByUsername("admin");
......
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);
}
}
package com.central.common.lock; package com.central.common.lock;
import java.util.concurrent.TimeUnit;
/** /**
* 分布式锁顶级接口 * 分布式锁顶级接口
* 例如:
* RETRY_TIMES=100,SLEEP_MILLIS=100
* RETRY_TIMES * SLEEP_MILLIS = 10000 意味着如果一直获取不了锁,最长会等待10秒后抛超时异常
* *
* @author zlt * @author zlt
* @date 2018/5/29 14:12 * @date 2018/5/29 14:12
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/ */
public interface DistributedLock { 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);
/** /**
* 获取锁 * 获取锁,如果获取不成功则一直等待直到lock被获取
* * @param key 锁的key
* @param key key * @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁;
* @param expire 获取锁超时时间 * 如果leaseTime为-1,则保持锁定直到显式解锁
* @param retryTimes 重试次数 * @param unit {@code leaseTime} 参数的时间单位
* @return 成功/失败 * @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;
/** /**
* 获取锁 * 尝试获取锁,如果锁不可用则等待最多waitTime时间后放弃
* * @param key 锁的key
* @param key key * @param waitTime 获取锁的最大尝试时间(单位毫秒)
* @param expire 获取锁超时时间 * @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁;
* @param retryTimes 重试次数 * 如果leaseTime为-1,则保持锁定直到显式解锁
* @param sleepMillis 获取锁失败的重试间隔 * @param unit {@code waitTime} 和 {@code leaseTime} 参数的时间单位
* @return 成功/失败 * @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 lock 锁对象
* @param key key值
* @return 释放结果
*/ */
boolean releaseLock(String key); void unlock(Object lock) throws Exception;
} }
...@@ -9,51 +9,46 @@ import com.central.common.lock.DistributedLock; ...@@ -9,51 +9,46 @@ import com.central.common.lock.DistributedLock;
* *
* @author zlt * @author zlt
* @date 2019/1/10 * @date 2019/1/10
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/ */
public interface ISuperService<T> extends IService<T> { public interface ISuperService<T> extends IService<T> {
/** /**
* 幂等性新增记录 * 幂等性新增记录
* 例子如下:
* String username = sysUser.getUsername();
* boolean result = super.saveIdempotency(sysUser, lock
* , LOCK_KEY_USERNAME+username
* , new QueryWrapper<SysUser>().eq("username", username));
* *
* @param entity 实体对象 * @param entity 实体对象
* @param lock 锁实例 * @param locker 锁实例
* @param lockKey 锁的key * @param lockKey 锁的key
* @param countWrapper 判断是否存在的条件 * @param countWrapper 判断是否存在的条件
* @param msg 对象已存在提示信息 * @param msg 对象已存在提示信息
* @return * @return
*/ */
boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper, String msg); boolean saveIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper<T> countWrapper, String msg) throws Exception;
/** boolean saveIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper<T> countWrapper) throws Exception;
* 幂等性新增记录
*
* @param entity 实体对象
* @param lock 锁实例
* @param lockKey 锁的key
* @param countWrapper 判断是否存在的条件
* @return
*/
boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper);
/** /**
* 幂等性新增或更新记录 * 幂等性新增或更新记录
* 例子如下:
* String username = sysUser.getUsername();
* boolean result = super.saveOrUpdateIdempotency(sysUser, lock
* , LOCK_KEY_USERNAME+username
* , new QueryWrapper<SysUser>().eq("username", username));
* *
* @param entity 实体对象 * @param entity 实体对象
* @param lock 锁实例 * @param locker 锁实例
* @param lockKey 锁的key * @param lockKey 锁的key
* @param countWrapper 判断是否存在的条件 * @param countWrapper 判断是否存在的条件
* @param msg 对象已存在提示信息 * @param msg 对象已存在提示信息
* @return * @return
*/ */
boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper, String msg); boolean saveOrUpdateIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper<T> countWrapper, String msg) throws Exception;
/** boolean saveOrUpdateIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper<T> countWrapper) throws Exception;
* 幂等性新增或更新记录
*
* @param entity 实体对象
* @param lock 锁实例
* @param lockKey 锁的key
* @param countWrapper 判断是否存在的条件
* @return
*/
boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper);
} }
...@@ -16,41 +16,31 @@ import com.central.common.service.ISuperService; ...@@ -16,41 +16,31 @@ import com.central.common.service.ISuperService;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.TimeUnit;
/** /**
* service实现父类 * service实现父类
* *
* @author zlt * @author zlt
* @date 2019/1/10 * @date 2019/1/10
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/ */
public class SuperServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements ISuperService<T> { public class SuperServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements ISuperService<T> {
/**
* 幂等性新增记录
* 例子如下:
* String username = sysUser.getUsername();
* boolean result = super.saveIdempotency(sysUser, lock
* , LOCK_KEY_USERNAME+username
* , new QueryWrapper<SysUser>().eq("username", username));
*
* @param entity 实体对象
* @param lock 锁实例
* @param lockKey 锁的key
* @param countWrapper 判断是否存在的条件
* @param msg 对象已存在提示信息
* @return
*/
@Override @Override
public boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper, String msg) { public boolean saveIdempotency(T entity, DistributedLock locker, String lockKey, Wrapper<T> countWrapper, String msg) throws Exception {
if (lock == null) { if (locker == null) {
throw new LockException("DistributedLock is null"); throw new LockException("DistributedLock is null");
} }
if (StrUtil.isEmpty(lockKey)) { if (StrUtil.isEmpty(lockKey)) {
throw new LockException("lockKey is null"); throw new LockException("lockKey is null");
} }
Object lock;
try { try {
//加锁 //加锁
boolean isLock = lock.lock(lockKey); lock = locker.tryLock(lockKey, 10, 60, TimeUnit.SECONDS);
if (isLock) { if (lock != null) {
//判断记录是否已存在 //判断记录是否已存在
int count = super.count(countWrapper); int count = super.count(countWrapper);
if (count == 0) { if (count == 0) {
...@@ -65,41 +55,17 @@ public class SuperServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, ...@@ -65,41 +55,17 @@ public class SuperServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M,
throw new LockException("锁等待超时"); throw new LockException("锁等待超时");
} }
} finally { } finally {
lock.releaseLock(lockKey); locker.unlock(lockKey);
} }
} }
/**
* 幂等性新增记录
*
* @param entity 实体对象
* @param lock 锁实例
* @param lockKey 锁的key
* @param countWrapper 判断是否存在的条件
* @return
*/
@Override @Override
public boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper) { public boolean saveIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper) throws Exception {
return saveIdempotency(entity, lock, lockKey, countWrapper, null); return saveIdempotency(entity, lock, lockKey, countWrapper, null);
} }
/**
* 幂等性新增或更新记录
* 例子如下:
* String username = sysUser.getUsername();
* boolean result = super.saveOrUpdateIdempotency(sysUser, lock
* , LOCK_KEY_USERNAME+username
* , new QueryWrapper<SysUser>().eq("username", username));
*
* @param entity 实体对象
* @param lock 锁实例
* @param lockKey 锁的key
* @param countWrapper 判断是否存在的条件
* @param msg 对象已存在提示信息
* @return
*/
@Override @Override
public boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper, String msg) { public boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper, String msg) throws Exception {
if (null != entity) { if (null != entity) {
Class<?> cls = entity.getClass(); Class<?> cls = entity.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls); TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
...@@ -120,22 +86,8 @@ public class SuperServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, ...@@ -120,22 +86,8 @@ public class SuperServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M,
return false; return false;
} }
/**
* 幂等性新增或更新记录
* 例子如下:
* String username = sysUser.getUsername();
* boolean result = super.saveOrUpdateIdempotency(sysUser, lock
* , LOCK_KEY_USERNAME+username
* , new QueryWrapper<SysUser>().eq("username", username));
*
* @param entity 实体对象
* @param lock 锁实例
* @param lockKey 锁的key
* @param countWrapper 判断是否存在的条件
* @return
*/
@Override @Override
public boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper) { public boolean saveOrUpdateIdempotency(T entity, DistributedLock lock, String lockKey, Wrapper<T> countWrapper) throws Exception {
return this.saveOrUpdateIdempotency(entity, lock, lockKey, countWrapper, null); return this.saveOrUpdateIdempotency(entity, lock, lockKey, countWrapper, null);
} }
} }
package com.central.common.redis.lock; package com.central.common.redis.lock;
import com.central.common.lock.AbstractDistributedLock;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; 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.RedisStringCommands;
import org.springframework.data.redis.connection.ReturnType; import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration; import org.springframework.data.redis.core.types.Expiration;
import org.springframework.stereotype.Component;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -18,9 +17,16 @@ import java.util.concurrent.TimeUnit; ...@@ -18,9 +17,16 @@ import java.util.concurrent.TimeUnit;
* *
* @author zlt * @author zlt
* @date 2018/5/29 14:16 * @date 2018/5/29 14:16
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*
* @deprecated 建议使用Redisson的实现方式 {@link RedissonDistributedLock}
*/ */
@Slf4j @Slf4j
public class RedisDistributedLock extends AbstractDistributedLock { @ConditionalOnClass(RedisTemplate.class)
@Deprecated
public class RedisDistributedLock {
@Autowired @Autowired
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
...@@ -45,7 +51,15 @@ public class RedisDistributedLock extends AbstractDistributedLock { ...@@ -45,7 +51,15 @@ public class RedisDistributedLock extends AbstractDistributedLock {
this.redisTemplate = redisTemplate; 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) { public boolean lock(String key, long expire, int retryTimes, long sleepMillis) {
boolean result = setRedis(key, expire); boolean result = setRedis(key, expire);
// 如果获取锁失败,按照传入的重试次数进行重试 // 如果获取锁失败,按照传入的重试次数进行重试
...@@ -79,7 +93,11 @@ public class RedisDistributedLock extends AbstractDistributedLock { ...@@ -79,7 +93,11 @@ public class RedisDistributedLock extends AbstractDistributedLock {
return false; return false;
} }
@Override /**
* 释放锁
* @param key 锁的key
* @return 成功/失败
*/
public boolean releaseLock(String key) { public boolean releaseLock(String key) {
// 释放锁的时候,有可能因为持锁之后方法执行时间大于锁的有效期,此时有可能已经被另外一个线程持有锁,所以不能直接删除 // 释放锁的时候,有可能因为持锁之后方法执行时间大于锁的有效期,此时有可能已经被另外一个线程持有锁,所以不能直接删除
try { try {
......
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
* <p>
* 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");
}
}
}
}
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<Object> {
// 做一个空数组,不是null
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
// 为了方便进行对象与字节数组的转换,所以应该首先准备出两个转换器
private Converter<Object, byte[]> serializingConverter = new SerializingConverter();
private Converter<byte[], Object> 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
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.central.common.redis.RedisAutoConfigure,\ com.central.common.redis.RedisAutoConfigure,\
com.central.common.redis.lock.RedisDistributedLock,\ com.central.common.redis.lock.RedissonDistributedLock,\
com.central.common.redis.template.RedisRepository com.central.common.redis.template.RedisRepository
\ No newline at end of file
...@@ -18,6 +18,9 @@ import java.util.Map; ...@@ -18,6 +18,9 @@ import java.util.Map;
* 应用相关接口 * 应用相关接口
* *
* @author zlt * @author zlt
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/ */
@Api(tags = "应用") @Api(tags = "应用")
@RestController @RestController
...@@ -53,7 +56,7 @@ public class ClientController { ...@@ -53,7 +56,7 @@ public class ClientController {
@PostMapping("/saveOrUpdate") @PostMapping("/saveOrUpdate")
@ApiOperation(value = "保存或者修改应用") @ApiOperation(value = "保存或者修改应用")
public Result saveOrUpdate(@RequestBody ClientDto clientDto) { public Result saveOrUpdate(@RequestBody ClientDto clientDto) throws Exception {
return clientService.saveClient(clientDto); return clientService.saveClient(clientDto);
} }
} }
...@@ -9,9 +9,12 @@ import java.util.Map; ...@@ -9,9 +9,12 @@ import java.util.Map;
/** /**
* @author zlt * @author zlt
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/ */
public interface IClientService extends ISuperService<Client> { public interface IClientService extends ISuperService<Client> {
Result saveClient(Client clientDto); Result saveClient(Client clientDto) throws Exception;
/** /**
* 查询应用列表 * 查询应用列表
......
...@@ -23,11 +23,14 @@ import java.util.Map; ...@@ -23,11 +23,14 @@ import java.util.Map;
/** /**
* @author zlt * @author zlt
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/ */
@Slf4j @Slf4j
@Service @Service
public class ClientServiceImpl extends SuperServiceImpl<ClientMapper, Client> implements IClientService { public class ClientServiceImpl extends SuperServiceImpl<ClientMapper, Client> implements IClientService {
private final static String LOCK_KEY_CLIENTID = CommonConstant.LOCK_KEY_PREFIX+"clientId:"; private final static String LOCK_KEY_CLIENTID = "clientId:";
@Autowired @Autowired
private RedisRepository redisRepository; private RedisRepository redisRepository;
...@@ -39,7 +42,7 @@ public class ClientServiceImpl extends SuperServiceImpl<ClientMapper, Client> im ...@@ -39,7 +42,7 @@ public class ClientServiceImpl extends SuperServiceImpl<ClientMapper, Client> im
private DistributedLock lock; private DistributedLock lock;
@Override @Override
public Result saveClient(Client client) { public Result saveClient(Client client) throws Exception {
client.setClientSecret(passwordEncoder.encode(client.getClientSecretStr())); client.setClientSecret(passwordEncoder.encode(client.getClientSecretStr()));
String clientId = client.getClientId(); String clientId = client.getClientId();
super.saveOrUpdateIdempotency(client, lock super.saveOrUpdateIdempotency(client, lock
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册