编程示例: Session Id的生成

实现思路

Session的实现方式如下:在用户第一次登录的时候,系统为它分配一个唯一Id(被称为Session Id)作为标识,并且

记录下这个用户的用户名、要登录的账套名、用户拥有的权限等,以Id为键,用户名、账套名等信息为值保存到一

张Session哈希表中。以后客户端登录的时候只要提供此Id即可,应用服务器可以通过此Id到Session哈希表中查询

到所需要的一切信息。因为Session哈希表是保存在存储器中的(通常是内存),存储过多的Session信息将会占用内存

空间,所以客户端退出的时候要通知应用服务器注销此Id。

具体到细节还有一些问题需要处理:

l 如何生成唯一的Id。

l 如何保存用户名、账套名等信息,如何能在Session中放入自定义的信息。

l 如何维护管理Session。

l 如何清除Session。当系统非正常退出的时候,比如客户端机器故障,客户端是无法通知应用服务器注销Id的,

这会造成应用服务器中存在垃圾Session。

l 如何防止此Id被恶意程序截获,从而冒充合法客户端登录系统。

Session Id的生成

客户端Session Id的生成与数据库中的主键生成面对的问题是类似的。以可移植、高效率、可靠的方式来生成主键是一个非常重要的问题。可移植指的是主键生成策略不能依赖于服务器、操作系统、数据库等;高效率是生成主键的过程必须足够快,不能让生成主键的算法成为系统的瓶颈;可靠指的是生成的主键必须保证唯一性。主键生成方式可以分为数据库相关方式和数据库无关方式两种。

数据库相关方式是通过数据库的帮助来生成主键。对于支持自增字段的数据库,可以借助其序列号发生器来产生唯一的主键;对于不支持自增字段的数据库,可以在系统中放置一张表,采用此表记录本次生成的主键,这样就保证了生成的主键与以前的不冲突。数据库相关方式的优点是实现简单,而且可以完全保证生成主键的唯一性;不过由于需要数据库来维护主键的状态和同步对主键生成器的访问,所以对数据库有依赖性,而且由于需要访问数据库,其生成速度较慢。

数据无关方式是无须依靠数据库而生成主键的方式。最典型的算法就是UUID算法。UUID是一个字符串,它被编码为包含了使生成的UUID在整个空间和时间上都完全唯一的所必需的系统信息集,不管这个UUID是何时何地被生成的。原始的UUID规范是由Paul Leach和Rich Salz在网络工作组因特网草案中定义的。

UUID字符串一般由下面信息构成:

l 系统时钟的毫秒值。这是通过System.currentTimeMillis()方法得到的。这保证了在时间维度上产生主键的唯一性。

l 网络IP或者网卡标识。这保证了在集群环境中产生主键的唯一性。

l 精确到在一个JVM内部的对象的唯一。通常是System.identityHashCode(this)所调用产生的编码,这个方法调用保证对JVM中不同对象返回不同的整数。即使在同一台机器上存在多个JVM,两个UUID生成器返回相同的UUID的情况也极不可能发生。

l 在一个对象内的毫秒级的唯一。这是由与每一个方法调用所对应的随机整数,这个随机整数是通过使用java.security.SecureRandom类生成的。这可以保证在同一毫秒内对同一个方法的多个调用都是唯一的。

上述这些部分组合在一起,就可以保证生成的UUID在所有机器中(IP不重复或者网卡地址不重复),以及在同一台机器上的JVM内部的所有UUID生成器的实例中都保持唯一,并且能精确到毫秒级甚至是一个毫秒内的单个方法调用的级别。

流行的UUID算法有很多,这些算法有的不能完全保证生成的UUID的唯一性,必须根据情况选用。下面推荐两种UUID实现算法。

【例】UUID.Hex算法。

这个算法是Hibernate中主键策略为"uuid.hex"时所使用的算法,代码位于包org.hibernate.id下的UUIDHexGenerator.java文件中。

调用方法:

IdentifierGenerator gen = new UUIDHexGenerator();

for (int i = 0; i < 10; i++)

{

String id = (String) gen.generate(null, null);

System.out.println(id);

}

运行结果(UUID的生成是不重复的,每次的运行结果都会不同):

相关推荐
Lhappy嘻嘻5 小时前
Java IO|File 文件操作 + 字节流 / 字符流完整笔记 + 递归删除文件实战
java·笔记·php
伊玛目的门徒5 小时前
试用leetcode之典中典 二数之和问题
java·算法·leetcode
懒鸟一枚8 小时前
深入理解 Linux 内存、Swap 交换分区与分页机制的关系
java·linux·数据库
我命由我123459 小时前
执行 Gradle 指令报错,无法将“grep”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
考虑考虑10 小时前
Sentinel安装
java·后端·微服务
凤凰院凶涛QAQ11 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
掘金_答案12 小时前
上线那天,一个 ConcurrentHashMap 差点送走我的 AI 客服——3 天排查 JVM 血泪史
java·后端·架构
猿与禅12 小时前
CosId 分布式 ID 生成器完全教程:从架构原理到生产落地
java·shardingsphere·雪花算法·分布式id·高性能·cosid·号段模式
MindUp12 小时前
企业网盘权限模型解析:多层级访问控制与审计能力选型指南
java·linux·运维
NG47713 小时前
【软件设计与体系结构】-策略设计模式
java·设计模式·软件工程