Java中将UUID存储为Base64字符串的方法实现

 更新时间:2024年04月28日 16:36:16   作者:HoneyMoose  
使用Base64编码来对UUID存储在一些特定的场合被广泛的使用,本文主要介绍了Java中将UUID存储为Base64字符串的方法实现,具有一定的参考价值,感兴趣的可以了解一下

概述

使用 Base64 编码来对 UUID(Universally Unique Identifiers) 存储在一些特定的场合被广泛的使用。使用 Base64 对比直接使用 UUID 进行存储来说能够更多的节约空间。

本文对这方面的相关内容和问题进行探讨。

在这里,使用 Base64 来对 UUID 进行存储,涉及到一些类型的转换的。Base64 是编码算法,在实际使用的时候我们更多会用到 Byte 数组的方式来进行编码的。这样我们就比较明确在对其进行 Base64 转换之前,我们应该要先干什么了。

使用 byte[]和 Base64.Encoder

Base64.Encoder 就能够提供 byte[] 的 Base64 编码了,我们先使用这个最简单的方式来进行处理。

编码

首先我们需要给出的 UUID 位中创建出我们需要的 byte 数组。

我们先获得 UUID 的 most significant bits 和 least significant bits,然后放入我们 byte 数组中的 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 数组中,同时还会移动 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));
    }
}

当我们获得 byte 数组后,我们就可以调用 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 数组,然后调用我们的转换方法,把我们获得 byte 数组转换成为 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 分别进行转换,然后再组合在一起。

转换的方法如下:

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;
}

通过上面的测试代码,可以看到代码的转换都顺利完成了。

使用 ByteBuffer 和 Base64.getUrlEncoder()

如果我们还使用 JDK 的 API 的话,我们还可以把上面的代码进行一些简化。

编码

通过使用 ByteBuffer,我们可以使用非常简单的下面 2 行代码把 UUID 的 bit 转换为 buffer wrapping 数组。

ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]);
byteBuffer.putLong(originalUUID.getMostSignificantBits());
byteBuffer.putLong(originalUUID.getLeastSignificantBits());

当程序执行完上面的 2 行代码后,我们将会获得 一个 ByteBuffer 对象,这个对象中存储的是 UUID 转换过来的数据。

针对编码,我们就可以使用 Base64.getUrlEncoder() 方法,这个方法的参数我们可以使用 ByteBuffer 转换成 array 就可以了,因为 ByteBuffer 转换成 Array 是返回 Array 的。

String encodedUUID = Base64.getUrlEncoder().encodeToString(byteBuffer.array());

针对上面代码的修改,我们只需要下面简单的几行代码就可以完成 UUID 到 Base64 的转换。

@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() 的解码结果为 byte 数组,所以我们还需要用 ByteBuffer.wrap 把解码后的数组包装成 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 个等号 “==” 。为了进一步节约我们的存储空间,我们可以把这 2 个等号从字符串中删除。

我们可以配置编码函数,告诉编码函数不要在字符串的末尾添加 2 个等号。

String encodedUUID = 
  Base64.getUrlEncoder().withoutPadding().encodeToString(byteBuffer.array());

assertEquals(expectedEncodedString, encodedUUID);

针对解码的方法来说,我们并不需要对方法进行任何改变,因为现在的解码方法已经能够正确识别 Base64 字符串的末尾是不是有 2 个等号,并且可都兼容。

使用 Apache Commons Conversion Utils 和Codec Utils 工具类

在这部分,我们使用 Apache Commons Conversion Utils 的工具类来先把 UUID 对象转换为 UUID byte 数组,然后使用 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);
}

通过上面的代码,我们可以看到结果是 Base 64 已经把最后的 2 个等号删掉了。

解码

针对解码来说,我们使用的是 JDK 的 Base64.decodeBase64() 方法,然后调用 Conversion.byteArrayToUuid() 把解码后的 byte 数组转换为 UUID 对象。

@Test
void givenEncodedString_whenDecodingUsingApacheUtils_thenGiveExpectedUUID() {
    String expectedEncodedString = "UUrxjPeTX8xsDDoxQOfGgw";
    byte[] decodedBytes = decodeBase64(expectedEncodedString);
    UUID uuid = Conversion.byteArrayToUuid(decodedBytes, 0);
    assertEquals(originalUUID, uuid);
}

结论

UUID 是广泛使用的 ID 识别标识,我们通过对 Base64 的转换来让 UUID 能够以更小的数据量来进行存储。

转换的关键就在于 UUID 先要转换为 byte 数组,然后 Base64 是对 byte[] 数组进行编码的。

到此这篇关于Java中将UUID存储为Base64字符串的方法实现的文章就介绍到这了,更多相关Java UUID存储为Base64内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot 整合 Reactor实例详解

    Spring Boot 整合 Reactor实例详解

    这篇文章主要为大家介绍了Spring Boot 整合 Reactor实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Java基础之常用的命令行指令

    Java基础之常用的命令行指令

    这篇文章主要介绍了Java基础之常用的命令行指令,文中有非常详细的图文示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • 基于javaWeb 项目SSM配置要点及可能遇到的问题和解决方法

    基于javaWeb 项目SSM配置要点及可能遇到的问题和解决方法

    下面小编就为大家带来一篇基于javaWeb 项目SSM配置要点及可能遇到的问题和解决方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • swing重绘按钮为任意形状图案的方法

    swing重绘按钮为任意形状图案的方法

    这篇文章主要为大家详细介绍了swing重绘按钮为任意形状图案,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • 详解Java的Exception异常机制

    详解Java的Exception异常机制

    Java的Exception异常机制,为什么会突然聊到异常?其实不是突然,而是我已经准备了很久,但苦于没有好的例子来讲解,从表象到底层实现,今天就带大家详细了解Exception异常,需要的朋友可以参考下
    2021-05-05
  • Struts2实现上传单个文件功能

    Struts2实现上传单个文件功能

    这篇文章主要为大家详细介绍了Struts2实现上传单个文件功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • java IO实现电脑搜索、删除功能的实例

    java IO实现电脑搜索、删除功能的实例

    下面小编就为大家带来一篇java IO实现电脑搜索、删除功能的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • 利用Java中Calendar计算两个日期之间的天数和周数

    利用Java中Calendar计算两个日期之间的天数和周数

    Java 语言的Calendar(日历),Date(日期),和DateFormat(日期格式)组成了Java标准的一个基本但是非常重要的部分。日期是商业逻辑计算一个关键的部分。下面这篇文章就给大家介绍了如何利用Java中Calendar计算两个日期之间的天数和周数,下面来一起看看吧。
    2016-12-12
  • mybatis如何实现saveOrUpdate

    mybatis如何实现saveOrUpdate

    这篇文章主要介绍了mybatis如何实现saveOrUpdate问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Java异常处理 如何跟踪异常的传播路径

    Java异常处理 如何跟踪异常的传播路径

    这篇文章主要介绍了Java异常处理 如何跟踪异常的传播路径,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07

最新评论