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(); } } }