feat: 新增编码生成核心引擎

This commit is contained in:
zhouz
2026-07-15 17:08:40 +08:00
parent 24e407585f
commit ca8dfde35a
2 changed files with 138 additions and 0 deletions

View File

@@ -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);
}

View File

@@ -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;
}
}