1. Gambaran keseluruhan
UUID (Universally Unique Identifier), juga dikenali sebagai GUID (Globally Unique Identifier) mewakili nilai panjang 128-bit yang unik untuk semua tujuan praktikal . Perwakilan standard UUID menggunakan digit hex (oktet):
123e4567-e89b-12d3-a456-556642440000
UUID terdiri dari digit hex (masing-masing 4 huruf ) bersama dengan 4 simbol "-" yang panjangnya sama dengan 36 aksara .
Nil UUID adalah bentuk khas UUID di mana semua bit ditetapkan ke sifar.
Dalam artikel ini, kita akan melihat kelas UUID di Java. Pertama, kita akan melihat cara menggunakan kelas itu sendiri. Kemudian, kita akan melihat pelbagai jenis UUID dan bagaimana kita dapat menghasilkannya di Java.
2. Kelas UUID
Kelas UUID mempunyai satu pembina:
UUID uuid = new UUID(long mostSignificant64Bits, long leastSignificant64Bits);
Sekiranya kita mahu menggunakan konstruktor ini, kita perlu memberikan dua nilai panjang. Walau bagaimanapun, ia memerlukan kita membina corak bit untuk UUID sendiri.
Untuk kemudahan, terdapat tiga kaedah statik untuk membuat UUID. Ini adalah:
UUID uuid = UUID.nameUUIDFromBytes(byte[] bytes);
Kaedah ini membuat UUID versi 3 dari susunan bait yang diberikan.
UUID uuid = UUID.randomUUID();
Kaedah randomUUID () membuat UUID versi 4. Ini adalah kaedah paling senang untuk membuat UUID.
UUID uuid = UUID.fromString(String uuidHexDigitString);
Kaedah statik ketiga mengembalikan objek UUID yang diberi representasi rentetan dari UUID yang diberikan.
Sekarang mari kita lihat bagaimana UUID disusun.
3. Struktur
Mari ambil contoh UUID:
123e4567-e89b-42d3-a456-556642440000 xxxxxxxx-xxxx-Bxxx-Axxx-xxxxxxxxxxxx
3.1. Varian UUID
A mewakili varian yang menentukan susun atur UUID. Semua bit lain dalam UUID bergantung pada tetapan bit dalam bidang varian. Varian ditentukan oleh 3 bit A yang paling ketara:
MSB1 MSB2 MSB3 0 X X reserved (0) 1 0 X current variant (2) 1 1 0 reserved for Microsoft (6) 1 1 1 reserved for future (7)
Nilai A dalam UUID yang disebutkan adalah 'a'. Setara binari 'a' (= 10xx) menunjukkan varian sebagai 2.
3.2. Versi UUID
B mewakili versi. Versi dalam UUID yang disebutkan (nilai B ) adalah 4.
Java menyediakan kaedah untuk mendapatkan varian dan versi UUID:
UUID uuid = UUID.randomUUID(); int variant = uuid.variant(); int version = uuid.version();
Ini adalah 5 versi berbeza untuk varian 2 UUID: Berdasarkan Masa (UUIDv1), DCE Security (UUIDv2), Berdasarkan Nama (UUIDv3 dan UUIDv5), Rawak (UUIDv4).
Java menyediakan implementasi untuk v3 dan v4, tetapi juga menyediakan konstruktor untuk menghasilkan sebarang jenis UUID:
UUID uuid = new UUID(long mostSigBits, long leastSigBits);
4. Versi UUID
4.1. Versi 1
UUID versi 1 didasarkan pada cap waktu semasa, yang diukur dalam unit 100 nanodetik dari 15 Oktober 1582, disatukan dengan alamat MAC peranti tempat UUID dibuat.
Sekiranya privasi menjadi perhatian, UUID versi 1 boleh dihasilkan dengan nombor 48-bit rawak dan bukan alamat MAC.
Dalam artikel ini, kita akan alternatif ini. Pertama, kita akan menghasilkan 64 bit paling kecil dan paling penting sebagai nilai panjang:
private static long get64LeastSignificantBitsForVersion1() { Random random = new Random(); long random63BitLong = random.nextLong() & 0x3FFFFFFFFFFFFFFFL; long variant3BitFlag = 0x8000000000000000L; return random63BitLong + variant3BitFlag; } private static long get64MostSignificantBitsForVersion1() { LocalDateTime start = LocalDateTime.of(1582, 10, 15, 0, 0, 0); Duration duration = Duration.between(start, LocalDateTime.now()); long seconds = duration.getSeconds(); long nanos = duration.getNano(); long timeForUuidIn100Nanos = seconds * 10000000 + nanos * 100; long least12SignificatBitOfTime = (timeForUuidIn100Nanos & 0x000000000000FFFFL) >> 4; long version = 1 << 12; return (timeForUuidIn100Nanos & 0xFFFFFFFFFFFF0000L) + version + least12SignificatBitOfTime; }
Kami kemudian boleh menyampaikan dua nilai ini kepada pembangun UUID:
public static UUID generateType1UUID() { long most64SigBits = get64MostSignificantBitsForVersion1(); long least64SigBits = get64LeastSignificantBitsForVersion1(); return new UUID(most64SigBits, least64SigBits); }
4.2. Versi 2
Versi 2 berdasarkan cap waktu dan alamat MAC juga. Namun, RFC 4122 tidak menentukan perincian penjanaan yang tepat, oleh itu, kami tidak akan melihat implementasi dalam artikel ini.
4.3. Versi 3 & 5
UUID dihasilkan menggunakan hash ruang nama dan nama. Pengecam ruang nama adalah UUID seperti Sistem Nama Domain (DNS), Pengenal Objek (OID), URL, dll.
UUID = hash(NAMESPACE_IDENTIFIER + NAME)
Satu-satunya perbezaan antara UUIDv3 dan UUIDv5 adalah Hashing Algorithm - v3 menggunakan MD5 (128 bit) sementara v5 menggunakan SHA-1 (160 bit).
Ringkasnya, kami memotong hash yang dihasilkan menjadi 128-bit dan kemudian mengganti 4 bit untuk versi dan 2 bit untuk varian.
Mari buat UUID jenis 3:
byte[] nameSpaceBytes = bytesFromUUID(namespace); byte[] nameBytes = name.getBytes("UTF-8"); byte[] result = joinBytes(nameSpaceBytes, nameBytes); UUID uuid = UUID.nameUUIDFromBytes(result);
Di sini, penting untuk diperhatikan bahawa rentetan heks untuk ruang nama terlebih dahulu perlu ditukar menjadi tatasusunan bait.
Java tidak menyediakan pelaksanaan untuk jenis 5. Periksa repositori kod sumber kami untuk UUIDv5.
4.4. Versi 4
Pelaksanaan UUID v4 menggunakan nombor rawak sebagai sumbernya. Pelaksanaan Java adalah SecureRandom - yang menggunakan nilai yang tidak dapat diramalkan sebagai benih untuk menghasilkan nombor rawak untuk mengurangkan kemungkinan perlanggaran.
Mari buat UUID versi 4:
UUID uuid = UUID.randomUUID();
Mari buat kunci unik menggunakan 'SHA-256' dan UUID rawak:
MessageDigest salt = MessageDigest.getInstance("SHA-256"); salt.update(UUID.randomUUID().toString().getBytes("UTF-8")); String digest = bytesToHex(salt.digest());
5. Kesimpulan
Dalam artikel ini, kami melihat bagaimana UUID disusun, mana varian dan versi yang ada. Kami belajar untuk versi mana Java menyediakan pelaksanaan di luar kotak, dan melihat contoh kod untuk menghasilkan versi lain.
Dan, seperti biasa, kod sumber pelaksanaan tersedia di Github.