java唯一ID生成

 

有时我们不依赖于数据库中自动递增的字段产生唯一ID,比如多表同一字段需要统一一个唯一ID,这时就需要用程序来生成一个唯一的全局ID,然后在数据库事务中同时插入到多章表中实现同步.

在java中有个类工具很好的实现产生唯一ID(UUID),但是由数字和字母及中划线组成的,故数据库字段应该设置为char 并相应的建立索引.

UUID是128位整数(16字节)的全局唯一标识符(Universally Unique Identifier).
指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成UUID的API.UUID按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址,纳秒级时间,芯片ID码和许多可能的数字.由以下几部分的组合:当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个 UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同),时钟序列,全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得),UUID的唯一缺陷在于生成的结果串会比较长.关于UUID这个标准使用最普遍的是微软的GUID(Globals Unique Identifiers).
在ColdFusion中可以用CreateUUID()函数很简单的生成UUID,其格式为:xxxxxxxx- xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字.而标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
,可以从cflib 下载CreateGUID() UDF进行转换.
使用UUID的好处在分布式的软件系统中(比如:DCE/RPC, COM+,CORBA)就能体现出来,它能保证每个节点所生成的标识都不会重复,并且随着WEB服务等整合技术的发展,UUID的优势将更加明显.
关于UUID的更多信息可以多google 一下.

Java生成UUID
UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址,纳秒级时间,芯片ID码和许多可能的数字.由以下几部分的组合:当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同),时钟序列,全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得),UUID的唯一缺陷在于生成的结果串会比较长.
在Java中生成UUID主要有以下几种方式:

JDK1.5
如果使用的JDK1.5的话,那么生成UUID变成了一件简单的事,以为JDK实现了UUID:
java.util.UUID, 直接调用即可.

UUID uuid = UUID.randomUUID();
String s = UUID.randomUUID().toString();//用来生成数据库的主键id非常不错..
 
Java代码 
  1. package com.taobao.tddl.client.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.UnsupportedEncodingException;  
  5. import java.net.InetAddress;  
  6. import java.security.MessageDigest;  
  7. import java.security.NoSuchAlgorithmException;  
  8. import java.security.SecureRandom;  
  9. import java.util.HashMap;  
  10. import java.util.Map;  
  11. import java.util.Random;  
  12. import java.util.concurrent.atomic.AtomicLong;  
  13. import java.util.concurrent.locks.ReentrantLock;  
  14.   
  15. /** 
  16.  * @author huangshang 
  17.  *  
  18.  */  
  19. public class UniqId {  
  20.     private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7',  
  21.             '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };  
  22.   
  23.     private static Map<Character, Integer> rDigits = new HashMap<Character, Integer>(  
  24.             16);  
  25.     static {  
  26.         for (int i = 0; i < digits.length; ++i) {  
  27.             rDigits.put(digits[i], i);  
  28.         }  
  29.     }  
  30.   
  31.     private static UniqId me = new UniqId();  
  32.     private String hostAddr;  
  33.     private Random random = new SecureRandom();  
  34.     private MessageDigest mHasher;  
  35.     private UniqTimer timer = new UniqTimer();  
  36.   
  37.     private ReentrantLock opLock = new ReentrantLock();  
  38.   
  39.     private UniqId() {  
  40.         try {  
  41.             InetAddress addr = InetAddress.getLocalHost();  
  42.   
  43.             hostAddr = addr.getHostAddress();  
  44.         } catch (IOException e) {  
  45.             hostAddr = String.valueOf(System.currentTimeMillis());  
  46.         }  
  47.   
  48.         if (hostAddr == null || hostAddr.length() == 0  
  49.                 || "127.0.0.1".equals(hostAddr)) {  
  50.             hostAddr = String.valueOf(System.currentTimeMillis());  
  51.         }  
  52.   
  53.         try {  
  54.             mHasher = MessageDigest.getInstance("MD5");  
  55.         } catch (NoSuchAlgorithmException nex) {  
  56.             mHasher = null;  
  57.         }  
  58.     }  
  59.   
  60.     /** 
  61.      * 获取UniqID实例 
  62.      *  
  63.      * @return UniqId 
  64.      */  
  65.     public static UniqId getInstance() {  
  66.         return me;  
  67.     }  
  68.   
  69.     /** 
  70.      * 获得不会重复的毫秒数 
  71.      *  
  72.      * @return 
  73.      */  
  74.     public long getUniqTime() {  
  75.         return timer.getCurrentTime();  
  76.     }  
  77.   
  78.     /** 
  79.      * 获得UniqId 
  80.      *  
  81.      * @return uniqTime-randomNum-hostAddr-threadId 
  82.      */  
  83.     public String getUniqID() {  
  84.         StringBuffer sb = new StringBuffer();  
  85.         long t = timer.getCurrentTime();  
  86.   
  87.         sb.append(t);  
  88.   
  89.         sb.append("-");  
  90.   
  91.         sb.append(random.nextInt(8999) + 1000);  
  92.   
  93.         sb.append("-");  
  94.         sb.append(hostAddr);  
  95.   
  96.         sb.append("-");  
  97.         sb.append(Thread.currentThread().hashCode());  
  98.   
  99.         return sb.toString();  
  100.     }  
  101.   
  102.     /** 
  103.      * 获取MD5之后的uniqId string 
  104.      *  
  105.      * @return uniqId md5 string 
  106.      */  
  107.     public String getUniqIDHashString() {  
  108.         return hashString(getUniqID());  
  109.     }  
  110.   
  111.     /** 
  112.      * 获取MD5之后的uniqId 
  113.      *  
  114.      * @return byte[16] 
  115.      */  
  116.     public byte[] getUniqIDHash() {  
  117.         return hash(getUniqID());  
  118.     }  
  119.   
  120.     /** 
  121.      * 对字符串进行md5 
  122.      *  
  123.      * @param str 
  124.      * @return md5 byte[16] 
  125.      */  
  126.     public byte[] hash(String str) {  
  127.         opLock.lock();  
  128.         try {  
  129.             byte[] bt = mHasher.digest(str.getBytes("UTF-8"));  
  130.             if (null == bt || bt.length != 16) {  
  131.                 throw new IllegalArgumentException("md5 need");  
  132.             }  
  133.             return bt;  
  134.         } catch (UnsupportedEncodingException e) {  
  135.             throw new RuntimeException("unsupported utf-8 encoding", e);  
  136.         } finally {  
  137.             opLock.unlock();  
  138.         }  
  139.     }  
  140.   
  141.     /** 
  142.      * 对二进制数据进行md5 
  143.      *  
  144.      * @param str 
  145.      * @return md5 byte[16] 
  146.      */  
  147.     public byte[] hash(byte[] data) {  
  148.         opLock.lock();  
  149.         try {  
  150.             byte[] bt = mHasher.digest(data);  
  151.             if (null == bt || bt.length != 16) {  
  152.                 throw new IllegalArgumentException("md5 need");  
  153.             }  
  154.             return bt;  
  155.         } finally {  
  156.             opLock.unlock();  
  157.         }  
  158.     }  
  159.   
  160.     /** 
  161.      * 对字符串进行md5 string 
  162.      *  
  163.      * @param str 
  164.      * @return md5 string 
  165.      */  
  166.     public String hashString(String str) {  
  167.         byte[] bt = hash(str);  
  168.         return bytes2string(bt);  
  169.     }  
  170.   
  171.     /** 
  172.      * 对字节流进行md5 string 
  173.      *  
  174.      * @param str 
  175.      * @return md5 string 
  176.      */  
  177.     public String hashBytes(byte[] str) {  
  178.         byte[] bt = hash(str);  
  179.         return bytes2string(bt);  
  180.     }  
  181.   
  182.     /** 
  183.      * 将一个字节数组转化为可见的字符串 
  184.      *  
  185.      * @param bt 
  186.      * @return 
  187.      */  
  188.     public String bytes2string(byte[] bt) {  
  189.         int l = bt.length;  
  190.   
  191.         char[] out = new char[l << 1];  
  192.   
  193.         for (int i = 0, j = 0; i < l; i++) {  
  194.             out[j++] = digits[(0xF0 & bt[i]) >>> 4];  
  195.             out[j++] = digits[0x0F & bt[i]];  
  196.         }  
  197.   
  198.         return new String(out);  
  199.     }  
  200.   
  201.     /** 
  202.      * 将字符串转换为bytes 
  203.      *  
  204.      * @param str 
  205.      * @return byte[] 
  206.      */  
  207.     public byte[] string2bytes(String str) {  
  208.         if (null == str) {  
  209.             throw new NullPointerException("参数不能为空");  
  210.         }  
  211.         if (str.length() != 32) {  
  212.             throw new IllegalArgumentException("字符串长度必须是32");  
  213.         }  
  214.         byte[] data = new byte[16];  
  215.         char[] chs = str.toCharArray();  
  216.         for (int i = 0; i < 16; ++i) {  
  217.             int h = rDigits.get(chs[i * 2]).intValue();  
  218.             int l = rDigits.get(chs[i * 2 + 1]).intValue();  
  219.             data[i] = (byte) ((h & 0x0F) << 4 | (l & 0x0F));  
  220.         }  
  221.         return data;  
  222.     }  
  223.   
  224.     /** 
  225.      * 实现不重复的时间 
  226.      *  
  227.      * @author dogun 
  228.      */  
  229.     private static class UniqTimer {  
  230.         private AtomicLong lastTime = new AtomicLong(System.currentTimeMillis());  
  231.   
  232.         public long getCurrentTime() {  
  233.             return this.lastTime.incrementAndGet();  
  234.         }  
  235.     }  
  236. }  
 
 
 
posted @ 2018-04-11 16:23  溪山晴雪  阅读(1294)  评论(0编辑  收藏  举报