feat: 新增编码生成核心引擎
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package cn.code.nl.module.base.service.codegen;
|
||||
|
||||
/**
|
||||
* 编码生成 Service 接口
|
||||
*
|
||||
* @author zhouz
|
||||
*/
|
||||
public interface CodeGenService {
|
||||
|
||||
/**
|
||||
* 根据规则编码生成编码字符串
|
||||
*
|
||||
* @param ruleCode 规则编码
|
||||
* @return 生成的编码
|
||||
*/
|
||||
String generate(String ruleCode);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package cn.code.nl.module.base.service.codegen;
|
||||
|
||||
import cn.code.nl.module.base.dal.dataobject.codegen.CodeRuleDO;
|
||||
import cn.code.nl.module.base.service.codegen.dto.DateSegment;
|
||||
import cn.code.nl.module.base.service.codegen.dto.PrefixSegment;
|
||||
import cn.code.nl.module.base.service.codegen.dto.SegmentConfig;
|
||||
import cn.code.nl.module.base.service.codegen.dto.SequenceSegment;
|
||||
import cn.code.nl.module.base.service.codegen.enums.LetterCaseEnum;
|
||||
import cn.code.nl.module.base.service.codegen.enums.SeqStrategyEnum;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.code.nl.module.base.enums.ErrorCodeConstants.CODE_GEN_LENGTH_EXCEED;
|
||||
|
||||
/**
|
||||
* 编码生成引擎实现类
|
||||
*
|
||||
* @author zhouz
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Validated
|
||||
public class CodeGenServiceImpl implements CodeGenService {
|
||||
|
||||
@Resource
|
||||
private CodeRuleService codeRuleService;
|
||||
|
||||
@Resource
|
||||
private SequenceAllocator sequenceAllocator;
|
||||
|
||||
@Override
|
||||
public String generate(String ruleCode) {
|
||||
// 1. 获取规则配置(带缓存)
|
||||
CodeRuleDO rule = codeRuleService.getRuleByCode(ruleCode);
|
||||
|
||||
// 2. 遍历分段配置,逐段生成
|
||||
List<SegmentConfig> segments = rule.getSegmentConfig();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < segments.size(); i++) {
|
||||
String segmentValue = buildSegment(rule, segments.get(i));
|
||||
sb.append(segmentValue);
|
||||
// 段之间加分隔符
|
||||
if (i < segments.size() - 1 && StrUtil.isNotBlank(rule.getSeparator())) {
|
||||
sb.append(rule.getSeparator());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 后处理
|
||||
return postProcess(sb.toString(), rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据段类型分发处理,生成段值
|
||||
*/
|
||||
private String buildSegment(CodeRuleDO rule, SegmentConfig segment) {
|
||||
return switch (segment.getType()) {
|
||||
case "PREFIX" -> buildPrefixSegment((PrefixSegment) segment);
|
||||
case "DATE" -> buildDateSegment((DateSegment) segment);
|
||||
case "SEQUENCE" -> buildSequenceSegment(rule, (SequenceSegment) segment);
|
||||
default -> throw new IllegalArgumentException("不支持的段类型: " + segment.getType());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成固定前缀段
|
||||
*/
|
||||
private String buildPrefixSegment(PrefixSegment segment) {
|
||||
return segment.getValue() != null ? segment.getValue() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成日期段
|
||||
*/
|
||||
private String buildDateSegment(DateSegment segment) {
|
||||
String format = StrUtil.isNotBlank(segment.getFormat())
|
||||
? segment.getFormat() : "yyyyMMdd";
|
||||
return LocalDate.now().format(DateTimeFormatter.ofPattern(format));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成流水序号段
|
||||
*/
|
||||
private String buildSequenceSegment(CodeRuleDO rule, SequenceSegment segment) {
|
||||
String strategy = rule.getSeqStrategy();
|
||||
if (SeqStrategyEnum.LOCK.getCode().equals(strategy)) {
|
||||
return sequenceAllocator.allocateByLock(rule.getId(), segment);
|
||||
}
|
||||
return sequenceAllocator.allocateBySegment(rule.getId(), segment);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后处理:大小写转换 + 总长度校验
|
||||
*/
|
||||
private String postProcess(String code, CodeRuleDO rule) {
|
||||
// 大小写转换
|
||||
if (rule.getLetterCase() != null && rule.getLetterCase() == LetterCaseEnum.UPPER.getCode()) {
|
||||
code = code.toUpperCase();
|
||||
} else if (rule.getLetterCase() != null && rule.getLetterCase() == LetterCaseEnum.LOWER.getCode()) {
|
||||
code = code.toLowerCase();
|
||||
}
|
||||
|
||||
// 总长度校验
|
||||
if (rule.getTotalLength() != null && rule.getTotalLength() > 0 && code.length() > rule.getTotalLength()) {
|
||||
log.error("生成的编码超出总长度限制,code={}, length={}, maxLength={}",
|
||||
code, code.length(), rule.getTotalLength());
|
||||
throw exception(CODE_GEN_LENGTH_EXCEED);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user