java 自定义自增_自定义全局自增ID生成器

本文介绍了如何设计一个自定义的ID生成器,以满足业务中具有特定规则(如“产品标志+时间+n位流水”)的ID需求。文章详细阐述了如何使用规则表达式、变量生成器接口和ID生成器工厂来实现这一功能,包括解析表达式、生成目标字符串和处理变量的方法。此外,还展示了如何根据业务规则初始化字段,并利用Redis的Lua脚本来保证ID的原子性。最后,作者指出该方案在并发环境下具有较高的生成速率,且仍有优化空间。
摘要由CSDN通过智能技术生成

看了网上很多生成自增ID的策略,最终给出的都是雪花算法,leaf算法。但是却没有满足咱们对于自定义生成规则的需求。

在业务上有一部分ID往往是有规则的,比如某个产品的订单号往往是“产品标志+时间+n位流水”,类似这样的订单规则,使用雪花算法是满足不了业务需求的,所以我们得设计一套自己的自定义ID生成器。

“产品标志+时间+n位流水”规则中,难点无非在于n位流水号的生成,因为这个流水号需要保证在多次请求中不会产生重复的订单号。

首先,咱们根据业务需求,先制定对应的规则表达式:

id:

generator:

expressions:

# 产品标志

TEST:

# 表达式,pid指的是产品标志

exp: "$(pid)$(yearMonthDayHms)$(id:6:0)"

# 字段名:初始值:最大值:最小数量:扩容数量:初始数量:增长步长

initFields: ["id"]

表达式对应的实体类:

@Data

@Configuration

@ConfigurationProperties(prefix = "id.generator")

public class IDExpressionProperties {

private Map expressions;

@Data

public static class SerialIdConfig {

// 表达式

private String exp;

// 初始化字段

private String[] initFields;

}

}

通过spring解析获得对应的IDExpressionProperties实体类,拿到咱们自定义的配置

通过规则表达式可以看出,类似“$(pid)”这样的表达式,咱们可以抽象成接口自定义生成。比如咱们定义一个VariableGenerator接口或者抽象类,遇到pid就从spring ioc容器中调用pidVariableGenerator这个Bean的生成方法获取pid的值。遇到yearMonthDayHms就调用yearMonthDayHmsVariableGenerator这个Bean的生成方法获取yearMonthDayHms指定的值。

@Configuration

public class SerialConfig {

@Autowired private IDExpressionProperties idExpressionProperties;

/**

** 咱们要创建一个ID工厂类,专门用来生成ID的类

** 使用方法:

** @Autowired

** private IDFactory idFactory;

** String id = idFactory.get("产品标志");

*/

@Bean(initMethod = "init")

public IDFactory serialIdFactory() {

return new IDFactory(idExpressionProperties.getExpressions());

}

}

变量生成器

import org.apache.commons.lang3.StringUtils;

/**

* 变量生成器

* @className VariableGenerator

* @date: 2021/2/18 下午2:53

* @description:

*/

public abstract class VariableGenerator {

public static final String COLON = ":";

/**

* apply是生成目标字符串的方法

*/

protected abstract String apply(ExpressionElement e, Expression expression);

/**

* apply的后置处理方法,默认处理字符串不足的情况下,补足对应的填充数据

*/

public String andThen(ExpressionElement e, Expression expression) {

String variableValue = apply(e, expression);

int count = e.getCount();

String fillStringValue = e.getFillStringValue();

if (StringUtils.isNotBlank(variableValue)) {

if (count > 0) {

variableValue = StringUtils.leftPad(variableValue, count, fillStringValue);

} else {

variableValue =

StringUtils.rightPad(variableValue, Math.abs(count), fillStringValue);

}

}

return variableValue;

}

}

ID生成器

初始化的时候根据表达式配置确定是哪些字段需要初始化,根据初始化字段调用指定的Bean执行初始化

通过get方法传入的参数key获取指定的规则表达式,根据指定的表达式调用对应的生成器Bean实例,调用指定的方法生成目标值,最后拼接出最终的ID

public class IDFactory {

// 变量生成器

@Autowired(required = false)

private Map variableGeneratorMap;

// 字段初始化生成器

@Autowired(required = false)

private Map initFieldGeneratorMap;

// 构造函数,参数是生成规则

public IDFactory(Map expressionMap) {

this.expressionMap = expressionMap;

}

// 实例化后执行

public void init() {

// 如果没有规则表达式,那么直接就结束

if (CollectionUti

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值