mirror of
https://gitee.com/lab1024/smart-admin.git
synced 2025-10-08 21:26:40 +08:00
Merge remote-tracking branch 'origin/2.0.0-alpha' into 2.0.0-alpha
This commit is contained in:
commit
49f925d3b0
@ -6,6 +6,11 @@ package net.lab1024.smartadmin.service.constant;
|
|||||||
*/
|
*/
|
||||||
public class CacheModuleConst {
|
public class CacheModuleConst {
|
||||||
|
|
||||||
|
public static class IdGenerator {
|
||||||
|
public static final String ID_GENERATOR_CACHE = "id_generator_cache";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Employee {
|
public static class Employee {
|
||||||
/**
|
/**
|
||||||
* 某个部门下的员工缓存
|
* 某个部门下的员工缓存
|
||||||
|
@ -8,6 +8,8 @@ import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
|
|||||||
import net.lab1024.smartadmin.service.common.swagger.SwaggerTagConst;
|
import net.lab1024.smartadmin.service.common.swagger.SwaggerTagConst;
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
import net.lab1024.smartadmin.service.common.util.SmartBaseEnumUtil;
|
import net.lab1024.smartadmin.service.common.util.SmartBaseEnumUtil;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorStrategyTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.service.IdGeneratorService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
@ -33,7 +35,7 @@ public class IdGeneratorController extends SupportBaseController {
|
|||||||
if (null == idGeneratorEnum) {
|
if (null == idGeneratorEnum) {
|
||||||
return ResponseDTO.error(UserErrorCode.PARAM_ERROR, "IdGenerator,不存在" + generatorId);
|
return ResponseDTO.error(UserErrorCode.PARAM_ERROR, "IdGenerator,不存在" + generatorId);
|
||||||
}
|
}
|
||||||
return ResponseDTO.ok(idGeneratorService.generate(idGeneratorEnum));
|
return ResponseDTO.ok(idGeneratorService.generate(idGeneratorEnum, IdGeneratorStrategyTypeEnum.INTERN));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,136 +0,0 @@
|
|||||||
package net.lab1024.smartadmin.service.module.support.idgenerator;
|
|
||||||
|
|
||||||
import com.google.common.collect.Interner;
|
|
||||||
import com.google.common.collect.Interners;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import net.lab1024.smartadmin.service.common.util.SmartRandomUtil;
|
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorRuleTypeEnum;
|
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity;
|
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局id生成器
|
|
||||||
*
|
|
||||||
* @author zhuo
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class IdGeneratorService {
|
|
||||||
|
|
||||||
private static final Interner<Integer> POOL = Interners.newWeakInterner();
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IdGeneratorDao idGeneratorDao;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IdGeneratorRecordDao idGeneratorRecordDao;
|
|
||||||
|
|
||||||
private Map<Integer, IdGeneratorEntity> idGeneratorMap;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
List<IdGeneratorEntity> idGeneratorEntityList = idGeneratorDao.selectList(null);
|
|
||||||
idGeneratorMap = idGeneratorEntityList.stream().collect(Collectors.toMap(IdGeneratorEntity::getId, Function.identity()));
|
|
||||||
log.info("##################### init IdGenerator #####################");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* id生成
|
|
||||||
*
|
|
||||||
* @param idGeneratorEnum 类型
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String generate(IdGeneratorEnum idGeneratorEnum) {
|
|
||||||
int generatorId = idGeneratorEnum.getValue();
|
|
||||||
IdGeneratorEntity idGeneratorEntity = this.idGeneratorMap.get(generatorId);
|
|
||||||
Assert.notNull(idGeneratorEntity, "IdGenerator不存在 " + idGeneratorEntity.getRuleType());
|
|
||||||
|
|
||||||
// 校验生成规则
|
|
||||||
IdGeneratorRuleTypeEnum ruleTypeEnum = this.getIdGeneratorRuleTypeEnum(idGeneratorEntity.getRuleType());
|
|
||||||
Assert.notNull(ruleTypeEnum, "IdGenerator rule type 不存在 " + idGeneratorEntity.getRuleType());
|
|
||||||
|
|
||||||
// 默认起始值
|
|
||||||
Long startNumber = idGeneratorEntity.getInitNumber();
|
|
||||||
|
|
||||||
// 判断是否有循环规则
|
|
||||||
String timeFormat = null;
|
|
||||||
DateTimeFormatter timeFormatter = null;
|
|
||||||
if (IdGeneratorRuleTypeEnum.YEAR_CYCLE == ruleTypeEnum || IdGeneratorRuleTypeEnum.MONTH_CYCLE == ruleTypeEnum || IdGeneratorRuleTypeEnum.DAY_CYCLE == ruleTypeEnum) {
|
|
||||||
timeFormatter = DateTimeFormatter.ofPattern(ruleTypeEnum.getValue());
|
|
||||||
timeFormat = LocalDateTime.now().format(timeFormatter);
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (POOL.intern(generatorId)) {
|
|
||||||
// 获取最后一次生成记录
|
|
||||||
boolean isFirst = false;
|
|
||||||
IdGeneratorRecordEntity recordEntity = idGeneratorRecordDao.selectHistoryLastNumber(generatorId, timeFormat);
|
|
||||||
if (recordEntity == null) {
|
|
||||||
recordEntity = new IdGeneratorRecordEntity();
|
|
||||||
recordEntity.setGeneratorId(generatorId);
|
|
||||||
recordEntity.setTime(timeFormat);
|
|
||||||
recordEntity.setLastNumber(startNumber);
|
|
||||||
recordEntity.setCount(1L);
|
|
||||||
idGeneratorRecordDao.insert(recordEntity);
|
|
||||||
|
|
||||||
isFirst = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 没有循环 或 在同个循环周期内,起始值 = 上次id
|
|
||||||
if (IdGeneratorRuleTypeEnum.NO_CYCLE == ruleTypeEnum || Objects.equals(recordEntity.getUpdateTime().format(timeFormatter), timeFormat)) {
|
|
||||||
startNumber = recordEntity.getLastNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 在范围内随机生成此次增加的数值 更新id生成记录
|
|
||||||
if (!isFirst) {
|
|
||||||
startNumber += SmartRandomUtil.nextInt(1, idGeneratorEntity.getStepRandomRange());
|
|
||||||
IdGeneratorRecordEntity updateRecordEntity = new IdGeneratorRecordEntity();
|
|
||||||
updateRecordEntity.setId(recordEntity.getId());
|
|
||||||
updateRecordEntity.setLastNumber(startNumber);
|
|
||||||
updateRecordEntity.setCount(recordEntity.getCount() + 1);
|
|
||||||
idGeneratorRecordDao.updateById(updateRecordEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 默认 最低长度 1
|
|
||||||
int minLength = NumberUtils.max(idGeneratorEntity.getMinLength(), 1);
|
|
||||||
// id长度补位
|
|
||||||
String finalId = String.format("%0" + minLength + "d", startNumber);
|
|
||||||
if (null != timeFormat) {
|
|
||||||
finalId = timeFormat + finalId;
|
|
||||||
}
|
|
||||||
// 前缀
|
|
||||||
if (StringUtils.isNotBlank(idGeneratorEntity.getPrefix())) {
|
|
||||||
finalId = idGeneratorEntity.getPrefix() + finalId;
|
|
||||||
}
|
|
||||||
return finalId;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询生成规则
|
|
||||||
*
|
|
||||||
* @param ruleType
|
|
||||||
* @return 没有则返回null
|
|
||||||
*/
|
|
||||||
private IdGeneratorRuleTypeEnum getIdGeneratorRuleTypeEnum(String ruleType) {
|
|
||||||
return Arrays.stream(IdGeneratorRuleTypeEnum.values())
|
|
||||||
.filter(e -> StringUtils.equalsIgnoreCase(e.name(), ruleType))
|
|
||||||
.findFirst().orElse(null);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,28 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.constant;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.lab1024.smartadmin.service.common.enumeration.BaseEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @date 2021/11/9 18:49
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum IdGeneratorStrategyTypeEnum implements BaseEnum {
|
||||||
|
|
||||||
|
INTERN(1, "string intern"),
|
||||||
|
|
||||||
|
REDIS(2, "redis"),
|
||||||
|
|
||||||
|
MYSQL_LOCK(2, "mysql排他锁"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer value;
|
||||||
|
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
package net.lab1024.smartadmin.service.module.support.idgenerator;
|
package net.lab1024.smartadmin.service.module.support.idgenerator.dao;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity;
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,4 +15,10 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public interface IdGeneratorDao extends BaseMapper<IdGeneratorEntity> {
|
public interface IdGeneratorDao extends BaseMapper<IdGeneratorEntity> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排他锁查询
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IdGeneratorEntity selectForUpdate(@Param("id")Integer id);
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package net.lab1024.smartadmin.service.module.support.idgenerator;
|
package net.lab1024.smartadmin.service.module.support.idgenerator.dao;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity;
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity;
|
@ -0,0 +1,37 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.service;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.lab1024.smartadmin.service.constant.CacheModuleConst;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.dao.IdGeneratorDao;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @date
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class IdGeneratorCacheService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IdGeneratorDao idGeneratorDao;
|
||||||
|
|
||||||
|
@Cacheable(CacheModuleConst.IdGenerator.ID_GENERATOR_CACHE)
|
||||||
|
public IdGeneratorEntity getIdGeneratorEntity(Integer generatorId){
|
||||||
|
return idGeneratorDao.selectById(generatorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.service;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorStrategyTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.strategy.IdGeneratorStrategyFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局id生成器
|
||||||
|
*
|
||||||
|
* @author zhuo
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class IdGeneratorService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IdGeneratorStrategyFactory idGeneratorStrategyFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义生成策略生成
|
||||||
|
*
|
||||||
|
* @param idGeneratorEnum
|
||||||
|
* @param strategyTypeEnum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String generate(IdGeneratorEnum idGeneratorEnum, IdGeneratorStrategyTypeEnum strategyTypeEnum) {
|
||||||
|
return idGeneratorStrategyFactory.getIdGeneratorStrategy(strategyTypeEnum).generate(idGeneratorEnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单的生成 依据 intern
|
||||||
|
*
|
||||||
|
* @param idGeneratorEnum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String simpleGenerate(IdGeneratorEnum idGeneratorEnum) {
|
||||||
|
return idGeneratorStrategyFactory.getIdGeneratorStrategy(IdGeneratorStrategyTypeEnum.INTERN).generate(idGeneratorEnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.strategy;
|
||||||
|
|
||||||
|
import net.lab1024.smartadmin.service.common.util.SmartRandomUtil;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorRuleTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorStrategyTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @date 2021/11/9 18:48
|
||||||
|
*/
|
||||||
|
public interface IIdGeneratorStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略类型
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IdGeneratorStrategyTypeEnum getStrategyType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成
|
||||||
|
* @param idGeneratorEnum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String generate(IdGeneratorEnum idGeneratorEnum);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.strategy;
|
||||||
|
|
||||||
|
import com.google.common.collect.Interner;
|
||||||
|
import com.google.common.collect.Interners;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorStrategyTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.service.IdGeneratorCacheService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @date 2021/11/9 18:48
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class IdGeneratorInternStrategy extends IdGeneratorStrategyBaseService {
|
||||||
|
|
||||||
|
private static final Interner<Integer> POOL = Interners.newWeakInterner();
|
||||||
|
@Autowired
|
||||||
|
private IdGeneratorCacheService idGeneratorCacheService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略类型
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IdGeneratorStrategyTypeEnum getStrategyType() {
|
||||||
|
return IdGeneratorStrategyTypeEnum.INTERN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成
|
||||||
|
*
|
||||||
|
* @param idGeneratorEnum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String generate(IdGeneratorEnum idGeneratorEnum) {
|
||||||
|
IdGeneratorEntity idGeneratorEntity = idGeneratorCacheService.getIdGeneratorEntity(idGeneratorEnum.getValue());
|
||||||
|
synchronized (POOL.intern(idGeneratorEntity.getId())) {
|
||||||
|
return generate(idGeneratorEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.strategy;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.lab1024.smartadmin.service.common.exception.BusinessException;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorStrategyTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.dao.IdGeneratorDao;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @date 2021/11/9 18:48
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class IdGeneratorMySqlStrategy extends IdGeneratorStrategyBaseService {
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IdGeneratorDao idGeneratorDao;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略类型
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IdGeneratorStrategyTypeEnum getStrategyType() {
|
||||||
|
return IdGeneratorStrategyTypeEnum.MYSQL_LOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成
|
||||||
|
*
|
||||||
|
* @param idGeneratorEnum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
|
public String generate(IdGeneratorEnum idGeneratorEnum) {
|
||||||
|
IdGeneratorEntity idGeneratorEntity = idGeneratorDao.selectForUpdate(idGeneratorEnum.getValue());
|
||||||
|
if (idGeneratorEntity == null) {
|
||||||
|
throw new BusinessException("IdGenerator, id 数据库不存在");
|
||||||
|
}
|
||||||
|
return generate(idGeneratorEntity);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.strategy;
|
||||||
|
|
||||||
|
import com.google.common.collect.Interner;
|
||||||
|
import com.google.common.collect.Interners;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
|
||||||
|
import net.lab1024.smartadmin.service.common.exception.BusinessException;
|
||||||
|
import net.lab1024.smartadmin.service.common.util.SmartRandomUtil;
|
||||||
|
import net.lab1024.smartadmin.service.constant.RedisKeyConst;
|
||||||
|
import net.lab1024.smartadmin.service.constant.SwaggerTagConst;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorRuleTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorStrategyTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.service.IdGeneratorCacheService;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.redis.RedisService;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.logging.log4j.util.Strings;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @date 2021/11/9 18:48
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class IdGeneratorRedisStrategy extends IdGeneratorStrategyBaseService {
|
||||||
|
|
||||||
|
private static final int MAX_GET_LOCK_COUNT = 5;
|
||||||
|
|
||||||
|
private static final long SLEEP_MILLISECONDS = 500L;
|
||||||
|
|
||||||
|
private static volatile long lastSleepMilliSeconds = SLEEP_MILLISECONDS;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IdGeneratorCacheService idGeneratorCacheService;
|
||||||
|
@Autowired
|
||||||
|
private RedisService redisService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略类型
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IdGeneratorStrategyTypeEnum getStrategyType() {
|
||||||
|
return IdGeneratorStrategyTypeEnum.REDIS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成
|
||||||
|
*
|
||||||
|
* @param idGeneratorEnum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String generate(IdGeneratorEnum idGeneratorEnum) {
|
||||||
|
IdGeneratorEntity idGeneratorEntity = idGeneratorCacheService.getIdGeneratorEntity(idGeneratorEnum.getValue());
|
||||||
|
String lockKey = RedisKeyConst.Support.ID_GENERATOR + idGeneratorEnum.getValue();
|
||||||
|
try {
|
||||||
|
boolean lock = false;
|
||||||
|
for (int i = 0; i < MAX_GET_LOCK_COUNT; i++) {
|
||||||
|
try {
|
||||||
|
lock = redisService.getLock(lockKey, 60 * 1000L);
|
||||||
|
if (lock) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Thread.sleep(Math.max(SLEEP_MILLISECONDS, lastSleepMilliSeconds));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!lock) {
|
||||||
|
throw new BusinessException("系统繁忙");
|
||||||
|
}
|
||||||
|
long beginTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
String id = generate(idGeneratorEntity);
|
||||||
|
lastSleepMilliSeconds = System.currentTimeMillis() - beginTime + 100;
|
||||||
|
return id;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
redisService.unLock(lockKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.strategy;
|
||||||
|
|
||||||
|
import net.lab1024.smartadmin.service.common.util.SmartBaseEnumUtil;
|
||||||
|
import net.lab1024.smartadmin.service.common.util.SmartRandomUtil;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorRuleTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.dao.IdGeneratorRecordDao;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @date 2021/11/9 19:12
|
||||||
|
*/
|
||||||
|
public abstract class IdGeneratorStrategyBaseService implements IIdGeneratorStrategy{
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IdGeneratorRecordDao idGeneratorRecordDao;
|
||||||
|
|
||||||
|
|
||||||
|
public String generate(IdGeneratorEntity idGeneratorEntity){
|
||||||
|
// 校验生成规则
|
||||||
|
IdGeneratorRuleTypeEnum ruleTypeEnum = SmartBaseEnumUtil.getEnumByName(idGeneratorEntity.getRuleType(),IdGeneratorRuleTypeEnum.class);
|
||||||
|
// 默认起始值
|
||||||
|
Long startNumber = idGeneratorEntity.getInitNumber();
|
||||||
|
Integer generatorId = idGeneratorEntity.getId();
|
||||||
|
// 判断是否有循环规则
|
||||||
|
String timeFormat = null;
|
||||||
|
DateTimeFormatter timeFormatter = null;
|
||||||
|
if (IdGeneratorRuleTypeEnum.YEAR_CYCLE == ruleTypeEnum || IdGeneratorRuleTypeEnum.MONTH_CYCLE == ruleTypeEnum || IdGeneratorRuleTypeEnum.DAY_CYCLE == ruleTypeEnum) {
|
||||||
|
timeFormatter = DateTimeFormatter.ofPattern(ruleTypeEnum.getValue());
|
||||||
|
timeFormat = LocalDateTime.now().format(timeFormatter);
|
||||||
|
}
|
||||||
|
// 获取最后一次生成记录
|
||||||
|
boolean isFirst = false;
|
||||||
|
IdGeneratorRecordEntity recordEntity = idGeneratorRecordDao.selectHistoryLastNumber(generatorId, timeFormat);
|
||||||
|
if (recordEntity == null) {
|
||||||
|
recordEntity = new IdGeneratorRecordEntity();
|
||||||
|
recordEntity.setGeneratorId(generatorId);
|
||||||
|
recordEntity.setTime(timeFormat);
|
||||||
|
recordEntity.setLastNumber(startNumber);
|
||||||
|
recordEntity.setCount(1L);
|
||||||
|
idGeneratorRecordDao.insert(recordEntity);
|
||||||
|
|
||||||
|
isFirst = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 没有循环 或 在同个循环周期内,起始值 = 上次id
|
||||||
|
if (IdGeneratorRuleTypeEnum.NO_CYCLE == ruleTypeEnum || Objects.equals(recordEntity.getUpdateTime().format(timeFormatter), timeFormat)) {
|
||||||
|
startNumber = recordEntity.getLastNumber();
|
||||||
|
}
|
||||||
|
// 在范围内随机生成此次增加的数值 更新id生成记录
|
||||||
|
if (!isFirst) {
|
||||||
|
startNumber += SmartRandomUtil.nextInt(1, idGeneratorEntity.getStepRandomRange());
|
||||||
|
IdGeneratorRecordEntity updateRecordEntity = new IdGeneratorRecordEntity();
|
||||||
|
updateRecordEntity.setId(recordEntity.getId());
|
||||||
|
updateRecordEntity.setLastNumber(startNumber);
|
||||||
|
updateRecordEntity.setCount(recordEntity.getCount() + 1);
|
||||||
|
idGeneratorRecordDao.updateById(updateRecordEntity);
|
||||||
|
}
|
||||||
|
// 默认 最低长度 1
|
||||||
|
int minLength = NumberUtils.max(idGeneratorEntity.getMinLength(), 1);
|
||||||
|
// id长度补位
|
||||||
|
String finalId = String.format("%0" + minLength + "d", startNumber);
|
||||||
|
if (null != timeFormat) {
|
||||||
|
finalId = timeFormat + finalId;
|
||||||
|
}
|
||||||
|
// 前缀
|
||||||
|
if (StringUtils.isNotBlank(idGeneratorEntity.getPrefix())) {
|
||||||
|
finalId = idGeneratorEntity.getPrefix() + finalId;
|
||||||
|
}
|
||||||
|
return finalId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.strategy;
|
||||||
|
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorStrategyTypeEnum;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ ]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @date 2021/11/9 18:48
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class IdGeneratorStrategyFactory {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private List<IIdGeneratorStrategy> idGeneratorStrategyList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取某个策略
|
||||||
|
* @param strategyTypeEnum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public IIdGeneratorStrategy getIdGeneratorStrategy(IdGeneratorStrategyTypeEnum strategyTypeEnum) {
|
||||||
|
Optional<IIdGeneratorStrategy> idGeneratorStrategyOptional = idGeneratorStrategyList.stream().filter(e -> e.getStrategyType() == strategyTypeEnum).findFirst();
|
||||||
|
if (!idGeneratorStrategyOptional.isPresent()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return idGeneratorStrategyOptional.get();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="net.lab1024.smartadmin.service.module.support.idgenerator.dao.IdGeneratorDao">
|
||||||
|
|
||||||
|
<!-- 查询最后生成记录 -->
|
||||||
|
<select id="selectForUpdate" resultType="net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity">
|
||||||
|
select * from t_id_generator where id = #{id} for update
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="net.lab1024.smartadmin.service.module.support.idgenerator.IdGeneratorRecordDao">
|
<mapper namespace="net.lab1024.smartadmin.service.module.support.idgenerator.dao.IdGeneratorRecordDao">
|
||||||
|
|
||||||
<!-- 查询最后生成记录 -->
|
<!-- 查询最后生成记录 -->
|
||||||
<select id="selectHistoryLastNumber" resultType="net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity">
|
<select id="selectHistoryLastNumber" resultType="net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package net.lab1024.smartadmin.service.module.support.idgenerator.service;
|
package net.lab1024.smartadmin.service.module.support.idgenerator.service;
|
||||||
|
|
||||||
import net.lab1024.smartadmin.service.SmartAdminApplicationTest;
|
import net.lab1024.smartadmin.service.SmartAdminApplicationTest;
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.IdGeneratorService;
|
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorStrategyTypeEnum;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ class IdGeneratorServiceTest extends SmartAdminApplicationTest {
|
|||||||
CountDownLatch countDownLatch = new CountDownLatch(thread);
|
CountDownLatch countDownLatch = new CountDownLatch(thread);
|
||||||
|
|
||||||
Runnable task = () -> {
|
Runnable task = () -> {
|
||||||
String id = generatorService.generate(IdGeneratorEnum.CONTRACT);
|
String id = generatorService.generate(IdGeneratorEnum.CONTRACT, IdGeneratorStrategyTypeEnum.MYSQL_LOCK);
|
||||||
System.out.println(countDownLatch.getCount() + "生成id->" + id);
|
System.out.println(countDownLatch.getCount() + "生成id->" + id);
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user