package cn.jeesoft.core.util; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; /** * @author huangshang * */ public class UniqId { private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private static Map<Character, Integer> rDigits = new HashMap<Character, Integer>( 16); static { for (int i = 0; i < digits.length; ++i) { rDigits.put(digits[i], i); } } private static UniqId me = new UniqId(); private String hostAddr; private Random random = new SecureRandom(); private MessageDigest mHasher; private UniqTimer timer = new UniqTimer(); private ReentrantLock opLock = new ReentrantLock(); private UniqId() { try { InetAddress addr = InetAddress.getLocalHost(); hostAddr = addr.getHostAddress(); } catch (IOException e) { hostAddr = String.valueOf(System.currentTimeMillis()); } if (hostAddr == null || hostAddr.length() == 0 || "127.0.0.1".equals(hostAddr)) { hostAddr = String.valueOf(System.currentTimeMillis()); } try { mHasher = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException nex) { mHasher = null; } } /** * 获取UniqID实例 * * @return UniqId */ public static UniqId getInstance() { return me; } /** * 获得不会重复的毫秒数 * * @return */ public long getUniqTime() { return timer.getCurrentTime(); } /** * 获得UniqId * * @return uniqTime-randomNum-hostAddr-threadId */ public String getUniqID() { StringBuffer sb = new StringBuffer(); long t = timer.getCurrentTime(); sb.append(t); sb.append("-"); sb.append(random.nextInt(8999) + 1000); sb.append("-"); sb.append(hostAddr); sb.append("-"); sb.append(Thread.currentThread().hashCode()); return sb.toString(); } /** * 获取MD5之后的uniqId string * * @return uniqId md5 string */ public String getUniqIDHashString() { return hashString(getUniqID()); } /** * 获取MD5之后的uniqId * * @return byte[16] */ public byte[] getUniqIDHash() { return hash(getUniqID()); } /** * 对字符串进行md5 * * @param str * @return md5 byte[16] */ public byte[] hash(String str) { opLock.lock(); try { byte[] bt = mHasher.digest(str.getBytes("UTF-8")); if (null == bt || bt.length != 16) { throw new IllegalArgumentException("md5 need"); } return bt; } catch (UnsupportedEncodingException e) { throw new RuntimeException("unsupported utf-8 encoding", e); } finally { opLock.unlock(); } } /** * 对二进制数据进行md5 * * @param str * @return md5 byte[16] */ public byte[] hash(byte[] data) { opLock.lock(); try { byte[] bt = mHasher.digest(data); if (null == bt || bt.length != 16) { throw new IllegalArgumentException("md5 need"); } return bt; } finally { opLock.unlock(); } } /** * 对字符串进行md5 string * * @param str * @return md5 string */ public String hashString(String str) { byte[] bt = hash(str); return bytes2string(bt); } /** * 对字节流进行md5 string * * @param str * @return md5 string */ public String hashBytes(byte[] str) { byte[] bt = hash(str); return bytes2string(bt); } /** * 将一个字节数组转化为可见的字符串 * * @param bt * @return */ public String bytes2string(byte[] bt) { int l = bt.length; char[] out = new char[l << 1]; for (int i = 0, j = 0; i < l; i++) { out[j++] = digits[(0xF0 & bt[i]) >>> 4]; out[j++] = digits[0x0F & bt[i]]; } return new String(out); } /** * 将字符串转换为bytes * * @param str * @return byte[] */ public byte[] string2bytes(String str) { if (null == str) { throw new NullPointerException("参数不能为空"); } if (str.length() != 32) { throw new IllegalArgumentException("字符串长度必须是32"); } byte[] data = new byte[16]; char[] chs = str.toCharArray(); for (int i = 0; i < 16; ++i) { int h = rDigits.get(chs[i * 2]).intValue(); int l = rDigits.get(chs[i * 2 + 1]).intValue(); data[i] = (byte) ((h & 0x0F) << 4 | (l & 0x0F)); } return data; } /** * 实现不重复的时间 * * @author dogun */ private static class UniqTimer { private static AtomicLong lastTime = new AtomicLong( System.currentTimeMillis()); public long getCurrentTime() { return lastTime.incrementAndGet(); } } }