Gids voor UUID in Java

1. Overzicht

UUID (Universally Unique Identifier), ook bekend als GUID (Globally Unique Identifier) ​​vertegenwoordigt een 128-bits lange waarde die uniek is voor alle praktische doeleinden. De standaardweergave van de UUID maakt gebruik van hexadecimale cijfers (octetten):

123e4567-e89b-12d3-a456-556642440000

Een UUID bestaat uit hexadecimale cijfers (elk 4 tekens) samen met 4 "-" symbolen die zijn lengte gelijk aan 36 karakters.

De Nil UUID is een speciale vorm van UUID waarin alle bits op nul worden gezet.

In dit artikel zullen we de UUID klasse in Java. Eerst kijken we hoe we de klasse zelf kunnen gebruiken. Vervolgens kijken we naar de verschillende soorten UUID's en hoe we deze in Java kunnen genereren.

2. Het UUID Klasse

De UUID-klasse heeft één constructor:

UUID uuid = nieuwe UUID (long mostSignificant64Bits, long leastSignificant64Bits);

Als we deze constructor willen gebruiken, moeten we twee lange waarden opgeven. Het vereist echter dat we het bitpatroon voor de UUID zelf construeren.

Gemakshalve zijn er drie statische methoden om een ​​UUID te maken. Dit zijn:

UUID uuid = UUID.nameUUIDFromBytes (byte [] bytes); 

Deze methode maakt een versie 3 UUID van de opgegeven byte-array.

UUID uuid = UUID.randomUUID (); 

De willekeurigUUID () methode maakt een versie 4 UUID aan. Dit is de handigste manier om een ​​UUID aan te maken.

UUID uuid = UUID.fromString (String uuidHexDigitString); 

De derde statische methode retourneert een UUID-object op basis van de stringvoorstelling van een bepaalde UUID.

Laten we nu eens kijken hoe een UUID is opgebouwd.

3. Structuur

Laten we het voorbeeld UUID nemen:

123e4567-e89b-42d3-a456-556642440000 xxxxxxxx-xxxx-Bxxx-Axxx-xxxxxxxxxxxx

3.1. UUID-variant

EEN staat voor de variant die de layout van de UUID bepaalt. Alle andere bits in de UUID zijn afhankelijk van de instelling van de bits in het variantveld. De variant wordt bepaald door de 3 belangrijkste bits van A:

 MSB1 MSB2 MSB3 0 X X gereserveerd (0) 1 0 X huidige variant (2) 1 1 0 gereserveerd voor Microsoft (6) 1 1 1 gereserveerd voor toekomst (7)

De waarde van EEN in de genoemde UUID is ‘a '. Het binaire equivalent van ‘a '(= 10xx) toont de variant als 2.

3.2. UUID-versie

B vertegenwoordigt de versie. De versie in de genoemde UUID (waarde van B) is 4.

Java biedt methoden om een ​​variant en versie van UUID op te halen:

UUID uuid = UUID.randomUUID (); int variant = uuid.variant (); int versie = uuid.version ();

Dit zijn 5 verschillende versies voor variant 2 UUID's: Time Based (UUIDv1), DCE Security (UUIDv2), Name Based (UUIDv3 en UUIDv5), Random (UUIDv4).

Java biedt een implementatie voor de v3 en v4, maar biedt ook een constructeur voor het genereren van elk type UUID:

UUID uuid = nieuwe UUID (long mostSigBits, long leastSigBits);

4. De UUID-versies

4.1. Versie 1

UUID versie 1 is gebaseerd op de huidige tijdstempel, gemeten in eenheden van 100 nanoseconden vanaf 15 oktober 1582, samengevoegd met het MAC-adres van het apparaat waarop de UUID is aangemaakt.

Als privacy een probleem is, kan UUID-versie 1 als alternatief worden gegenereerd met een willekeurig 48-bits nummer in plaats van het MAC-adres.

In dit artikel zullen we dit alternatief bespreken. Eerst genereren we de 64 kleinste en meest significante bits als lange waarden:

privé statisch lang get64LeastSignificantBitsForVersion1 () {Willekeurig willekeurig = nieuw willekeurig (); lang random63BitLong = random.nextLong () & 0x3FFFFFFFFFFFFFFFL; lange variant3BitFlag = 0x8000000000000000L; return random63BitLong + variant3BitFlag; } privé statisch lang get64MostSignificantBitsForVersion1 () {LocalDateTime start = LocalDateTime.of (1582, 10, 15, 0, 0, 0); Duur duur = Duration.between (start, LocalDateTime.now ()); lange seconden = duration.getSeconds (); lange nanos = duur.getNano (); lange timeForUuidIn100Nanos = seconden * 10000000 + nanos * 100; long least12SignificatBitOfTime = (timeForUuidIn100Nanos & 0x000000000000FFFFL) >> 4; lange versie = 1 << 12; terugkeer (timeForUuidIn100Nanos & 0xFFFFFFFFFFFF0000L) + versie + least12SignificatBitOfTime; }

We kunnen deze twee waarden vervolgens doorgeven aan de constructor van de UUID:

openbare statische UUID generationType1UUID () {long most64SigBits = get64MostSignificantBitsForVersion1 (); long least64SigBits = get64LeastSignificantBitsForVersion1 (); retourneer nieuwe UUID (most64SigBits, least64SigBits); }

4.2. Versie 2

Versie 2 is gebaseerd op een tijdstempel en ook op het MAC-adres. RFC 4122 specificeert echter niet de exacte generatiedetails, daarom zullen we in dit artikel niet naar een implementatie kijken.

4.3. Versie 3 en 5

De UUID's worden gegenereerd met behulp van de hash van naamruimte en naam. De naamruimte-ID's zijn UUID's zoals Domain Name System (DNS), Object Identifiers (OID's), URL's, enz.

UUID = hash (NAMESPACE_IDENTIFIER + NAME)

Het enige verschil tussen UUIDv3 en UUIDv5 is het hash-algoritme - v3 gebruikt MD5 (128 bits) terwijl v5 SHA-1 (160 bits) gebruikt.

Simpel gezegd, we kappen de resulterende hash af tot 128 bits en vervangen vervolgens 4 bits voor de versie en 2 bits voor de variant.

Laten we type 3 UUID genereren:

byte [] nameSpaceBytes = bytesFromUUID (naamruimte); byte [] nameBytes = name.getBytes ("UTF-8"); byte [] resultaat = joinBytes (nameSpaceBytes, nameBytes); UUID uuid = UUID.nameUUIDFromBytes (resultaat);

Hier is het belangrijk op te merken dat de hex-string voor de naamruimte eerst moet worden geconverteerd naar een byte-array.

Java biedt niet de implementatie voor type 5. Controleer onze broncode-repository voor de UUIDv5.

4.4. Versie 4

De UUID v4-implementatie gebruikt willekeurige getallen als bron. De Java-implementatie is SecureRandom - die een onvoorspelbare waarde gebruikt als zaad om willekeurige getallen te genereren om de kans op botsingen te verkleinen.

Laten we versie 4 UUID genereren:

UUID uuid = UUID.randomUUID ();

Laten we een unieke sleutel genereren met ‘SHA-256 'en een willekeurige UUID:

MessageDigest salt = MessageDigest.getInstance ("SHA-256"); salt.update (UUID.randomUUID (). toString (). getBytes ("UTF-8")); String digest = bytesToHex (salt.digest ());

5. Conclusie

In dit artikel hebben we gezien hoe een UUID is opgebouwd, welke varianten en versies er zijn. We leerden voor welke versies Java een out-of-the-box implementatie biedt, en keken naar codevoorbeelden om de andere versies te genereren.

En, zoals altijd, is de broncode van de implementatie beschikbaar op Github.