Java中將UUID存儲(chǔ)為Base64字符串的方法實(shí)現(xiàn)
概述
使用 Base64 編碼來對(duì) UUID(Universally Unique Identifiers) 存儲(chǔ)在一些特定的場(chǎng)合被廣泛的使用。使用 Base64 對(duì)比直接使用 UUID 進(jìn)行存儲(chǔ)來說能夠更多的節(jié)約空間。

本文對(duì)這方面的相關(guān)內(nèi)容和問題進(jìn)行探討。
在這里,使用 Base64 來對(duì) UUID 進(jìn)行存儲(chǔ),涉及到一些類型的轉(zhuǎn)換的。Base64 是編碼算法,在實(shí)際使用的時(shí)候我們更多會(huì)用到 Byte 數(shù)組的方式來進(jìn)行編碼的。這樣我們就比較明確在對(duì)其進(jìn)行 Base64 轉(zhuǎn)換之前,我們應(yīng)該要先干什么了。
使用 byte[]和 Base64.Encoder
Base64.Encoder 就能夠提供 byte[] 的 Base64 編碼了,我們先使用這個(gè)最簡(jiǎn)單的方式來進(jìn)行處理。
編碼
首先我們需要給出的 UUID 位中創(chuàng)建出我們需要的 byte 數(shù)組。
我們先獲得 UUID 的 most significant bits 和 least significant bits,然后放入我們 byte 數(shù)組中的 0-7 和 8-15 的位置。
程序代碼如下:
private byte[] convertToByteArray(UUID uuid) {
byte[] result = new byte[16];
long mostSignificantBits = uuid.getMostSignificantBits();
fillByteArray(0, 8, result, mostSignificantBits);
long leastSignificantBits = uuid.getLeastSignificantBits();
fillByteArray(8, 16, result, leastSignificantBits);
return result;
}
上面的代碼中還有一個(gè) fillByteArray 方法,這個(gè)方法,這個(gè)方法將會(huì)把我們的 bit 存如 byte array 數(shù)組中,同時(shí)還會(huì)移動(dòng) 8 位。
方法的代碼如下:
void fillByteArray(int start, int end, byte[] result, long bits) {
for (int i = start; i < end; i++) {
int shift = i * 8;
result[i] = (byte) ((int) (255L & bits >> shift));
}
}
當(dāng)我們獲得 byte 數(shù)組后,我們就可以調(diào)用 JDK 的 Base64.Encoder 方法來直接進(jìn)行編碼了成一個(gè) Base64 加密字符串了。
完整的測(cè)試代碼如下:
UUID originalUUID = UUID.fromString("cc5f93f7-8cf1-4a51-83c6-e740313a0c6c");
@Test
void givenEncodedString_whenDecodingUsingBase64Decoder_thenGiveExpectedUUID() {
String expectedEncodedString = "UUrxjPeTX8xsDDoxQOfGgw==";
byte[] uuidBytes = convertToByteArray(originalUUID);
String encodedUUID = Base64.getEncoder().encodeToString(uuidBytes);
assertEquals(expectedEncodedString, encodedUUID);
}
解碼
把我們獲得的 UUID Base64 字符串進(jìn)行解碼,我們可以使用完全相反的方法:
@Test
public void givenEncodedString_whenDecodingUsingBase64Decoder_thenGiveExpectedUUID() {
String expectedEncodedString = "UUrxjPeTX8xsDDoxQOfGgw==";
byte[] decodedBytes = Base64.getDecoder().decode(expectedEncodedString);
UUID uuid = convertToUUID(decodedBytes);
}
首先把 Base64 字符串解碼成 Byte 數(shù)組,然后調(diào)用我們的轉(zhuǎn)換方法,把我們獲得 byte 數(shù)組轉(zhuǎn)換成為 UUID 對(duì)象。
UUID convertToUUID(byte[] src) {
long mostSignificantBits = convertBytesToLong(src, 0);
long leastSignificantBits = convertBytesToLong(src, 8);
return new UUID(mostSignificantBits, leastSignificantBits);
}
在上面的方法中,我們分別對(duì) UUID 中需要使用的 most significant bits 和 less significant bits 分別進(jìn)行轉(zhuǎn)換,然后再組合在一起。
轉(zhuǎn)換的方法如下:
long convertBytesToLong(byte[] uuidBytes, int start) {
long result = 0;
for(int i = 0; i < 8; i++) {
int shift = i * 8;
long bits = (255L & (long)uuidBytes[i + start]) << shift;
long mask = 255L << shift;
result = result & ~mask | bits;
}
return result;
}
通過上面的測(cè)試代碼,可以看到代碼的轉(zhuǎn)換都順利完成了。
使用 ByteBuffer 和 Base64.getUrlEncoder()
如果我們還使用 JDK 的 API 的話,我們還可以把上面的代碼進(jìn)行一些簡(jiǎn)化。
編碼
通過使用 ByteBuffer,我們可以使用非常簡(jiǎn)單的下面 2 行代碼把 UUID 的 bit 轉(zhuǎn)換為 buffer wrapping 數(shù)組。
ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); byteBuffer.putLong(originalUUID.getMostSignificantBits()); byteBuffer.putLong(originalUUID.getLeastSignificantBits());
當(dāng)程序執(zhí)行完上面的 2 行代碼后,我們將會(huì)獲得 一個(gè) ByteBuffer 對(duì)象,這個(gè)對(duì)象中存儲(chǔ)的是 UUID 轉(zhuǎn)換過來的數(shù)據(jù)。
針對(duì)編碼,我們就可以使用 Base64.getUrlEncoder() 方法,這個(gè)方法的參數(shù)我們可以使用 ByteBuffer 轉(zhuǎn)換成 array 就可以了,因?yàn)?ByteBuffer 轉(zhuǎn)換成 Array 是返回 Array 的。
String encodedUUID = Base64.getUrlEncoder().encodeToString(byteBuffer.array());
針對(duì)上面代碼的修改,我們只需要下面簡(jiǎn)單的幾行代碼就可以完成 UUID 到 Base64 的轉(zhuǎn)換。
@Test
public void givenUUID_whenEncodingUsingByteBufferAndBase64UrlEncoder_thenGiveExpectedEncodedString() {
String expectedEncodedString = "zF-T94zxSlGDxudAMToMbA==";
ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]);
byteBuffer.putLong(originalUUID.getMostSignificantBits());
byteBuffer.putLong(originalUUID.getLeastSignificantBits());
String encodedUUID = Base64.getUrlEncoder().encodeToString(byteBuffer.array());
assertEquals(expectedEncodedString, encodedUUID);
}
解碼
解碼就使用 Base64.UrlDecoder() 即可,Base64.UrlDecoder() 的解碼結(jié)果為 byte 數(shù)組,所以我們還需要用 ByteBuffer.wrap 把解碼后的數(shù)組包裝成 ByteBuffer 對(duì)象。
@Test
void givenEncodedString_whenDecodingUsingByteBufferAndBase64UrlDecoder_thenGiveExpectedUUID() {
String expectedEncodedString = "zF-T94zxSlGDxudAMToMbA==";
byte[] decodedBytes = Base64.getUrlDecoder().decode(expectedEncodedString);
ByteBuffer byteBuffer = ByteBuffer.wrap(decodedBytes);
long mostSignificantBits = byteBuffer.getLong();
long leastSignificantBits = byteBuffer.getLong();
UUID uuid = new UUID(mostSignificantBits, leastSignificantBits);
assertEquals(originalUUID, uuid);
}
縮短編碼后字符串
在我們完成上面的編碼后,我們會(huì)看到字符串的最后還有 2 個(gè)等號(hào) “==” 。為了進(jìn)一步節(jié)約我們的存儲(chǔ)空間,我們可以把這 2 個(gè)等號(hào)從字符串中刪除。
我們可以配置編碼函數(shù),告訴編碼函數(shù)不要在字符串的末尾添加 2 個(gè)等號(hào)。
String encodedUUID = Base64.getUrlEncoder().withoutPadding().encodeToString(byteBuffer.array()); assertEquals(expectedEncodedString, encodedUUID);
針對(duì)解碼的方法來說,我們并不需要對(duì)方法進(jìn)行任何改變,因?yàn)楝F(xiàn)在的解碼方法已經(jīng)能夠正確識(shí)別 Base64 字符串的末尾是不是有 2 個(gè)等號(hào),并且可都兼容。
使用 Apache Commons Conversion Utils 和Codec Utils 工具類
在這部分,我們使用 Apache Commons Conversion Utils 的工具類來先把 UUID 對(duì)象轉(zhuǎn)換為 UUID byte 數(shù)組,然后使用 Apache Commons Codec Utils 工具類來把進(jìn)行 Base64 的字符串處理。
依賴
為了完成上面 2 個(gè)步驟,我們需要分別使用 Apache Commons Lang library 和 commons-codec 類庫(kù)
在我們的 pom.xml 項(xiàng)目文件中,分別添加上面 2 個(gè)類庫(kù)的依賴。
通常你的項(xiàng)目基本上都會(huì)包含進(jìn)來的,如果沒有的話再添加。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.16.0</version>
</dependency>
編碼
上面的編碼就非常簡(jiǎn)單了,直接使用 Conversion.uuidToByteArray 方法,把要編碼的 UUID 對(duì)象傳進(jìn)來,然后直接 Base64,使用 URL 安全的方法。
@Test
void givenUUID_whenEncodingUsingApacheUtils_thenGiveExpectedEncodedString() {
String expectedEncodedString = "UUrxjPeTX8xsDDoxQOfGgw";
byte[] bytes = Conversion.uuidToByteArray(originalUUID, new byte[16], 0, 16);
String encodedUUID = encodeBase64URLSafeString(bytes);
assertEquals(expectedEncodedString, encodedUUID);
}
通過上面的代碼,我們可以看到結(jié)果是 Base 64 已經(jīng)把最后的 2 個(gè)等號(hào)刪掉了。
解碼
針對(duì)解碼來說,我們使用的是 JDK 的 Base64.decodeBase64() 方法,然后調(diào)用 Conversion.byteArrayToUuid() 把解碼后的 byte 數(shù)組轉(zhuǎn)換為 UUID 對(duì)象。
@Test
void givenEncodedString_whenDecodingUsingApacheUtils_thenGiveExpectedUUID() {
String expectedEncodedString = "UUrxjPeTX8xsDDoxQOfGgw";
byte[] decodedBytes = decodeBase64(expectedEncodedString);
UUID uuid = Conversion.byteArrayToUuid(decodedBytes, 0);
assertEquals(originalUUID, uuid);
}
結(jié)論
UUID 是廣泛使用的 ID 識(shí)別標(biāo)識(shí),我們通過對(duì) Base64 的轉(zhuǎn)換來讓 UUID 能夠以更小的數(shù)據(jù)量來進(jìn)行存儲(chǔ)。
轉(zhuǎn)換的關(guān)鍵就在于 UUID 先要轉(zhuǎn)換為 byte 數(shù)組,然后 Base64 是對(duì) byte[] 數(shù)組進(jìn)行編碼的。
到此這篇關(guān)于Java中將UUID存儲(chǔ)為Base64字符串的方法實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java UUID存儲(chǔ)為Base64內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java service層獲取HttpServletRequest工具類的方法
今天小編就為大家分享一篇關(guān)于Java service層獲取HttpServletRequest工具類的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12
Java之Spring注解配置bean實(shí)例代碼解析
這篇文章主要介紹了Java之Spring注解配置bean實(shí)例代碼解析,具有一定參考價(jià)值,文中還有有關(guān)Spring學(xué)習(xí)的資料下載鏈接及相關(guān)內(nèi)容推薦,需要的朋友可以了解下。2017-09-09
使用springboot 獲取控制器參數(shù)的幾種方法小結(jié)
這篇文章主要介紹了使用springboot 獲取控制器參數(shù)的幾種方法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
java 并發(fā)編程之共享變量的實(shí)現(xiàn)方法
這篇文章主要介紹了java 并發(fā)編程之共享變量的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
RabbitMQ如何直接查看隊(duì)列中消息的內(nèi)容
RabbitMQ是一款基于AMQP協(xié)議的開源消息中間件,支持異步通信、消息路由和可靠性保障,這篇文章主要介紹了RabbitMQ如何直接查看隊(duì)列中消息的內(nèi)容的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2026-01-01
詳解Java實(shí)現(xiàn)負(fù)載均衡的幾種算法代碼
本篇文章主要介紹了詳解Java實(shí)現(xiàn)負(fù)載均衡的幾種算法代碼 ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02

