0
点赞
收藏
分享

微信扫一扫

订单号生成器

荷一居茶生活 2024-11-06 阅读 37

import com.hz.tgb.common.RandomUtil;
import com.hz.tgb.common.ValidateUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 订单号生成器
 * 订单号生成工具类 - Yaphis的个人页面
 */
public class OrderGenerater {

    private static final Logger LOG = LoggerFactory.getLogger(OrderGenerater.class);

    private volatile static int serialNo = 0;

    private static final String FORMATSTRING = "yyMMddHHmmssSSS";

    /**
     * 使用公平锁防止饥饿
     */
    private static final Lock lock = new ReentrantLock(true);

    private static final int TIMEOUTSECODES = 3;
    
    private OrderGenerater() {
		// 私有类构造方法
	}

    /**
     * 生成订单号,生成规则:时间戳 + 机器IP最后两位 + 2位随机数 + 两位自增序列 <br>
     * 采用可重入锁减小锁持有的粒度,提高系统在高并发情况下的性能
     * 
     * @return
     */
    public static String generateOrder() {
        StringBuilder builder = new StringBuilder();
        builder.append(getDateTime(FORMATSTRING))
               .append(getNumberFromMechine())
               .append(getRandomNum())
               .append(getIncrement());
        return builder.toString();
    }

    /**
     * 生成订单号,生成规则:前缀 + 剩余长度(UUID)
     *
      * @param prefix 前缀
     * @param len 订单号总长度
     * @return
     */
    public static String generateOrder(String prefix, int len) {
        StringBuilder builder = new StringBuilder(prefix);
        builder.append(RandomUtil.getRandomUuidStr(len - prefix.length()));
        return builder.toString();
    }

    /**
     * 获取系统当前时间
     * 
     * @param formatStr
     * @return
     */
    private static String getDateTime(String formatStr) {
        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        return format.format(new Date());
    }

    /**
     * 获取自增序列
     * 
     * @return
     */
    private static String getIncrement() {
        int tempSerialNo = 0;
        try {
            if (lock.tryLock(TIMEOUTSECODES, TimeUnit.SECONDS)) {
                if (serialNo >= 99) {
                    serialNo = 0;
                } else {
                    serialNo = serialNo + 1;
                }
                tempSerialNo = serialNo;
            } else {
                // 指定时间内没有获取到锁,存在激烈的锁竞争或者性能问题,直接报错
                LOG.error("can not get lock in:{} seconds!", TIMEOUTSECODES);
                throw new RuntimeException("generateOrder can not get lock!");
            }
        } catch (Exception e) {
            LOG.error("tryLock throws Exception:", e);
            throw new RuntimeException("tryLock throws Exception!");
        } finally {
            lock.unlock();
        }
        if (tempSerialNo < 10) {
            return "0" + tempSerialNo;
        } else {
            return "" + tempSerialNo;
        }
    }

    /**
     * 返回两位随机整数
     * 
     * @return
     */
    private static String getRandomNum() {
        int num = new Random(System.nanoTime()).nextInt(100);
        if (num < 10) {
            return "0" + num;
        } else {
            return num + "";
        }
    }

    /**
     * 获取IP的最后两位数字
     *
     * @return
     */
    private static String getNumberFromMechine() {
        String hostName = "";
        try {
            hostName = getHostName();
        } catch (Exception e) {
            LOG.error("getHostName throws Exception:", e);
        }
        if (StringUtils.isBlank(hostName) || hostName.length() < 2) {
            // 机器名为空
            LOG.warn("hostName:{} is illegal!return randomNum!", hostName);
            return getRandomNum();
        } else {
            // 得到了机器名
            String number = hostName.substring(hostName.length() - 2, hostName.length());
            if (ValidateUtil.isPoInteger(number)) {
                return number;
            } else {
                LOG.warn("number:{} is not number!return randomNum!", number);
                return getRandomNum();
            }
        }
    }

    /**
     * 获取本机IP
     *
     * @return
     */
    private static String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            LOG.error("getLocalHost throws UnknownHostException:", e);
        }
        return "";
    }
}

举报

相关推荐

0 条评论