generated from mingliqiye/lib-tem
All checks were successful
Gitea Actions Build / Build (push) Successful in 53s
286 lines
6.7 KiB
Java
286 lines
6.7 KiB
Java
/*
|
||
* Copyright 2025 mingliqiye
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*
|
||
* ProjectName mingli-utils
|
||
* ModuleName mingli-utils.main
|
||
* CurrentFile UUID.java
|
||
* LastUpdate 2025-09-10 11:14:27
|
||
* UpdateUser MingLiPro
|
||
*/
|
||
|
||
package com.mingliqiye.utils.uuid;
|
||
|
||
import com.github.f4b6a3.uuid.UuidCreator;
|
||
import com.mingliqiye.utils.string.StringUtil;
|
||
import com.mingliqiye.utils.time.DateTime;
|
||
import com.mingliqiye.utils.time.DateTimeOffset;
|
||
import java.io.Serializable;
|
||
import java.nio.ByteBuffer;
|
||
import java.time.temporal.ChronoUnit;
|
||
import java.util.Locale;
|
||
import java.util.Objects;
|
||
import lombok.Data;
|
||
|
||
/**
|
||
* UUID 工具类,用于生成、解析和操作 UUID。
|
||
* 支持时间戳型 UUID(版本1)以及标准 UUID 的创建与转换。
|
||
*
|
||
* @author MingLiPro
|
||
*/
|
||
@Data
|
||
public class UUID implements Serializable {
|
||
|
||
/**
|
||
* 内部封装的 java.util.UUID 实例
|
||
*/
|
||
private java.util.UUID uuid;
|
||
|
||
/**
|
||
* 构造一个由指定高位和低位组成的 UUID。
|
||
*
|
||
* @param msb 高64位
|
||
* @param lsb 低64位
|
||
*/
|
||
public UUID(long msb, long lsb) {
|
||
uuid = new java.util.UUID(msb, lsb);
|
||
}
|
||
|
||
/**
|
||
* 构造一个基于当前时间的时间戳型 UUID(版本1)。<br>
|
||
* 由于springboot 默认使用此构造函数构造UUID 导致致命BUG 废弃<br>
|
||
* 下个大版本删除<br>
|
||
* @deprecated 请使用 <code>UUID.getTimeBased()</code>
|
||
*/
|
||
@Deprecated
|
||
public UUID() {
|
||
uuid = UUID.getTimeBased().GetUUID();
|
||
}
|
||
|
||
/**
|
||
* 使用给定的 java.util.UUID 对象构造一个新的 UUID 实例。
|
||
*
|
||
* @param uuid java.util.UUID 实例
|
||
*/
|
||
public UUID(java.util.UUID uuid) {
|
||
this.uuid = uuid;
|
||
}
|
||
|
||
/**
|
||
* 根据字符串表示的 UUID 构造一个新的 UUID 实例。
|
||
*
|
||
* @param uuid 字符串形式的 UUID
|
||
*/
|
||
public UUID(String uuid) {
|
||
this.uuid = java.util.UUID.fromString(uuid);
|
||
}
|
||
|
||
/**
|
||
* 获取一个基于当前时间生成的时间戳型 UUID(版本1)。
|
||
*
|
||
* @return 时间戳型 UUID
|
||
*/
|
||
public static UUID getTimeBased() {
|
||
return new UUID(UuidCreator.getTimeBased());
|
||
}
|
||
|
||
/**
|
||
* 将字节数组转换为 UUID 实例。
|
||
*
|
||
* @param bytes 表示 UUID 的 16 字节数据
|
||
* @return 新建的 UUID 实例
|
||
*/
|
||
public static UUID of(byte[] bytes) {
|
||
if (bytes == null) {
|
||
return null;
|
||
}
|
||
ByteBuffer bb = ByteBuffer.wrap(bytes);
|
||
long msb = bb.getLong();
|
||
long lsb = bb.getLong();
|
||
return new UUID(msb, lsb);
|
||
}
|
||
|
||
/**
|
||
* 将字符串解析为 UUID 实例,如果解析失败则抛出 UUIDException。
|
||
*
|
||
* @param data UUID 字符串
|
||
* @return 解析后的 UUID 实例
|
||
* @throws UUIDException 如果解析失败
|
||
*/
|
||
public static UUID of(String data) {
|
||
if (data == null) {
|
||
return null;
|
||
}
|
||
try {
|
||
return new UUID(java.util.UUID.fromString(data));
|
||
} catch (Exception e) {
|
||
throw new UUIDException(e.getMessage(), e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 将 UUID 转换为 16 字节的字节数组。
|
||
*
|
||
* @return 表示该 UUID 的字节数组
|
||
*/
|
||
public byte[] toBytes() {
|
||
if (this.uuid == null) {
|
||
return null;
|
||
}
|
||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
||
bb.putLong(uuid.getMostSignificantBits());
|
||
bb.putLong(uuid.getLeastSignificantBits());
|
||
return bb.array();
|
||
}
|
||
|
||
/**
|
||
* 获取内部封装的 java.util.UUID 实例。
|
||
*
|
||
* @return java.util.UUID 实例
|
||
*/
|
||
public java.util.UUID GetUUID() {
|
||
return uuid;
|
||
}
|
||
|
||
/**
|
||
* 将 UUID 转换为字符串表示,默认使用小写格式。
|
||
*
|
||
* @return UUID 字符串
|
||
*/
|
||
public String toUUIDString() {
|
||
return toUUIDString(false);
|
||
}
|
||
|
||
/**
|
||
* 将 UUID 转换为字符串表示,并可选择是否使用大写。
|
||
*
|
||
* @param u 是否使用大写格式
|
||
* @return UUID 字符串
|
||
* @throws UUIDException 如果 uuid 为 null
|
||
*/
|
||
public String toUUIDString(boolean u) {
|
||
if (uuid == null) {
|
||
throw new UUIDException("uuid is null : NullPointerException");
|
||
}
|
||
if (u) {
|
||
return uuid.toString().toUpperCase(Locale.ROOT);
|
||
}
|
||
return uuid.toString();
|
||
}
|
||
|
||
/**
|
||
* 计算此 UUID 的哈希码。
|
||
*
|
||
* @return 哈希码值
|
||
*/
|
||
@Override
|
||
public int hashCode() {
|
||
return Objects.hash(uuid);
|
||
}
|
||
|
||
/**
|
||
* 判断两个 UUID 是否相等。
|
||
*
|
||
* @param o 比较对象
|
||
* @return 如果相等返回 true,否则返回 false
|
||
*/
|
||
@Override
|
||
public boolean equals(Object o) {
|
||
if (this == o) {
|
||
return true;
|
||
}
|
||
if (o == null || getClass() != o.getClass()) {
|
||
return false;
|
||
}
|
||
UUID uuid = (UUID) o;
|
||
return Objects.equals(this.uuid, uuid.uuid);
|
||
}
|
||
|
||
/**
|
||
* 返回此 UUID 的字符串表示,包含版本信息和时间戳(如果是版本1)。
|
||
*
|
||
* @return UUID 的详细字符串表示
|
||
*/
|
||
@Override
|
||
public String toString() {
|
||
if (uuid == null) {
|
||
return "UUID(null)";
|
||
}
|
||
return StringUtil.format(
|
||
"UUID(uuid={},version={})",
|
||
toUUIDString(true),
|
||
uuid.version()
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 从时间戳型 UUID 中提取时间戳并转换为 DateTime 对象。
|
||
*
|
||
* @return 对应的 DateTime 对象;如果 uuid 为 null,则返回 null
|
||
*/
|
||
public DateTime getDateTime() {
|
||
if (uuid == null) {
|
||
return null;
|
||
}
|
||
if (uuid.version() != 1) {
|
||
return null;
|
||
}
|
||
return DateTime.of(uuid.timestamp() / 10_000).add(
|
||
DateTimeOffset.of(-141427L, ChronoUnit.DAYS)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 从时间戳型 UUID 中提取 MAC 地址,默认使用冒号分隔符。
|
||
*
|
||
* @return MAC 地址字符串
|
||
* @throws UUIDException 如果 uuid 为 null
|
||
*/
|
||
public String extractMACFromUUID() {
|
||
return extractMACFromUUID(null);
|
||
}
|
||
|
||
/**
|
||
* 从时间戳型 UUID 中提取 MAC 地址,并允许自定义分隔符。
|
||
*
|
||
* @param spec 分隔符字符,默认为 ":"
|
||
* @return MAC 地址字符串
|
||
* @throws UUIDException 如果 uuid 为 null
|
||
*/
|
||
public String extractMACFromUUID(String spec) {
|
||
if (uuid == null) {
|
||
throw new UUIDException("uuid is null : NullPointerException");
|
||
}
|
||
if (spec == null) {
|
||
spec = ":";
|
||
}
|
||
long leastSigBits = uuid.getLeastSignificantBits();
|
||
long macLong = leastSigBits & 0xFFFFFFFFFFFFL;
|
||
byte[] macBytes = new byte[6];
|
||
// 提取 MAC 地址的每个字节
|
||
for (int i = 0; i < 6; i++) {
|
||
macBytes[5 - i] = (byte) (macLong >> (8 * i));
|
||
}
|
||
StringBuilder mac = new StringBuilder();
|
||
// 构造 MAC 地址字符串
|
||
for (int i = 0; i < 6; i++) {
|
||
mac.append(String.format("%02X", macBytes[i]));
|
||
if (i < 5) {
|
||
mac.append(spec);
|
||
}
|
||
}
|
||
return mac.toString();
|
||
}
|
||
}
|