實現思路
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的生成是不重復的,每次的運行結果都會不同):