im.shs.tick.sequence.seq.impl.DefaultRangeSequence Maven / Gradle / Ivy
package im.shs.tick.sequence.seq.impl;
import im.shs.tick.core.Env;
import im.shs.tick.core.utils.SpringUtil;
import im.shs.tick.sequence.exception.SeqException;
import im.shs.tick.sequence.range.BizName;
import im.shs.tick.sequence.range.SeqRange;
import im.shs.tick.sequence.range.SeqRangeMgr;
import im.shs.tick.sequence.seq.RangeSequence;
import im.shs.tick.sequence.seq.format.GenerateNoFormat;
import im.shs.tick.core.utils.RandomType;
import im.shs.tick.core.utils.StringUtil;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 序列号区间生成器接口默认实现
* 根据biz name 自增
*/
public class DefaultRangeSequence implements RangeSequence {
private static Map seqRangeMap = new ConcurrentHashMap<>(8);
/**
* 获取区间是加一把独占锁防止资源冲突
*/
private final Lock lock = new ReentrantLock();
/**
* 序列号区间管理器
*/
private SeqRangeMgr seqRangeMgr;
/**
* 当前序列号区间
*/
private volatile SeqRange currentRange;
/**
* 需要获取区间的业务名称
*/
private BizName bizName;
/**
* 格式
*/
private GenerateNoFormat format;
/**
* 前缀
*/
private String bizPrefix;
/**
* 是否添加环境参数
*/
private boolean addEnv;
/**
* 添加随机数位数
*/
private int addRandom = 0;
@Override
public long nextValue() throws SeqException {
String name = bizName.create();
currentRange = seqRangeMap.get(name);
//当前区间不存在,重新获取一个区间
if (null == currentRange) {
lock.lock();
try {
if (null == currentRange) {
currentRange = seqRangeMgr.nextRange(name);
seqRangeMap.put(name, currentRange);
}
} finally {
lock.unlock();
}
}
//当value值为-1时,表明区间的序列号已经分配完,需要重新获取区间
long value = currentRange.getAndIncrement();
if (value == -1) {
lock.lock();
try {
for (; ; ) {
if (currentRange.isOver()) {
currentRange = seqRangeMgr.nextRange(name);
}
value = currentRange.getAndIncrement();
if (value == -1) {
continue;
}
break;
}
} finally {
lock.unlock();
}
}
if (value < 0) {
throw new SeqException("Sequence value overflow, value = " + value);
}
return value;
}
/**
* 下一个生成序号(带格式)
*
* @return
* @throws SeqException
*/
@Override
public String nextNo() throws SeqException {
StringBuilder noBuilder = new StringBuilder();
noBuilder.append(this.bizPrefix);
if (this.addEnv) {
Env profile = null;
try {
profile = SpringUtil.getActiveProfile();
} catch (Exception e) {
profile = Env.DEV;
}
switch (profile) {
case DEV:
noBuilder.append("1");
break;
case TEST:
noBuilder.append("2");
break;
case PROD:
noBuilder.append("3");
break;
default:
}
}
switch (this.format) {
case NONE:
break;
case DATE:
case DATETIME:
case DATETIME_MS:
case TIME:
noBuilder.append(this.format.getFmt());
default:
}
if (this.addRandom > 0) {
noBuilder.append(StringUtil.random(this.addRandom, RandomType.INT));
}
return noBuilder.append(String.format("%05d", nextValue())).toString();
}
@Override
public void setSeqRangeMgr(SeqRangeMgr seqRangeMgr) {
this.seqRangeMgr = seqRangeMgr;
}
@Override
public void setName(BizName name) {
this.bizName = name;
}
@Override
public void setFormat(GenerateNoFormat format) {
this.format = format;
}
@Override
public void setBizPrefix(String bizPrefix) {
this.bizPrefix = bizPrefix;
}
@Override
public void setAddEnv(boolean addEnv) {
this.addEnv = addEnv;
}
@Override
public void setAddRandom(int addRandom) {
this.addRandom = addRandom;
}
}