自定义编码生成

news2024/11/27 0:33:41

自定义自增编码规则生成

  • 需求场景
  • 开发需求
  • 需求实现
  • 其它

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

需求场景

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获取对应的规则)
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服务重启后,含有到期时间的数据失效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/460586.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ts定义对象类型Record<string, any>;和object、Object的区别

Record Record 是 TS 内置的一个高级类型&#xff0c;是通过映射类型的语法来生成索引类型的&#xff1a; type Record<K extends string | number | symbol, T> { [P in K]: T; } 比如传入 a | b 作为 key&#xff0c;1 作为 value&#xff0c;就可以生成这样索引类…

Linux安装tomcat以及 对tomcat服务的操作

目录 1、使用FinalShell自带的上传工具将jdk的二进制发布包上传到Linux 2、解压安装包&#xff08;解压到指定位置&#xff0c;-C后面指定位置即可&#xff09; 3、进入Tomcat的bin目录去启动服务&#xff08;两种方式&#xff09; 4、验证Tomcat启动是否成功 方式一&#…

你如何看待,“国内ChatGPT还没成熟,但ChatGPT的付费模式已经成熟了?”

作者&#xff1a;小傅哥 博客&#xff1a;https://bugstack.cn 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; 说来奇怪&#x1f914;&#xff0c;我们从0到1的事往往较少&#xff0c;但从1到100的嫁衣神功却很多也很快。就像 ChatGPT 还没有…

自有品牌与新兴渠道双轮驱动,丽人丽妆提速起航

2023年4月12日&#xff0c;上海市电子商务行业协会评选出上海市数字商务优秀企业&#xff0c;丽人丽妆凭借在数智化营销领域的专业能力&#xff0c;荣获“上海市数字商务优秀企业”称号。 此次获奖&#xff0c;也反映了丽人丽妆以科技赋能企业高效运营&#xff0c;已经取得突出…

Vue3技术8之Fragment、Suspense、Vue3中其他的改变

Vue3技术8 FragmentTeleport弹窗案例目录结构App.vueChild.vueSon.vueDialog.vue 总结 Suspense普通写法App.vueChild.vue 使用suspense之后App.vueChild.vue 不再自己调整网络低速Child.vueApp.vue 总结补充setup的一个知识点Suspense总结 Vue3中其他的改变全局API的转移其他改…

62 openEuler 22.03-LTS 搭建MySQL数据库服务器-管理数据库

文章目录 62 openEuler 22.03-LTS 搭建MySQL数据库服务器-管理数据库62.1 创建数据库示例 62.2 查看数据库示例 62.3 选择数据库示例 62.4 删除数据库示例 62.5 备份数据库示例 62.6 恢复数据库示例 62 openEuler 22.03-LTS 搭建MySQL数据库服务器-管理数据库 62.1 创建数据库…

一个全端通用的折叠面板,个性定制支持复杂表格

使用uniapp框架全端通用的折叠面板&#xff0c;下载地址见文末 介绍 这是一个全端通用的折叠面板组件&#xff0c;可以折叠/展开的内容区域&#xff0c;支持复杂的表格形式展示&#xff0c;简单的设置即可实现&#xff0c;节省效率必备。 插件含全部源码&#xff0c;可以给您…

Java初学篇——Java语言的发展,特性,基本配置

目录 ps&#xff1a; java的发展 java的特性 java技术体系平台 java的跨平台性 JDK 介绍 安装 Java程序的编译和运行 流程 程序基本框架 一些小知识 注释 常用的转义字符 需要注意的小问题 ps&#xff1a; java算是我第二门系统学习的语言&#xff0c;同时也是我以…

【神经网络】tensorflow实验7--回归问题

1. 实验目的 ①掌握一元线性回归模型的实现方法 ②掌握多元线性回归模型的实现方法 ③掌握三维数据可视化方法 2. 实验内容 ①使用TensorFlow建立一元线性回归模型&#xff0c;使用商品房销售数据训练模型&#xff0c;并使用训练好的模型预测房价 ②使用TensorFlow建立多元线…

SpringBoot 集成 FastDFS(附安装教程)

1、FastDFS 简介 FastDFS是用 c 语言编写的一款开源的分布式文件系统&#xff0c;它对文件进行管理&#xff0c;功能包括&#xff1a;文件存储、文件同步、文件访问&#xff08;文件上传、文件下载&#xff09;等&#xff0c;解决了大容量存储和负载均衡的问题。特别适合以文件…

Bindiff工具使用-[GDOUCTF 2023]L!s!

目录 题目&#xff1a; 学到的点&#xff1a; 题目&#xff1a; 打了GDOUCTF的比赛&#xff08;被暴打了hhh)&#xff0c;学到很多新东西,这里总结一下 Diff的文件是ida数据库文件&#xff0c;选择i64或者idb文件进行Diff 打开附件&#xff0c;有两个文件&#xff0c;一个…

【Git 入门教程】第二节、Git基础使用

Git是一个分布式版本控制系统&#xff0c;它可以帮助开发者更好地管理和维护代码。在本文中&#xff0c;我们将介绍Git的最基本操作&#xff0c;如安装Git、初始化仓库、添加文件、提交代码、查看记录等。 一、Git安装 1.下载 要使用Git&#xff0c;首先需要在计算机上安装G…

JavaWeb开发 —— 登录认证校验和异常处理

在 JavaWeb开发 —— SpringBootWeb综合案例 中我们通过实例部门管理以及员工管理中的详细操作。而这篇文章我们将会通过综合实例学习登录认证、登录校验以及异常处理的了解和掌握。 目录 一、基本登录功能 二、登录校验 1. 会话技术 1.1 客户端会话跟踪技术Cookie 1.2 …

iview render函数(vue render函数)

iview 的render函数就是vue的render函数&#xff0c;iview常用在表格里面自定义内容&#xff0c;下面来看render函数常用的配置&#xff1a; 1、 h是createdElement的简写&#xff0c;有3个参数&#xff1a; 语法&#xff1a;render:(h,params)>{} render:(h,params) >…

mulesoft MCIA 破釜沉舟备考 2023.04.25.24(易错题)

mulesoft MCIA 破釜沉舟备考 2023.04.25.24(易错题) 1. An insurance company is using a CIoudHub runtime plane.2. A mule application must periodically process a large dataset which varies from 6 GB lo 8 GB from a back-end database and write transform data lo…

LSTM简单介绍—然后使用LSTM对FashionMNIST数据集处理

文章目录 LSTM 简单介绍LSTM的基本结构LSTM的工作原理输入门遗忘门输出门细胞状态更新输出计算 总结代码实例 LSTM 简单介绍 在自然语言处理、语音识别等领域&#xff0c;长短时记忆网络 (Long Short-Term Memory, LSTM) 已经成为了常用的模型之一。本文将介绍 LSTM 的基本结构…

gpt在线使用-免费的 GPT在哪下载

免费的 GPT&#xff08;Generative Pre-trained Transformer&#xff09; 。现在您可以免费体验我们的 GPT 技术&#xff0c;来让您的业务或项目更加智能。 GPT 是一种基于最前沿的自然语言处理技术&#xff0c;它展现出了令人惊叹的预测能力和交互性能。我们的 GPT 是在世界顶…

警惕读书无用论,要知道一个人最可怕的就是精神世界的贫瘠和荒凉

孔乙已是鲁迅笔下人物&#xff0c;穷困流倒还穿着象征读书人的长衫&#xff0c;迁腐、麻木。最近&#xff0c;大家自我调佩是“当代孔乙己”&#xff0c;学历成为思想负担&#xff0c;找工作时高不成低不就。 一、社会对于学历和职业之间的关系认知是怎样的&#xff1f; 学历不…

Forefront GPT-4免费版:开启无限畅聊时代,乐享人工智能快感,无限制“白嫖”,还能和N多角色一起聊天?赶紧注册,再过些时间估计就要收费了

目录 前言注册登录方式应用体验聊天体验绘图体验 “是打算先免费后收费吗&#xff1f;”建议其它资料下载 前言 近期&#xff0c;人工智能技术迎来重大飞跃&#xff0c;OpenAI的ChatGPT等工具成为全球数亿人探索提高生产力和增强创造力的新方法。人们现在可以使用人工智能驱动…

绩效管理系统有哪些推荐?

绩效管理系统有哪些推荐&#xff1f;市面上的绩效管理系统五花八门&#xff0c;这就来给大家推荐几款优质的&#xff01; 一、如何选择绩效管理系统 在选择绩效管理系统之前&#xff0c;需要先考虑以下几个问题&#xff1a; 了解你的企业目标和需求&#xff1a;在选择绩效管…