package com.ruoyi.common.utils;
|
|
import com.ruoyi.common.utils.ip.IpUtils;
|
import org.apache.commons.lang3.StringUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
public class OrderNos {
|
|
public static final char PADCHAR = '0';
|
|
|
|
/**
|
* 长度24位全球唯一标识
|
*/
|
|
/**
|
* 统一不重复内部订单号
|
*
|
* @param systemCode
|
* 4字节系统编码
|
* @return 24字节不重复编码
|
*/
|
public static String oid(String systemCode) {
|
StringBuilder sb = new StringBuilder();
|
sb.append(padding(systemCode, 4));
|
sb.append(Did.getInstance().getId(20));
|
return sb.toString();
|
}
|
|
public static String oid() {
|
return oid("O001");
|
}
|
|
/**
|
* 获取分布式Id
|
*
|
* @return 默认20字符长度的数字不重复编码
|
*/
|
public static String getDid() {
|
return Did.getInstance().getId();
|
}
|
|
public static String getDid(int size) {
|
return Did.getInstance().getId(size);
|
}
|
|
public static String getDid(String prefix) {
|
return prefix + Did.getInstance().getId();
|
}
|
|
private static String padding(String text, int size) {
|
String txt = StringUtils.trimToEmpty(text);
|
if (StringUtils.length(txt) > size) {
|
txt = StringUtils.substring(txt, StringUtils.length(txt) - size);
|
}
|
return StringUtils.leftPad(txt, size, PADCHAR);
|
}
|
|
/**
|
* ID生成器
|
*
|
* 20字符长度 yyMMddHHmmss+3位本机IP末三位+5位随机数字
|
*
|
* @author zhangpu
|
*
|
*/
|
public static class Did {
|
private static final Logger logger = LoggerFactory.getLogger(OrderNos.class);
|
private static final int MIN_LENGTH = 19;
|
private static final int SEQU_MAX = 99999;
|
private static final int SEQU_19_MAX = 9999;
|
private volatile static long BASE = 0;
|
private AtomicLong sequence = new AtomicLong(0);
|
private String nodeFlag;
|
private Object nodeFlagLock = new Object();
|
private static Did did = new Did();
|
|
|
public static Did getInstance() {
|
return did;
|
}
|
|
/**
|
* 生产新Id
|
*
|
* @return
|
*/
|
public String getId() {
|
return getId(20);
|
}
|
|
public String getId(int size) {
|
if (size < MIN_LENGTH) {
|
throw new RuntimeException("did最小长度为" + MIN_LENGTH);
|
}
|
StringBuilder sb = new StringBuilder();
|
sb.append(DateUtils.dateTimeNow("yyMMddHHmmss"));
|
sb.append(getNodeFlag());
|
sb.append(getSequ(size-15));
|
return sb.toString();
|
}
|
|
public synchronized String getSequ(int size) {
|
long timeCount = System.currentTimeMillis() / 1000;
|
|
while (true) {
|
long now = sequence.get();
|
if (timeCount > now) {
|
// 已经过了本秒,则设置新的值
|
if (sequence.compareAndSet(now, timeCount)) {
|
break;
|
}
|
} else {
|
if (sequence.compareAndSet(now, now + 1)) {
|
timeCount = now + 1;
|
break;
|
}
|
}
|
}
|
int sn = (int) (timeCount % (size>=5?SEQU_MAX:SEQU_19_MAX));
|
return StringUtils.leftPad(String.valueOf(sn), size, '0');
|
}
|
|
private String getNodeFlag(){
|
if (this.nodeFlag == null) {
|
synchronized (Did.class){
|
if (this.nodeFlag==null){
|
this.nodeFlag = generateNodeFlag();
|
}
|
}
|
}
|
return this.nodeFlag;
|
}
|
|
/**
|
* 简单节点编码
|
*
|
* 逻辑:Ip地址后三位,便于快速知道是哪个节点
|
*
|
* @return
|
*/
|
private String generateNodeFlag() {
|
String ipPostfix = null;
|
try {
|
String ip = IpUtils.getFirstNoLoopbackIPV4Address();
|
ipPostfix = StringUtils.substringAfterLast(ip, ".");
|
} catch (Exception e) {
|
logger.warn("生产DID要素本机IP获取失败:" + e.getMessage());
|
}
|
return StringUtils.leftPad(ipPostfix, 3, "0");
|
}
|
|
private Did() {
|
super();
|
}
|
}
|
|
|
|
}
|