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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot中TransactionTemplate事务管理的实现

    SpringBoot中TransactionTemplate事务管理的实现

    Spring Boot提供了多种方式来管理事务,其中之一是使用TransactionTemplate,本文主要介绍了SpringBoot中TransactionTemplate事务管理的实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • Java实现简单台球游戏

    Java实现简单台球游戏

    这篇文章主要为大家详细介绍了Java实现简单台球游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • J2EE Servlet上传文件到服务器并相应显示功能的实现代码

    J2EE Servlet上传文件到服务器并相应显示功能的实现代码

    这篇文章主要介绍了J2EE Servlet上传文件到服务器,并相应显示,在文中上传方式使用的是post不能使用get,具体实例代码大家参考下本文
    2018-07-07
  • java中\t,\n,\r,\b,\f 的作用及说明

    java中\t,\n,\r,\b,\f 的作用及说明

    这篇文章主要介绍了java中\t,\n,\r,\b,\f 的作用及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • 关于Spring统一异常处理及说明

    关于Spring统一异常处理及说明

    这篇文章主要介绍了关于Spring统一异常处理及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Nacos客户端配置中心缓存动态更新实现源码

    Nacos客户端配置中心缓存动态更新实现源码

    这篇文章主要为大家介绍了Nacos客户端配置中心缓存动态更新实现源码,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-03-03
  • 解决idea的debug模式突然变卡,项目启动变慢的状况

    解决idea的debug模式突然变卡,项目启动变慢的状况

    这篇文章主要介绍了解决idea的debug模式突然变卡,项目启动变慢的状况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • java抓取网页或文件中的邮箱号码

    java抓取网页或文件中的邮箱号码

    这篇文章主要为大家详细介绍了java如何抓取网页或文件中的邮箱号码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • SpringBoot整合Redis实现消息发布与订阅的示例代码

    SpringBoot整合Redis实现消息发布与订阅的示例代码

    能实现发送与接收信息的中间介有很多,比如:RocketMQ、RabbitMQ、ActiveMQ、Kafka等,本文主要介绍了Redis的推送与订阅功能并集成Spring Boot的实现,感兴趣的可以了解一下
    2022-08-08
  • Spring中的模块与应用场景详解

    Spring中的模块与应用场景详解

    这篇文章主要介绍了Spring中的模块与应用场景详解,Spring 框架可以为 Java 应用程序开发提供全面的基础设施支持,它是现在非常流行的 Java 开源框架,对于一个 Java 开发人员来说,熟练掌握 Spring 是必不可少的,需要的朋友可以参考下
    2023-09-09

最新评论