Java中的UUID简单介绍1、UUID的格式
xxxxxxxx—xxxx—xxxx—xxxx—xxxxxxxxxxxx
8个⼗六进制数—4个⼗六进制数—4个⼗六进制数—4个⼗六进制数—12个⼗六进制数
⼀共是32个⼗六进制数,128bit。刚好跟IPV6数⽬相等。
估计我们有⽣之年是⽤不完了。(有点可惜,我尽然不能看到UUID被⽤尽的那⼀天)。
详细UUID保证唯⼀性的介绍,。
2、获取UUID的三种⽅式
UUID.randomUUID();//最常⽤
UUID.fromString("095c64fe-c5bf-11ea-aec6-a402b9e2b04d");
UUID.nameUUIDFromBytes("⾝份证号码".getBytes());
randomUUID() 随机获取⼀个UUID,有极⼩的概率会重复
fromString() 根据⼀个符合UUID格式的字符串获取,不常⽤,我都有了还获取⼲嘛。
nameUUIDFromBytes() 根据⼀个字节数组获取,⼀般要求给定的字节数组不重复3、⽅法介绍
UUID类的⽅法好像是所有底层源码中⽅法最少的了吧,下⾯就简单介绍⼀下。
UUID uuid = UUID.randomUUID();
System.out.println("String() = "+ String());
System.out.println("uuid.version() = "+ uuid.version());//版本号,下⾯会详细介绍
System.out.println("uuid.variant() = "+ uuid.variant());//还没搞清楚
结果如下
uuid.version() = 4
uuid.variant() = 2
UUID uuid = UUID.randomUUID();
System.out.println("uuid.timestamp() = "+ uuid.timestamp());
System.out.println("uuid.clockSequence() = "+ uuid.clockSequence());
还可以获取时间戳,这uuid有点强啊,结果如下:
纳尼?为什么会报Not a time-based UUID错误呢。
错误提⽰这不是⼀个基于时间的uuid,也就是说这个uuid不是基于时间戳⽣成的。
看⼀下源码,这个错误是怎么产⽣的。
4、UUID的版本介绍
⼜有问题出来了,uuid还有版本?还真有!那这些不同版本的uuid⼜有什么区别呢?
UUID Version 1:基于时间的UUID基于时间的UUID通过计算当前时间戳、随机数和机器MAC地址得到。由于在算法中使⽤了MAC 地址,这个版本的UUID可以保证在全球范围的唯⼀性。但与此同时,使⽤MAC地址会带来安全性问题,这就是这个版本UUID受到批评的地⽅。如果应⽤只是在局域⽹中使⽤,也可以使⽤退化的算法,以IP地址来代替MAC地址--Java的UUID往往是这样实现的(当然也考虑了获取MAC的难度)。
UUID Version 2:DCE安全的UUIDDCE(Distributed Computing Environment)安全的UUID和基于时间的UUID算法相同,但会把时间戳的前4位置换为POSIX的UID或GID。这个版本的UUID在实际中较少⽤到。
UUID Version 3:基于名字的UUID(MD5)基于名字的UUID通过计算名字和名字空间的MD5散列值得到。这个版本的UUID保证了:相同名字空间中不同名字⽣成的UUID的唯⼀性;不同名字空间中的UUID的唯⼀性;相同名字空间中相同名字的UUID重复⽣成是相同的。
UUID Version 4:随机UUID根据随机数,或者伪随机数⽣成UUID。这种UUID产⽣重复的概率是可以
计算出来的,但随机的东西就像是买:你指望它发财是不可能的,但狗屎运通常会在不经意中到来。
UUID Version 5:基于名字的UUID(SHA1)和版本3的UUID算法类似,只是散列值计算使⽤SHA1(Secure Hash Algorithm 1)算法。
UUID的应⽤从UUID的不同版本可以看出,Version 1/2适合应⽤于分布式计算环境下,具有⾼度的唯⼀性;Version 3/5适合于⼀定范围内名字唯⼀,且需要或可能会重复⽣成UUID的环境下;⾄于Version 4,个⼈的建议是最好不⽤(虽然它是最简单最⽅便的)。通常我们建议使⽤UUID来标识对象或持久化数据,但以下情况最好不使⽤UUID: 映射类型的对象。⽐如只有代码及名称的代码表。 ⼈⼯维护的⾮系统⽣成对象。⽐如系统中的部分基础数据。对于具有名称不可重复的⾃然特性的对象,最好使⽤Version 3/5的UUID。⽐如系统中的⽤户。如果⽤户的UUID是Version 1的,如果你不⼩⼼删除了再重建⽤户,你会发现⼈还是那个⼈,⽤户已经不是那个⽤户了。(虽然标记为删除状态也是⼀种解决⽅案,但会带来实现上的复杂性。)
看到了吧。使⽤UUID.randomUUID()获取的uuid是不带时间戳信息的。
那么怎么获取带时间戳信息的uuid呢?
5、获取带时间戳信息的uuid
就是通过⼀个给定uuid来获取,有点鸡肋。
UUID.fromString("095c64fe-c5bf-11ea-aec6-a402b9e2b04d");
上⾯也说了,这个版本1有个不安全的地⽅,那就是会暴露机器的Mac地址。为了写个教程我也是拼了。怎么验证呢?
ipconfig/all
上⾯哪个uuid是通过python获取的,可以看到⼈家python⽀持指定版本。
重新获取时间戳
System.out.println("uuid.timestamp() = "+ uuid.timestamp());
System.out.println("uuid.clockSequence() = "+ uuid.clockSequence());
结果如下:
uuid.timestamp() = 138140162874696958
uuid.clockSequence() = 11974
这个时间戳是个啥?咋这么长呢?
对⽐我们⽤Java的System.currentTimeMillis()获取以下时间戳,对⽐⼀下长度。
java生成随机数的方法138140162874696958 ------>18位
1594724368033 --------------->13位
还得反底层源码,看看timestamp()的解释。
两个关键点
获得的是纳秒级别的
时间并不是从1970年开始的
拓展⼀下1582年的10⽉是个⼀个特殊的⽉份。可以看到少了10天。具体原因⾃⾏百度把。
6、把UUID的时间戳转换
怎么把这个时间戳转成具体的我们能看懂的时间⽇期呢?
公式如下:
uuid.timestamp()—1970到1582年这段时间的时间差
//把uuid的时间戳转成可以识别的时间戳
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(138140162874696958L -0x01b21dd213814000L,0, ZoneOffset.ofHours(8)); System.out.println("w() = "+ w());
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论