1. 数据库表设计
DROP TABLE IF EXISTS `lock_info`;
CREATE TABLE `lock_info` (
`id` bigint(20) NOT NULL,
`expiration_time` datetime NOT NULL,
`status` int(11) NOT NULL,
`tag` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tag` (`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. Mapper代码示例
@Mapper
public interface LockInfoMapper extends BaseMapper<LockInfoEntity>{
/**
* 分页查询指定行数据
*
* @param page 分页参数
* @param wrapper 动态查询条件
* @return 分页对象列表
*/
IPage<LockInfoEntity> selectByPage(IPage<LockInfoEntity> page , @Param(Constants.WRAPPER) Wrapper<LockInfoEntity> wrapper);
LockInfoEntity findByTag(String tag);
int deleteByTag(String tag);
}
3.Entity代码示例
@Data
@TableName("lock_info")
public class LockInfoEntity implements Serializable,Cloneable{
public final static Integer LOCKED_STATUS = 1;
public final static Integer UNLOCKED_STATUS = 0;
/** */
@TableId
private Long id ;
/** */
private Date expirationTime ;
/** */
private Integer status ;
/** */
private String tag ;
public LockInfoEntity(String tag, Date expirationTime, Integer status) {
this.tag = tag;
this.expirationTime = expirationTime;
this.status = status;
}
}
4.Service代码示例
@Override
@Transactional(rollbackFor = Throwable.class)
public boolean tryLock(String tag, Integer expiredSeconds) {
if (StringUtils.isEmpty(tag)) {
throw new NullPointerException();
}
LockInfoEntity lockItem = lockInfoMapper.findByTag(tag);
if (Objects.isNull(lockItem)) {
lockInfoMapper.insert(new LockInfoEntity(tag, this.addSeconds(new Date(), expiredSeconds), LockInfoEntity.LOCKED_STATUS));
return true;
} else {
Date expiredTime = lockItem.getExpirationTime();
Date now = new Date();
if (expiredTime.before(now)) {
lockItem.setExpirationTime(this.addSeconds(now, expiredSeconds));
lockInfoMapper.updateById(lockItem);
return true;
}
}
return false;
}
@Override
public boolean unlock(String tag) {
if (StringUtils.isEmpty(tag)) {
throw new NullPointerException();
}
int cnt = lockInfoMapper.deleteByTag(tag);
return cnt==1 ? true : false;
}
private Date addSeconds(Date date, Integer seconds) {
if (Objects.isNull(seconds)){
seconds = DEFAULT_EXPIRED_SECONDS;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.SECOND, seconds);
return calendar.getTime();
}
5. 分布式锁功能验证代码示例、
@GetMapping("/test")
public String testBusiness(@RequestParam String tag, @RequestParam Integer expiredSeconds) {
if (lockService.tryLock(tag, expiredSeconds)) {
try {
//do something
Thread.sleep(3000);
} catch (Exception e) {
} finally {
lockService.unlock(tag);
}
return "获取锁成功,tag是:" + tag;
}
return "当前tag:" + tag + "已经存在锁,请稍后重试!";
}