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