From 3dc77a653eef07caebdf3122e2af0d7338faa877 Mon Sep 17 00:00:00 2001 From: yandanyang Date: Tue, 9 Nov 2021 19:48:25 +0800 Subject: [PATCH] =?UTF-8?q?id=E6=9B=BF=E6=8D=A2=E4=BB=A5=E5=8F=8A=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/constant/CacheModuleConst.java | 5 + .../idgenerator/IdGeneratorController.java | 4 +- .../idgenerator/IdGeneratorService.java | 136 ------------------ .../constant/IdGeneratorStrategyTypeEnum.java | 28 ++++ .../idgenerator/{ => dao}/IdGeneratorDao.java | 9 +- .../{ => dao}/IdGeneratorRecordDao.java | 2 +- .../service/IdGeneratorCacheService.java | 37 +++++ .../service/IdGeneratorService.java | 44 ++++++ .../strategy/IIdGeneratorStrategy.java | 36 +++++ .../strategy/IdGeneratorInternStrategy.java | 48 +++++++ .../strategy/IdGeneratorMySqlStrategy.java | 53 +++++++ .../strategy/IdGeneratorRedisStrategy.java | 95 ++++++++++++ .../IdGeneratorStrategyBaseService.java | 82 +++++++++++ .../strategy/IdGeneratorStrategyFactory.java | 34 +++++ .../mapper/support/IdGeneratorMapper.xml | 10 ++ .../support/IdGeneratorRecordMapper.xml | 2 +- .../service/IdGeneratorServiceTest.java | 4 +- 17 files changed, 487 insertions(+), 142 deletions(-) delete mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorService.java create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/constant/IdGeneratorStrategyTypeEnum.java rename admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/{ => dao}/IdGeneratorDao.java (70%) rename admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/{ => dao}/IdGeneratorRecordDao.java (99%) create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/service/IdGeneratorCacheService.java create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/service/IdGeneratorService.java create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IIdGeneratorStrategy.java create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorInternStrategy.java create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorMySqlStrategy.java create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorRedisStrategy.java create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorStrategyBaseService.java create mode 100644 admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorStrategyFactory.java create mode 100644 admin-api/java-api/src/main/resources/mapper/support/IdGeneratorMapper.xml diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/constant/CacheModuleConst.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/constant/CacheModuleConst.java index fd8edb63..05fc7d81 100644 --- a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/constant/CacheModuleConst.java +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/constant/CacheModuleConst.java @@ -6,6 +6,11 @@ package net.lab1024.smartadmin.service.constant; */ public class CacheModuleConst { + public static class IdGenerator { + public static final String ID_GENERATOR_CACHE = "id_generator_cache"; + } + + public static class Employee { /** * 某个部门下的员工缓存 diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorController.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorController.java index a420d4da..2430febe 100644 --- a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorController.java +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorController.java @@ -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.module.support.idgenerator.constant.IdGeneratorEnum; 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.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -33,7 +35,7 @@ public class IdGeneratorController extends SupportBaseController { if (null == idGeneratorEnum) { return ResponseDTO.error(UserErrorCode.PARAM_ERROR, "IdGenerator,不存在" + generatorId); } - return ResponseDTO.ok(idGeneratorService.generate(idGeneratorEnum)); + return ResponseDTO.ok(idGeneratorService.generate(idGeneratorEnum, IdGeneratorStrategyTypeEnum.INTERN)); } } diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorService.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorService.java deleted file mode 100644 index 2f02b79a..00000000 --- a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorService.java +++ /dev/null @@ -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 POOL = Interners.newWeakInterner(); - - @Autowired - private IdGeneratorDao idGeneratorDao; - - @Autowired - private IdGeneratorRecordDao idGeneratorRecordDao; - - private Map idGeneratorMap; - - @PostConstruct - public void init() { - List 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); - } -} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/constant/IdGeneratorStrategyTypeEnum.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/constant/IdGeneratorStrategyTypeEnum.java new file mode 100644 index 00000000..3511c12d --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/constant/IdGeneratorStrategyTypeEnum.java @@ -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; + +} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorDao.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/dao/IdGeneratorDao.java similarity index 70% rename from admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorDao.java rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/dao/IdGeneratorDao.java index 8d74f247..c52455c0 100644 --- a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorDao.java +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/dao/IdGeneratorDao.java @@ -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 net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Component; /** @@ -14,4 +15,10 @@ import org.springframework.stereotype.Component; @Component public interface IdGeneratorDao extends BaseMapper { + /** + * 排他锁查询 + * @param id + * @return + */ + IdGeneratorEntity selectForUpdate(@Param("id")Integer id); } diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorRecordDao.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/dao/IdGeneratorRecordDao.java similarity index 99% rename from admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorRecordDao.java rename to admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/dao/IdGeneratorRecordDao.java index e003e324..370778c1 100644 --- a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/IdGeneratorRecordDao.java +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/dao/IdGeneratorRecordDao.java @@ -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 net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity; diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/service/IdGeneratorCacheService.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/service/IdGeneratorCacheService.java new file mode 100644 index 00000000..73fc0858 --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/service/IdGeneratorCacheService.java @@ -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); + } + +} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/service/IdGeneratorService.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/service/IdGeneratorService.java new file mode 100644 index 00000000..5fa1d316 --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/service/IdGeneratorService.java @@ -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); + } + + +} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IIdGeneratorStrategy.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IIdGeneratorStrategy.java new file mode 100644 index 00000000..9ce2ac4b --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IIdGeneratorStrategy.java @@ -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); + + +} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorInternStrategy.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorInternStrategy.java new file mode 100644 index 00000000..0b41bc73 --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorInternStrategy.java @@ -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 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); + } + } +} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorMySqlStrategy.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorMySqlStrategy.java new file mode 100644 index 00000000..ad481bb3 --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorMySqlStrategy.java @@ -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); + + } +} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorRedisStrategy.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorRedisStrategy.java new file mode 100644 index 00000000..9dd672b3 --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorRedisStrategy.java @@ -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); + } + } +} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorStrategyBaseService.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorStrategyBaseService.java new file mode 100644 index 00000000..140c96f5 --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorStrategyBaseService.java @@ -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; + } +} diff --git a/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorStrategyFactory.java b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorStrategyFactory.java new file mode 100644 index 00000000..12d6b0da --- /dev/null +++ b/admin-api/java-api/src/main/java/net/lab1024/smartadmin/service/module/support/idgenerator/strategy/IdGeneratorStrategyFactory.java @@ -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 idGeneratorStrategyList; + + /** + * 获取某个策略 + * @param strategyTypeEnum + * @return + */ + public IIdGeneratorStrategy getIdGeneratorStrategy(IdGeneratorStrategyTypeEnum strategyTypeEnum) { + Optional idGeneratorStrategyOptional = idGeneratorStrategyList.stream().filter(e -> e.getStrategyType() == strategyTypeEnum).findFirst(); + if (!idGeneratorStrategyOptional.isPresent()) { + return null; + } + return idGeneratorStrategyOptional.get(); + } +} diff --git a/admin-api/java-api/src/main/resources/mapper/support/IdGeneratorMapper.xml b/admin-api/java-api/src/main/resources/mapper/support/IdGeneratorMapper.xml new file mode 100644 index 00000000..b7f50e73 --- /dev/null +++ b/admin-api/java-api/src/main/resources/mapper/support/IdGeneratorMapper.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/admin-api/java-api/src/main/resources/mapper/support/IdGeneratorRecordMapper.xml b/admin-api/java-api/src/main/resources/mapper/support/IdGeneratorRecordMapper.xml index 8a7d5c5f..3b48fae8 100644 --- a/admin-api/java-api/src/main/resources/mapper/support/IdGeneratorRecordMapper.xml +++ b/admin-api/java-api/src/main/resources/mapper/support/IdGeneratorRecordMapper.xml @@ -1,6 +1,6 @@ - +