欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在SpringBoot中實(shí)現(xiàn)一個(gè)訂單號(hào)生成系統(tǒng)的示例代碼

 更新時(shí)間:2024年02月10日 07:49:38   作者:一只愛擼貓的程序猿  
在Spring Boot中設(shè)計(jì)一個(gè)訂單號(hào)生成系統(tǒng),主要考慮到生成的訂單號(hào)需要滿足的幾個(gè)要求:唯一性、可擴(kuò)展性、以及可能的業(yè)務(wù)相關(guān)性,本文給大家介紹了幾種常見的解決方案及相應(yīng)的示例代碼,需要的朋友可以參考下

1. UUID

最簡(jiǎn)單的方法是使用UUID生成唯一的訂單號(hào)。UUID(Universally Unique Identifier)是一種廣泛使用的標(biāo)識(shí)符,由128位組成,通常以32個(gè)十六進(jìn)制數(shù)字表示,分為五組,形式為8-4-4-4-12的字符串,例如123e4567-e89b-12d3-a456-426614174000。UUID全球唯一,實(shí)現(xiàn)簡(jiǎn)單,但缺點(diǎn)是UUID較長(zhǎng),不易記憶和存儲(chǔ)。

實(shí)例代碼

Java中生成UUID的示例代碼如下:

import java.util.UUID;

public class UUIDGenerator {

    public static String generateUUID() {
        // 生成一個(gè)UUID
        UUID uuid = UUID.randomUUID();
        
        // 將UUID轉(zhuǎn)換為字符串
        String uuidAsString = uuid.toString();
        
        // 返回UUID字符串
        return uuidAsString;
    }

    public static void main(String[] args) {
        String uuid = generateUUID();
        System.out.println("Generated UUID: " + uuid);
    }
}

2. 數(shù)據(jù)庫序列或自增ID

利用數(shù)據(jù)庫的序列(如PostgreSQL的SEQUENCE)或自增ID(如MySQL的AUTO_INCREMENT)生成唯一的訂單號(hào)。數(shù)據(jù)庫序列或自增ID是一種常見的生成唯一標(biāo)識(shí)符的方法,特別是在單體應(yīng)用或非分布式系統(tǒng)中。這種方法依賴于數(shù)據(jù)庫的內(nèi)置機(jī)制來保證每次插入新記錄時(shí)自動(dòng)產(chǎn)生一個(gè)唯一的標(biāo)識(shí)符,缺點(diǎn)是難以在分布式環(huán)境中維護(hù)唯一性。

// 假設(shè)使用JPA
@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    // 其他屬性
}

數(shù)據(jù)庫序列(如PostgreSQL的SEQUENCE)

CREATE SEQUENCE order_id_seq START WITH 1 INCREMENT BY 1;

CREATE TABLE orders (
    order_id bigint NOT NULL DEFAULT nextval('order_id_seq'),
    order_data text
);

自增ID(如MySQL的AUTO_INCREMENT)

CREATE TABLE orders (
    order_id INT AUTO_INCREMENT,
    order_data TEXT,
    PRIMARY KEY (order_id)
);

3. 時(shí)間戳+隨機(jī)數(shù)/序列

結(jié)合時(shí)間戳和隨機(jī)數(shù)(或自定義序列)生成訂單號(hào),以保證唯一性和可讀性??梢酝ㄟ^添加業(yè)務(wù)相關(guān)的前綴來增強(qiáng)業(yè)務(wù)相關(guān)性。

實(shí)例代碼

以下是一個(gè)簡(jiǎn)單的Java示例,展示了如何結(jié)合時(shí)間戳、隨機(jī)數(shù)和業(yè)務(wù)前綴生成訂單號(hào):

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;

public class OrderNumberGenerator {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
    private static final int RANDOM_NUM_BOUND = 10000; // 定義隨機(jī)數(shù)范圍

    public static String generateOrderNumber(String prefix) {
        // 生成時(shí)間戳部分
        String timestamp = dateFormat.format(new Date());
        
        // 生成隨機(jī)數(shù)部分
        int randomNumber = ThreadLocalRandom.current().nextInt(RANDOM_NUM_BOUND);
        
        // 組合成訂單號(hào)
        return prefix + timestamp + String.format("%04d", randomNumber);
    }

    public static void main(String[] args) {
        // 示例:生成訂單號(hào),假設(shè)業(yè)務(wù)前綴為"ORD"
        String orderNumber = generateOrderNumber("ORD");
        System.out.println("Generated Order Number: " + orderNumber);
    }
}

4. 分布式唯一ID生成方案

在分布式系統(tǒng)中,可以使用像Twitter的Snowflake算法生成唯一的ID。Snowflake算法可以生成一個(gè)64位的長(zhǎng)整數(shù),其中包含時(shí)間戳、數(shù)據(jù)中心ID、機(jī)器ID和序列號(hào),以確保生成的ID既唯一又有序。

Snowflake ID結(jié)構(gòu)

Snowflake生成的64位ID可以分為以下幾個(gè)部分:

  • 1位符號(hào)位:由于整數(shù)的最高位是符號(hào)位,且64位整數(shù)中的最高位為符號(hào)位,通常這一位為0,保證ID為正數(shù)。
  • 41位時(shí)間戳位:記錄時(shí)間戳的差值(相對(duì)于某個(gè)固定的時(shí)間點(diǎn)),單位到毫秒。41位時(shí)間戳可以使用69年。
  • 10位數(shù)據(jù)中心ID和機(jī)器ID:通常分為5位數(shù)據(jù)中心ID和5位機(jī)器ID,最多支持32個(gè)數(shù)據(jù)中心,每個(gè)數(shù)據(jù)中心最多支持32臺(tái)機(jī)器。
  • 12位序列號(hào):用來記錄同一毫秒內(nèi)生成的不同ID,12位序列號(hào)支持每個(gè)節(jié)點(diǎn)每毫秒產(chǎn)生4096個(gè)ID序號(hào)。

以下是一個(gè)簡(jiǎn)化的Snowflake算法實(shí)現(xiàn)示例:

public class SnowflakeIdGenerator {

    private long datacenterId; // 數(shù)據(jù)中心ID
    private long machineId;    // 機(jī)器ID
    private long sequence = 0L; // 序列號(hào)
    private long lastTimestamp = -1L; // 上一次時(shí)間戳

    private final long twepoch = 1288834974657L;
    private final long datacenterIdBits = 5L;
    private final long machineIdBits = 5L;
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    private final long maxMachineId = -1L ^ (-1L << machineIdBits);
    private final long sequenceBits = 12L;

    private final long machineIdShift = sequenceBits;
    private final long datacenterIdShift = sequenceBits + machineIdBits;
    private final long timestampLeftShift = sequenceBits + machineIdBits + datacenterIdBits;
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    public SnowflakeIdGenerator(long datacenterId, long machineId) {
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException("datacenterId can't be greater than %d or less than 0");
        }
        if (machineId > maxMachineId || machineId < 0) {
            throw new IllegalArgumentException("machineId can't be greater than %d or less than 0");
        }
        this.datacenterId = datacenterId;
        this.machineId = machineId;
    }

    public synchronized long nextId() {
        long timestamp = System.currentTimeMillis();

        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate id");
        }

        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        return ((timestamp - twepoch) << timestampLeftShift) |
                (datacenterId << datacenterIdShift) |
                (machineId << machineIdShift) |
                sequence;
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }
}

下面是對(duì)這段代碼的逐行解釋:

類定義和變量初始化

  • private long datacenterId; 定義數(shù)據(jù)中心ID。
  • private long machineId; 定義機(jī)器ID。
  • private long sequence = 0L; 序列號(hào),用于同一毫秒內(nèi)生成多個(gè)ID時(shí)區(qū)分這些ID。
  • private long lastTimestamp = -1L; 上一次生成ID的時(shí)間戳。

以下是Snowflake算法的一些關(guān)鍵參數(shù):

  • private final long twepoch = 1288834974657L; 系統(tǒng)的起始時(shí)間戳,這里是Snowflake算法的作者選擇的一個(gè)固定的時(shí)間點(diǎn)(2010-11-04 09:42:54.657 GMT)。
  • private final long datacenterIdBits = 5L; 數(shù)據(jù)中心ID所占的位數(shù)。
  • private final long machineIdBits = 5L; 機(jī)器ID所占的位數(shù)。
  • private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); 數(shù)據(jù)中心ID的最大值,這里通過位運(yùn)算計(jì)算得出。
  • private final long maxMachineId = -1L ^ (-1L << machineIdBits); 機(jī)器ID的最大值,同樣通過位運(yùn)算得出。
  • private final long sequenceBits = 12L; 序列號(hào)占用的位數(shù)。

以下是一些用于位運(yùn)算的參數(shù),用于計(jì)算最終的ID:

  • private final long machineIdShift = sequenceBits; 機(jī)器ID的偏移位數(shù)。
  • private final long datacenterIdShift = sequenceBits + machineIdBits; 數(shù)據(jù)中心ID的偏移位數(shù)。
  • private final long timestampLeftShift = sequenceBits + machineIdBits + datacenterIdBits; 時(shí)間戳的偏移位數(shù)。
  • private final long sequenceMask = -1L ^ (-1L << sequenceBits); 用于保證序列號(hào)在指定范圍內(nèi)循環(huán)。

構(gòu)造函數(shù)

  • 構(gòu)造函數(shù)SnowflakeIdGenerator(long datacenterId, long machineId)接收數(shù)據(jù)中心ID和機(jī)器ID作為參數(shù),并對(duì)這些參數(shù)進(jìn)行校驗(yàn),確保它們?cè)诤戏ǚ秶鷥?nèi)。

ID生成方法

  • public synchronized long nextId()是生成ID的核心方法,使用synchronized保證線程安全。
    • 首先獲取當(dāng)前時(shí)間戳。
    • 如果當(dāng)前時(shí)間戳小于上一次生成ID的時(shí)間戳,拋出異常,因?yàn)闀r(shí)鐘回?fù)軙?huì)導(dǎo)致ID重復(fù)。
    • 如果當(dāng)前時(shí)間戳等于上一次的時(shí)間戳(即同一毫秒內(nèi)),通過增加序列號(hào)生成不同的ID;如果序列號(hào)溢出(超過最大值),則等待到下一個(gè)毫秒。
    • 如果當(dāng)前時(shí)間戳大于上一次的時(shí)間戳,重置序列號(hào)為0。
    • 最后,將時(shí)間戳、數(shù)據(jù)中心ID、機(jī)器ID和序列號(hào)按照各自的偏移量左移,然后進(jìn)行位或運(yùn)算,組合成一個(gè)64位的ID。

輔助方法

  • private long tilNextMillis(long lastTimestamp)是一個(gè)輔助方法,用于在序列號(hào)溢出時(shí)等待直到下一個(gè)毫秒。

以上就是在SpringBoot中設(shè)計(jì)一個(gè)訂單號(hào)生成系統(tǒng)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot訂單號(hào)生成系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Maven工程引入依賴失敗Dependencies全部飄紅問題

    Maven工程引入依賴失敗Dependencies全部飄紅問題

    這篇文章主要介紹了Maven工程引入依賴失敗Dependencies全部飄紅問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java Date裝成英文String后,無法再轉(zhuǎn)回Date的解決方案

    java Date裝成英文String后,無法再轉(zhuǎn)回Date的解決方案

    本文介紹了java Date裝成英文String后,無法再轉(zhuǎn)回Date的解決方案。具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • SpringBoot中的@Conditional?注解的使用

    SpringBoot中的@Conditional?注解的使用

    @Conditional是Spring4新提供的注解,它的作用是按照一定的條件進(jìn)行判斷,滿足條件的才給容器注冊(cè)Bean,本文主要介紹了SpringBoot中的@Conditional?注解的使用
    2024-01-01
  • 二進(jìn)制中1的個(gè)數(shù)

    二進(jìn)制中1的個(gè)數(shù)

    這篇文章介紹了二進(jìn)制中1的個(gè)數(shù),有需要的朋友可以參考一下
    2013-09-09
  • 詳解Java中Hibernate的基本原理

    詳解Java中Hibernate的基本原理

    持久化是將程序數(shù)據(jù)在持久狀態(tài)和瞬時(shí)狀態(tài)間轉(zhuǎn)換的機(jī)制。JDBC就是一種持久化機(jī)制。文件IO也是一種持久化機(jī)制。下面通過本文給大家介紹Java中Hibernate的基本原理,需要的朋友參考下吧
    2017-09-09
  • 詳解IDEA下Gradle多模塊(項(xiàng)目)的構(gòu)建

    詳解IDEA下Gradle多模塊(項(xiàng)目)的構(gòu)建

    這篇文章主要介紹了詳解IDEA下Gradle多模塊(項(xiàng)目)的構(gòu)建,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01
  • spring boot 本地圖片不能加載(圖片路徑)的問題及解決方法

    spring boot 本地圖片不能加載(圖片路徑)的問題及解決方法

    這篇文章主要介紹了spring boot 本地圖片不能加載(圖片路徑)的問題,解決的辦法其實(shí)很簡(jiǎn)單,只要寫一個(gè)配置文件,也就是圖片位置的轉(zhuǎn)化器,原理是虛擬一個(gè)在服務(wù)器上的文件夾,與本地圖片的位置進(jìn)行匹配。需要的朋友可以參考下
    2018-04-04
  • SpringBoot+Vue中的Token續(xù)簽機(jī)制

    SpringBoot+Vue中的Token續(xù)簽機(jī)制

    本文主要介紹了SpringBoot+Vue中的Token續(xù)簽機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • Java設(shè)計(jì)模式中的建造者模式詳解

    Java設(shè)計(jì)模式中的建造者模式詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式中的建造者模式詳解,建造者模式使我們?nèi)粘9ぷ髦斜容^常見的一種設(shè)計(jì)模式,和工廠模式一樣屬于創(chuàng)建型設(shè)計(jì)模式,用于解耦對(duì)象創(chuàng)建和對(duì)象使用的邏輯,需要的朋友可以參考下
    2023-12-12
  • maven 指定version不生效的問題

    maven 指定version不生效的問題

    這篇文章主要介紹了maven 指定version不生效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評(píng)論