mirror of
https://gitee.com/lab1024/smart-admin.git
synced 2025-10-09 05:36:41 +08:00
一顿优化IdGeneratorService
This commit is contained in:
parent
7295b90320
commit
98d80a0a03
@ -12,13 +12,12 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||||||
* [ admin 项目启动类 ]
|
* [ admin 项目启动类 ]
|
||||||
*
|
*
|
||||||
* @author 罗伊
|
* @author 罗伊
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@EnableCaching
|
@EnableCaching
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
|
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
|
||||||
@MapperScan(value = "net.lab1024.smartadmin.service.*",annotationClass = Mapper.class)
|
@MapperScan(value = "net.lab1024.smartadmin.service.*", annotationClass = Mapper.class)
|
||||||
public class SmartAdminApplication {
|
public class SmartAdminApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -18,7 +18,7 @@ import org.apache.commons.io.FileUtils;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ import java.util.Map;
|
|||||||
* @date 2020/8/25 11:57
|
* @date 2020/8/25 11:57
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Configuration
|
||||||
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = "cloud")
|
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = "cloud")
|
||||||
public class FileStorageCloudServiceImpl implements IFileStorageService {
|
public class FileStorageCloudServiceImpl implements IFileStorageService {
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import org.apache.commons.io.FileUtils;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ import java.io.InputStream;
|
|||||||
* @date 2020/8/25 11:57
|
* @date 2020/8/25 11:57
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Configuration
|
||||||
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = "local")
|
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = "local")
|
||||||
public class FileStorageLocalServiceImpl implements IFileStorageService {
|
public class FileStorageLocalServiceImpl implements IFileStorageService {
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ public class IdGeneratorController extends SupportBaseController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IdGeneratorService idGeneratorService;
|
private IdGeneratorService idGeneratorService;
|
||||||
|
|
||||||
@ApiOperation("生成id")
|
@ApiOperation("生成id by listen")
|
||||||
@GetMapping("/id/generator/{generatorId}")
|
@GetMapping("/id/generator/{generatorId}")
|
||||||
public ResponseDTO<String> generate(@PathVariable Integer generatorId) {
|
public ResponseDTO<String> generate(@PathVariable Integer generatorId) {
|
||||||
IdGeneratorEnum idGeneratorEnum = SmartBaseEnumUtil.getEnumByValue(generatorId, IdGeneratorEnum.class);
|
IdGeneratorEnum idGeneratorEnum = SmartBaseEnumUtil.getEnumByValue(generatorId, IdGeneratorEnum.class);
|
||||||
|
@ -1,32 +1,17 @@
|
|||||||
package net.lab1024.smartadmin.service.module.support.idgenerator;
|
package net.lab1024.smartadmin.service.module.support.idgenerator;
|
||||||
|
|
||||||
|
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 net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordDTO;
|
|
||||||
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;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zhuo
|
* id生成 dao
|
||||||
|
*
|
||||||
|
* @author zhuo
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
@Component
|
@Component
|
||||||
public interface IdGeneratorDao {
|
public interface IdGeneratorDao extends BaseMapper<IdGeneratorEntity> {
|
||||||
|
|
||||||
List<IdGeneratorEntity> selectAll();
|
|
||||||
|
|
||||||
int replaceIdGeneratorRecord(@Param("generatorId") Integer generatorId,
|
|
||||||
@Param("year") int year,
|
|
||||||
@Param("month") int month,
|
|
||||||
@Param("day") int day,
|
|
||||||
@Param("lastNumber") Long lastNumber,
|
|
||||||
@Param("count") long count);
|
|
||||||
|
|
||||||
IdGeneratorRecordDTO selectHistoryLastNumber(@Param("generatorId") Integer generatorId,
|
|
||||||
@Param("year") int year,
|
|
||||||
@Param("month") int month,
|
|
||||||
@Param("day") int day);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id生成 dao
|
||||||
|
*
|
||||||
|
* @author zhuo
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
@Component
|
||||||
|
public interface IdGeneratorRecordDao extends BaseMapper<IdGeneratorRecordEntity> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询id最后生成记录
|
||||||
|
*
|
||||||
|
* @param generatorId
|
||||||
|
* @param timeFormat
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IdGeneratorRecordEntity selectHistoryLastNumber(@Param("generatorId") Integer generatorId, @Param("time") String timeFormat);
|
||||||
|
}
|
@ -13,15 +13,13 @@ import net.lab1024.smartadmin.service.common.enumeration.BaseEnum;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum IdGeneratorEnum implements BaseEnum {
|
public enum IdGeneratorEnum implements BaseEnum {
|
||||||
|
|
||||||
|
ORDER(1, "订单id"),
|
||||||
|
|
||||||
|
CONTRACT(2, "合同id"),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
private final String desc;
|
private final String desc;
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "IdGeneratorEnum{" + "id=" + value + ", keyName='" + desc + '\'' + '}';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.lab1024.smartadmin.service.module.support.idgenerator.constant;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import net.lab1024.smartadmin.service.common.constant.StringConst;
|
||||||
import net.lab1024.smartadmin.service.common.enumeration.BaseEnum;
|
import net.lab1024.smartadmin.service.common.enumeration.BaseEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,7 +16,7 @@ public enum IdGeneratorRuleTypeEnum implements BaseEnum {
|
|||||||
/**
|
/**
|
||||||
* 没有周期
|
* 没有周期
|
||||||
*/
|
*/
|
||||||
NO_CYCLE("", "没有周期"),
|
NO_CYCLE(StringConst.EMPTY_STR, "没有周期"),
|
||||||
/**
|
/**
|
||||||
* 年周期
|
* 年周期
|
||||||
*/
|
*/
|
||||||
|
@ -4,8 +4,9 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorRuleTypeEnum;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,22 +16,20 @@ import java.time.LocalDateTime;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("t_id_generator")
|
@TableName("t_id_generator")
|
||||||
public class IdGeneratorEntity implements Serializable {
|
public class IdGeneratorEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 5582354131134766548L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主键id
|
* 主键id
|
||||||
*
|
*
|
||||||
* @see net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum
|
* @see IdGeneratorEnum
|
||||||
*/
|
*/
|
||||||
@TableId(type = IdType.AUTO)
|
@TableId(type = IdType.INPUT)
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 英文key
|
* 业务
|
||||||
*/
|
*/
|
||||||
private String keyName;
|
private String businessName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前缀
|
* 前缀
|
||||||
@ -38,15 +37,17 @@ public class IdGeneratorEntity implements Serializable {
|
|||||||
private String prefix;
|
private String prefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最低补位长度
|
* 生成规则
|
||||||
*/
|
*
|
||||||
private Integer minLength;
|
* @see IdGeneratorRuleTypeEnum
|
||||||
|
|
||||||
/**
|
|
||||||
* 类型
|
|
||||||
*/
|
*/
|
||||||
private String ruleType;
|
private String ruleType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最低生成id长度
|
||||||
|
*/
|
||||||
|
private Integer minLength;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始值
|
* 初始值
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package net.lab1024.smartadmin.service.module.support.idgenerator.domain;
|
package net.lab1024.smartadmin.service.module.support.idgenerator.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@ -10,15 +13,15 @@ import java.time.LocalDateTime;
|
|||||||
* @Description:
|
* @Description:
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class IdGeneratorRecordDTO {
|
@TableName("t_id_generator_record")
|
||||||
|
public class IdGeneratorRecordEntity {
|
||||||
|
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
private Integer generatorId;
|
private Integer generatorId;
|
||||||
|
|
||||||
private Integer year;
|
private String time;
|
||||||
|
|
||||||
private Integer month;
|
|
||||||
|
|
||||||
private Integer day;
|
|
||||||
|
|
||||||
private Long lastNumber;
|
private Long lastNumber;
|
||||||
|
|
@ -1,28 +1,29 @@
|
|||||||
package net.lab1024.smartadmin.service.module.support.idgenerator.service;
|
package net.lab1024.smartadmin.service.module.support.idgenerator.service;
|
||||||
|
|
||||||
|
import com.google.common.collect.Interner;
|
||||||
|
import com.google.common.collect.Interners;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.lab1024.smartadmin.service.common.code.UnexpectedErrorCode;
|
|
||||||
import net.lab1024.smartadmin.service.common.code.UserErrorCode;
|
|
||||||
import net.lab1024.smartadmin.service.common.constant.RedisKeyConst;
|
|
||||||
import net.lab1024.smartadmin.service.common.domain.ResponseDTO;
|
|
||||||
import net.lab1024.smartadmin.service.common.exception.BusinessException;
|
import net.lab1024.smartadmin.service.common.exception.BusinessException;
|
||||||
import net.lab1024.smartadmin.service.common.util.SmartRandomUtil;
|
import net.lab1024.smartadmin.service.common.util.SmartRandomUtil;
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.IdGeneratorDao;
|
import net.lab1024.smartadmin.service.module.support.idgenerator.IdGeneratorDao;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.IdGeneratorRecordDao;
|
||||||
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.IdGeneratorRuleTypeEnum;
|
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.IdGeneratorEntity;
|
||||||
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordDTO;
|
import net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity;
|
||||||
import net.lab1024.smartadmin.service.third.SmartRedisService;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -34,28 +35,25 @@ import java.util.stream.Collectors;
|
|||||||
@Service
|
@Service
|
||||||
public class IdGeneratorService {
|
public class IdGeneratorService {
|
||||||
|
|
||||||
private static final int MAX_GET_LOCK_COUNT = 5;
|
private static final Interner<Integer> POOL = Interners.newWeakInterner();
|
||||||
|
|
||||||
private static final long SLEEP_MILLISECONDS = 500L;
|
|
||||||
|
|
||||||
private static volatile long lastSleepMilliSeconds = SLEEP_MILLISECONDS;
|
|
||||||
|
|
||||||
private ConcurrentHashMap<Integer, IdGeneratorEntity> idGeneratorMap;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IdGeneratorDao idGeneratorDao;
|
private IdGeneratorDao idGeneratorDao;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SmartRedisService redisService;
|
private IdGeneratorRecordDao idGeneratorRecordDao;
|
||||||
|
|
||||||
|
private Map<Integer, IdGeneratorEntity> idGeneratorMap;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
void init() {
|
public void init() {
|
||||||
List<IdGeneratorEntity> idGeneratorEntityList = idGeneratorDao.selectAll();
|
List<IdGeneratorEntity> idGeneratorEntityList = idGeneratorDao.selectList(null);
|
||||||
idGeneratorMap = idGeneratorEntityList.stream().collect(Collectors.toMap(IdGeneratorEntity::getId, Function.identity(), (x, y) -> y, ConcurrentHashMap::new));
|
idGeneratorMap = idGeneratorEntityList.stream().collect(Collectors.toMap(IdGeneratorEntity::getId, Function.identity()));
|
||||||
|
log.info("##################### init IdGenerator #####################");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* id 生成器
|
* id生成
|
||||||
*
|
*
|
||||||
* @param idGeneratorEnum 类型
|
* @param idGeneratorEnum 类型
|
||||||
* @return
|
* @return
|
||||||
@ -64,84 +62,78 @@ public class IdGeneratorService {
|
|||||||
int generatorId = idGeneratorEnum.getValue();
|
int generatorId = idGeneratorEnum.getValue();
|
||||||
IdGeneratorEntity idGeneratorEntity = this.idGeneratorMap.get(generatorId);
|
IdGeneratorEntity idGeneratorEntity = this.idGeneratorMap.get(generatorId);
|
||||||
if (null == idGeneratorEntity) {
|
if (null == idGeneratorEntity) {
|
||||||
throw new BusinessException("IdGenerator, 生成器 不存在 " + idGeneratorEnum.getDesc());
|
throw new BusinessException("IdGenerator生产业务不存在 " + idGeneratorEnum.getDesc());
|
||||||
|
}
|
||||||
|
// 校验生成规则
|
||||||
|
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)) {
|
||||||
String lockKey = RedisKeyConst.Support.ID_GENERATOR + idGeneratorEnum.getDesc();
|
// 获取最后一次生成记录
|
||||||
boolean lock = false;
|
boolean isFirst = false;
|
||||||
for (int i = 0; i < MAX_GET_LOCK_COUNT; i++) {
|
IdGeneratorRecordEntity recordEntity = idGeneratorRecordDao.selectHistoryLastNumber(generatorId, timeFormat);
|
||||||
try {
|
if (recordEntity == null) {
|
||||||
//60秒
|
recordEntity = new IdGeneratorRecordEntity();
|
||||||
lock = redisService.getLock(lockKey, 60 * 1000L);
|
recordEntity.setGeneratorId(generatorId);
|
||||||
if (lock) {
|
recordEntity.setTime(timeFormat);
|
||||||
break;
|
recordEntity.setLastNumber(startNumber);
|
||||||
}
|
recordEntity.setCount(1L);
|
||||||
Thread.sleep(Math.max(SLEEP_MILLISECONDS, lastSleepMilliSeconds));
|
idGeneratorRecordDao.insert(recordEntity);
|
||||||
} catch (Throwable e) {
|
|
||||||
log.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!lock) {
|
|
||||||
throw new BusinessException("IdGenerator, 生成器繁忙,无法处理: " + idGeneratorEnum.getDesc());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
isFirst = true;
|
||||||
long beginTime = System.currentTimeMillis();
|
|
||||||
LocalDateTime now = LocalDateTime.now();
|
|
||||||
int year = now.getYear();
|
|
||||||
int monthValue = now.getMonthValue();
|
|
||||||
int dayOfMonth = now.getDayOfMonth();
|
|
||||||
|
|
||||||
IdGeneratorRecordDTO generatorRecordDTO = idGeneratorDao.selectHistoryLastNumber(generatorId, year, monthValue, dayOfMonth);
|
|
||||||
if (generatorRecordDTO == null) {
|
|
||||||
generatorRecordDTO = new IdGeneratorRecordDTO();
|
|
||||||
generatorRecordDTO.setGeneratorId(generatorId);
|
|
||||||
generatorRecordDTO.setYear(year);
|
|
||||||
generatorRecordDTO.setMonth(monthValue);
|
|
||||||
generatorRecordDTO.setDay(dayOfMonth);
|
|
||||||
generatorRecordDTO.setLastNumber(idGeneratorEntity.getInitNumber());
|
|
||||||
generatorRecordDTO.setCount(0L);
|
|
||||||
generatorRecordDTO.setUpdateTime(now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Long lastNumber = generatorRecordDTO.getLastNumber();
|
// 没有循环 或 在同个循环周期内,起始值 = 上次id
|
||||||
IdGeneratorRuleTypeEnum ruleTypeEnum = this.getIdGeneratorRuleTypeEnum(idGeneratorEntity.getRuleType());
|
if (IdGeneratorRuleTypeEnum.NO_CYCLE == ruleTypeEnum || Objects.equals(recordEntity.getUpdateTime().format(timeFormatter), timeFormat)) {
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ruleTypeEnum.getValue());
|
startNumber = recordEntity.getLastNumber();
|
||||||
String nowFormat = now.format(formatter);
|
|
||||||
if (IdGeneratorRuleTypeEnum.YEAR_CYCLE == ruleTypeEnum || IdGeneratorRuleTypeEnum.MONTH_CYCLE == ruleTypeEnum || IdGeneratorRuleTypeEnum.DAY_CYCLE == ruleTypeEnum) {
|
|
||||||
if (!Objects.equals(generatorRecordDTO.getUpdateTime().format(formatter), nowFormat)) {
|
|
||||||
lastNumber = idGeneratorEntity.getInitNumber();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastNumber += SmartRandomUtil.nextInt(1, idGeneratorEntity.getStepRandomRange());
|
// 在范围内随机生成此次增加的数值 更新id生成记录
|
||||||
long count = generatorRecordDTO.getCount() + 1;
|
if (!isFirst) {
|
||||||
idGeneratorDao.replaceIdGeneratorRecord(generatorId, year, monthValue, dayOfMonth, lastNumber, count);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
// 格式化num 不足位数则补零
|
// 默认 最低长度 1
|
||||||
int minLength = idGeneratorEntity.getMinLength();
|
int minLength = NumberUtils.max(idGeneratorEntity.getMinLength(), 1);
|
||||||
minLength = minLength <= 0 ? 1 : minLength;
|
// id长度补位
|
||||||
// 补位
|
String finalId = String.format("%0" + minLength + "d", startNumber);
|
||||||
String finalId = String.format("%0" + minLength + "d", lastNumber);
|
if (null != timeFormat) {
|
||||||
String prefix = StringUtils.isBlank(idGeneratorEntity.getPrefix()) ? StringUtils.EMPTY : idGeneratorEntity.getPrefix();
|
finalId = timeFormat + finalId;
|
||||||
|
}
|
||||||
lastSleepMilliSeconds = System.currentTimeMillis() - beginTime + 100;
|
// 前缀
|
||||||
return prefix + nowFormat + finalId;
|
if (StringUtils.isNotBlank(idGeneratorEntity.getPrefix())) {
|
||||||
} catch (Throwable e) {
|
finalId = idGeneratorEntity.getPrefix() + finalId;
|
||||||
log.error(e.getMessage(), e);
|
}
|
||||||
throw e;
|
return finalId;
|
||||||
} finally {
|
|
||||||
redisService.unLock(lockKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询生成规则
|
||||||
|
*
|
||||||
|
* @param ruleType
|
||||||
|
* @return 没有则返回null
|
||||||
|
*/
|
||||||
private IdGeneratorRuleTypeEnum getIdGeneratorRuleTypeEnum(String ruleType) {
|
private IdGeneratorRuleTypeEnum getIdGeneratorRuleTypeEnum(String ruleType) {
|
||||||
for (IdGeneratorRuleTypeEnum en : IdGeneratorRuleTypeEnum.values()) {
|
return Arrays.stream(IdGeneratorRuleTypeEnum.values())
|
||||||
if (en.name().equalsIgnoreCase(ruleType)) {
|
.filter(e -> StringUtils.equalsIgnoreCase(e.name(), ruleType))
|
||||||
return en;
|
.findFirst().orElse(null);
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
<?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.IdGeneratorDao">
|
|
||||||
|
|
||||||
<!-- 查询上次id -->
|
|
||||||
<select id="selectAll" resultType="net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorEntity">
|
|
||||||
select * from t_id_generator
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectHistoryLastNumber" resultType="net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordDTO">
|
|
||||||
select * from t_id_generator_record
|
|
||||||
where generator_id = #{generatorId} and year=#{year} and month=#{month} and day=#{day}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<update id="replaceIdGeneratorRecord">
|
|
||||||
REPLACE INTO t_id_generator_record (generator_id, `year`, `month`, `day`, last_number,`count`)
|
|
||||||
values (#{generatorId}, #{year}, #{month}, #{day}, #{lastNumber},#{count})
|
|
||||||
</update>
|
|
||||||
|
|
||||||
|
|
||||||
</mapper>
|
|
@ -0,0 +1,31 @@
|
|||||||
|
<?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.IdGeneratorRecordDao">
|
||||||
|
|
||||||
|
<select id="selectHistoryLastNumber" resultType="net.lab1024.smartadmin.service.module.support.idgenerator.domain.IdGeneratorRecordEntity">
|
||||||
|
select * from t_id_generator_record
|
||||||
|
where generator_id = #{generatorId}
|
||||||
|
<if test="null != time">
|
||||||
|
and `time`= #{time}
|
||||||
|
</if>
|
||||||
|
ORDER BY id DESC LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<update id="replaceIdGeneratorRecord">
|
||||||
|
UPDATE t_id_generator_record
|
||||||
|
<set>
|
||||||
|
<if test="null != year">
|
||||||
|
and `year`= #{year}
|
||||||
|
</if>
|
||||||
|
<if test="null != month">
|
||||||
|
and `month`= #{month}
|
||||||
|
</if>
|
||||||
|
<if test="null != day">
|
||||||
|
and `day`= #{day}
|
||||||
|
</if>
|
||||||
|
</set>
|
||||||
|
where generator_id = #{generatorId}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
@ -0,0 +1,25 @@
|
|||||||
|
package net.lab1024.smartadmin.service;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||||
|
public class SmartAdminApplicationTest {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before() {
|
||||||
|
System.out.println("----------------------- 测试开始 -----------------------");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void after() {
|
||||||
|
System.out.println("----------------------- 测试结束 -----------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
|||||||
|
package net.lab1024.smartadmin.service.module.support.idgenerator.service;
|
||||||
|
|
||||||
|
import net.lab1024.smartadmin.service.SmartAdminApplicationTest;
|
||||||
|
import net.lab1024.smartadmin.service.module.support.idgenerator.constant.IdGeneratorEnum;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
class IdGeneratorServiceTest extends SmartAdminApplicationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IdGeneratorService generatorService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id 生成测试
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void generateTest() throws InterruptedException {
|
||||||
|
|
||||||
|
int thread = 10;
|
||||||
|
CountDownLatch countDownLatch = new CountDownLatch(thread);
|
||||||
|
|
||||||
|
Runnable task = () -> {
|
||||||
|
String id = generatorService.generate(IdGeneratorEnum.CONTRACT);
|
||||||
|
System.out.println(countDownLatch.getCount() + "生成id->" + id);
|
||||||
|
countDownLatch.countDown();
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < thread; i++) {
|
||||||
|
new Thread(task).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
countDownLatch.await();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user