自定义编码生成

自定义自增编码规则生成

    在项目中遇到的需求,这里记录下实现。以下仅供参考,代码有所删减,但核心代码在

需求场景

1.需要多个编号规则,不同的场景使用的编码规则不同。
2.编码需要可自定义灵活选择配置,序号按自增处理。
3.编码规则包含时间,前缀,后缀,自增序列位数,分隔符等。

开发需求

1.创建一个表,用来维护编号规则,每个规则都有一个type,用来区分规则的使用场景,type唯一。数据如下所示
在这里插入图片描述

2.使用redis,用来存储自增序数(本文示例中,核心代码是设置redis的自增和时间那一部分代码

需求实现

1.数据库设计

表名 code_rules
字段说明
rule_name规则名称
prefix前缀
serial_type序号规则
serial_digitis自增序列位数
suffix后缀
rule_separator分隔符
rule_type编号类型(用于区分使用场景,不同的场景通过type获取对应的规则)

数据示例:

rule_nameprefixserial_typeserial_digitissuffixrule_separator rule_type
商混单位编号JCyyyyMMdd 3 sh_type

2.SequenceCodeService.java

public interface SequenceCodeService {


    /**
     * 根据codeRulesId获取编码规则
     * @param codeRulesId
     * @return
     */
    public String getCodeByCodeRulesId(String codeRulesId);


    /** 
    * @Description: 根据规则类型获取编码
     * @param ruleType
    * @return: {@link java.lang.String}
    * @Author: lvyq
    * @Date: 2022/9/21 17:04
    */
    public String getCodeByRuleType(String ruleType);

}

3.SequenceCodeServiceImpl.java(核心代码)

@Service
public class SequenceCodeServiceImpl implements SequenceCodeService  {
    public static Logger logger = LoggerFactory.getLogger(SequenceCodeService.class);

    @Resource
    public RedisTemplate redisTemplate;

    @Resource
    public CodeRulesMapper codeRulesMapper;

    private static final String CODE_PUB="code:pub:";


    /** 
    * @Description: 根据规则类型获取编码
     * @param ruleType
    * @return: {@link java.lang.String}
    * @Author: lvyq
    * @Date: 2022/9/21 17:04
    */
    @Override
    public String getCodeByRuleType(String ruleType) {
        String codeRulesId =codeRulesMapper.getIdByRuleType(ruleType);
        if (StringUtils.isEmpty(codeRulesId)){
                throw new RuntimeException(ruleType+"编码规则不存在");
        }
        return getCodeByCodeRulesId(codeRulesId);
    }



    /**
     * 根据codeRulesId获取编号
     * @param codeRulesId
     * @return
     */
    @Override
    public String getCodeByCodeRulesId(String codeRulesId) {
        CodeRules codeRules = codeRulesMapper.selectById(codeRulesId);
        //以codeRulesId为key进行存储
        if (codeRules!=null){
            return getCode(codeRules);
        }else {
            throw new RuntimeException("当前编码规则不存在");
        }

    }

    /**
     * 获取编码
     * @param codeRules
     * @return
     */
    public String getCode(CodeRules codeRules) {
        //前缀
        String prefix = codeRules.getPrefix();
        //规则类型-时间规则
        String serialType=codeRules.getSerialType();
        //后缀
        String suffix = codeRules.getSuffix();
        //自增序列位数
        String serialDigitis = codeRules.getSerialDigitis();
        //分隔符
        String ruleSeparator = codeRules.getRuleSeparator();
        if (ruleSeparator==null){ruleSeparator="";}
        if (prefix==null){prefix="";}
        if (suffix==null){suffix="";}
        if (StringUtils.isNotEmpty(serialType)){
            return getCodeNo(CODE_PUB+codeRules.getRuleType()+":"+codeRules.getId(),serialType,prefix,suffix,serialDigitis,ruleSeparator);
        }else {
            //无规则,无过期
            return geOtherNo(CODE_PUB+codeRules.getRuleType()+":"+codeRules.getId(),prefix,suffix,serialDigitis,ruleSeparator);
        }
    }

    /**
     * 含规则
     * @param key
     * @param serialType
     * @param prefix
     * @param suffix
     * @param serialDigitis
     * @param ruleSeparator
     * @return
     */
    private String getCodeNo(String key, String serialType, String prefix, String suffix, String serialDigitis, String ruleSeparator) {
        Calendar calendar = Calendar.getInstance();
        //按年
        if (!serialType.contains("MM") ){
            //设置过期时间,这里设置为当年12月31日的23:59:59
            SimpleDateFormat format = new SimpleDateFormat("yyyy");
            calendar.set(Integer.valueOf(format.format(new Date())),11,31,23,59,59);
        }else if (serialType.contains("dd")){
            //按日,设置时间,到当日23:59:59过期
            calendar.set(Calendar.HOUR_OF_DAY, 23);
            calendar.set(Calendar.MINUTE, 59);
            calendar.set(Calendar.SECOND, 59);
            calendar.set(Calendar.MILLISECOND, 999);
        }else if (serialType.contains("MM") && !serialType.contains("dd")){
            //按月。设置时间,当月过期
            SimpleDateFormat format = new SimpleDateFormat("MM");
            calendar.set(Calendar.MONTH,Integer.valueOf(format.format(new Date())));
            calendar.set(Calendar.DATE,0);//表示取当前月份的前一天
            calendar.set(Calendar.HOUR_OF_DAY, 23);
            calendar.set(Calendar.MINUTE, 59);
            calendar.set(Calendar.SECOND, 59);
            calendar.set(Calendar.MILLISECOND, 999);
        }
        Date expireDate = calendar.getTime();
        Long seq = generate(redisTemplate, key, expireDate);
        String sequence="";
        //生成x位序列号,如果seq不够x位,seq前面补0,
        if (StringUtils.isNotEmpty(serialDigitis)){
            sequence = StringUtils.leftPad(seq.toString(), Integer.valueOf(serialDigitis), "0");
        }else {
            //无补位自增
            sequence=seq.toString();
        }
        //规则日期生成
        SimpleDateFormat format = new SimpleDateFormat(serialType);
        //拼接业务编号
        String seqNo = prefix + ruleSeparator+format.format(new Date()) +ruleSeparator+ sequence+ruleSeparator+suffix;
        if (seqNo.endsWith(ruleSeparator) && StringUtils.isNotEmpty(ruleSeparator)){
            seqNo=seqNo.substring(0,seqNo.length()-ruleSeparator.length());
        }
        if (seqNo.startsWith(ruleSeparator) && StringUtils.isNotEmpty(ruleSeparator)){
            seqNo=seqNo.substring(ruleSeparator.length());
        }
        logger.info("KEY:{}, 序列号生成:{}, 过期时间:{}", key, seqNo, String.format("%tF %tT ", expireDate, expireDate));
        return seqNo;
    }




    /**
     * 无规则
     * @param prefix
     * @param suffix
     * @param serialDigitis
     * @param ruleSeparator
     * @return
     */
    public String geOtherNo(String key,String prefix,String suffix,String serialDigitis,String ruleSeparator) {
        RedisAtomicLong counter = new RedisAtomicLong(key,redisTemplate.getConnectionFactory());
        Long seq=counter.incrementAndGet();
        String sequence="";
        //生成x位序列号,如果seq不够x位,seq前面补0,
        if (StringUtils.isNotEmpty(serialDigitis)){
            sequence = StringUtils.leftPad(seq.toString(), Integer.valueOf(serialDigitis), "0");
        }else {
            //无补位自增
            sequence=seq.toString();
        }
        //拼接业务编号 前缀+分割符+序号+分割+后缀
        String seqNo=prefix+ruleSeparator+sequence+ruleSeparator+suffix;
        if (seqNo.endsWith(ruleSeparator) && StringUtils.isNotEmpty(ruleSeparator)){
            seqNo=seqNo.substring(0,seqNo.length()-ruleSeparator.length());
        }
        if (seqNo.startsWith(ruleSeparator) && StringUtils.isNotEmpty(ruleSeparator)){
            seqNo=seqNo.substring(ruleSeparator.length());
        }
        logger.info("KEY:{}, 序列号生成:{}", key, seqNo);
        return seqNo;
    }


    /**
     * @param key
     * @param expireTime <i>过期时间</i>
     * @return
     */
    public static long generate(RedisTemplate<?,?> redisTemplate,String key,Date expireTime) {
        RedisAtomicLong counter = new RedisAtomicLong(key,redisTemplate.getConnectionFactory());
        //设置过期时间
        counter.expireAt(expireTime);
        return counter.incrementAndGet();
    }
}
说明codeRulesMapper 的两个查询比较简单,就不贴了,也可以根据type直接查询获取对应的规则。

4.使用
在使用的地方注入

    @Resource
    private SequenceCodeService sequenceCodeService;

并使用

    String code =sequenceCodeService.getCodeByRuleType(RuleCodeConstant.SHDW);

5 RuleCodeConstant.java
常量类,放的表中的type。

public class RuleCodeConstant {
    /**
     * 商混单位
     */
    public static final String SHDW ="sh_type";

}

其它

1.修改规则
在这里插入图片描述
2.redis配置修改
修改redis.conf

appendonly no 

改为

appendonly yes

防止redis服务重启后,含有到期时间的数据失效。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要喷香水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值