Java中將UUID存儲為Base64字符串的方法實現(xiàn)
概述
使用 Base64 編碼來對 UUID(Universally Unique Identifiers) 存儲在一些特定的場合被廣泛的使用。使用 Base64 對比直接使用 UUID 進行存儲來說能夠更多的節(jié)約空間。
本文對這方面的相關(guān)內(nèi)容和問題進行探討。
在這里,使用 Base64 來對 UUID 進行存儲,涉及到一些類型的轉(zhuǎn)換的。Base64 是編碼算法,在實際使用的時候我們更多會用到 Byte 數(shù)組的方式來進行編碼的。這樣我們就比較明確在對其進行 Base64 轉(zhuǎn)換之前,我們應(yīng)該要先干什么了。
使用 byte[]和 Base64.Encoder
Base64.Encoder
就能夠提供 byte[]
的 Base64 編碼了,我們先使用這個最簡單的方式來進行處理。
編碼
首先我們需要給出的 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; }
上面的代碼中還有一個 fillByteArray 方法,這個方法,這個方法將會把我們的 bit 存如 byte array 數(shù)組中,同時還會移動 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 方法來直接進行編碼了成一個 Base64 加密字符串了。
完整的測試代碼如下:
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 字符串進行解碼,我們可以使用完全相反的方法:
@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 對象。
UUID convertToUUID(byte[] src) { long mostSignificantBits = convertBytesToLong(src, 0); long leastSignificantBits = convertBytesToLong(src, 8); return new UUID(mostSignificantBits, leastSignificantBits); }
在上面的方法中,我們分別對 UUID 中需要使用的 most significant bits 和 less significant bits 分別進行轉(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; }
通過上面的測試代碼,可以看到代碼的轉(zhuǎn)換都順利完成了。
使用 ByteBuffer 和 Base64.getUrlEncoder()
如果我們還使用 JDK 的 API 的話,我們還可以把上面的代碼進行一些簡化。
編碼
通過使用 ByteBuffer,我們可以使用非常簡單的下面 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 行代碼后,我們將會獲得 一個 ByteBuffer 對象,這個對象中存儲的是 UUID 轉(zhuǎn)換過來的數(shù)據(jù)。
針對編碼,我們就可以使用 Base64.getUrlEncoder() 方法,這個方法的參數(shù)我們可以使用 ByteBuffer 轉(zhuǎn)換成 array 就可以了,因為 ByteBuffer 轉(zhuǎn)換成 Array 是返回 Array 的。
String encodedUUID = Base64.getUrlEncoder().encodeToString(byteBuffer.array());
針對上面代碼的修改,我們只需要下面簡單的幾行代碼就可以完成 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 對象。
@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); }
縮短編碼后字符串
在我們完成上面的編碼后,我們會看到字符串的最后還有 2 個等號 “==” 。為了進一步節(jié)約我們的存儲空間,我們可以把這 2 個等號從字符串中刪除。
我們可以配置編碼函數(shù),告訴編碼函數(shù)不要在字符串的末尾添加 2 個等號。
String encodedUUID = Base64.getUrlEncoder().withoutPadding().encodeToString(byteBuffer.array()); assertEquals(expectedEncodedString, encodedUUID);
針對解碼的方法來說,我們并不需要對方法進行任何改變,因為現(xiàn)在的解碼方法已經(jīng)能夠正確識別 Base64 字符串的末尾是不是有 2 個等號,并且可都兼容。
使用 Apache Commons Conversion Utils 和Codec Utils 工具類
在這部分,我們使用 Apache Commons Conversion Utils 的工具類來先把 UUID 對象轉(zhuǎn)換為 UUID byte 數(shù)組,然后使用 Apache Commons Codec Utils 工具類來把進行 Base64 的字符串處理。
依賴
為了完成上面 2 個步驟,我們需要分別使用 Apache Commons Lang library 和 commons-codec 類庫
在我們的 pom.xml 項目文件中,分別添加上面 2 個類庫的依賴。
通常你的項目基本上都會包含進來的,如果沒有的話再添加。
<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>
編碼
上面的編碼就非常簡單了,直接使用 Conversion.uuidToByteArray 方法,把要編碼的 UUID 對象傳進來,然后直接 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 個等號刪掉了。
解碼
針對解碼來說,我們使用的是 JDK 的 Base64.decodeBase64() 方法,然后調(diào)用 Conversion.byteArrayToUuid()
把解碼后的 byte 數(shù)組轉(zhuǎn)換為 UUID 對象。
@Test void givenEncodedString_whenDecodingUsingApacheUtils_thenGiveExpectedUUID() { String expectedEncodedString = "UUrxjPeTX8xsDDoxQOfGgw"; byte[] decodedBytes = decodeBase64(expectedEncodedString); UUID uuid = Conversion.byteArrayToUuid(decodedBytes, 0); assertEquals(originalUUID, uuid); }
結(jié)論
UUID 是廣泛使用的 ID 識別標(biāo)識,我們通過對 Base64 的轉(zhuǎn)換來讓 UUID 能夠以更小的數(shù)據(jù)量來進行存儲。
轉(zhuǎn)換的關(guān)鍵就在于 UUID 先要轉(zhuǎn)換為 byte 數(shù)組,然后 Base64 是對 byte[]
數(shù)組進行編碼的。
到此這篇關(guān)于Java中將UUID存儲為Base64字符串的方法實現(xiàn)的文章就介紹到這了,更多相關(guān)Java UUID存儲為Base64內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot中TransactionTemplate事務(wù)管理的實現(xiàn)
Spring Boot提供了多種方式來管理事務(wù),其中之一是使用TransactionTemplate,本文主要介紹了SpringBoot中TransactionTemplate事務(wù)管理的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-04-04J2EE Servlet上傳文件到服務(wù)器并相應(yīng)顯示功能的實現(xiàn)代碼
這篇文章主要介紹了J2EE Servlet上傳文件到服務(wù)器,并相應(yīng)顯示,在文中上傳方式使用的是post不能使用get,具體實例代碼大家參考下本文2018-07-07java中\(zhòng)t,\n,\r,\b,\f 的作用及說明
這篇文章主要介紹了java中\(zhòng)t,\n,\r,\b,\f 的作用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07Nacos客戶端配置中心緩存動態(tài)更新實現(xiàn)源碼
這篇文章主要為大家介紹了Nacos客戶端配置中心緩存動態(tài)更新實現(xiàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-03-03SpringBoot整合Redis實現(xiàn)消息發(fā)布與訂閱的示例代碼
能實現(xiàn)發(fā)送與接收信息的中間介有很多,比如:RocketMQ、RabbitMQ、ActiveMQ、Kafka等,本文主要介紹了Redis的推送與訂閱功能并集成Spring Boot的實現(xiàn),感興趣的可以了解一下2022-08-08