package com.henglu.test;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Arrays;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;
/**
* 金蝶EAS BOS 创建ID
* @author zhouxianglh@gmail.com
* @version 1.0 2014-4-11 下午9:31:14
*/
public class CreateID {
// byte 转 int
public static int bytesToInt(byte[] b) {
int v0 = (b[0] & 0xff) << 24;// &0xff将byte值无差异转成int,避免Java自动类型提升后,会保留高位的符号位
int v1 = (b[1] & 0xff) << 16;
int v2 = (b[2] & 0xff) << 8;
int v3 = (b[3] & 0xff);
return v0 + v1 + v2 + v3;
}
/**
* 生成BOSuuid,生成规则为 两个随机的 long 型数据,组合后加上 int 型的bostType ,经过Base64 转码生成的
*/
public static String createID(int bosType) throws IOException {
// 随机生成的数据不会重复么?
// 以下代码是从BOS里抽出来的
SecureRandom random = new SecureRandom();
byte[] randomBytes = new byte[16];
random.nextBytes(randomBytes);
randomBytes[6] = (byte) (randomBytes[6] & 0xF);
randomBytes[6] = (byte) (randomBytes[6] | 0x40);
randomBytes[8] = (byte) (randomBytes[8] & 0x3F);
randomBytes[8] = (byte) (randomBytes[8] | 0x80);
long mostSigBits = 0L;
long leastSigBits = 0L;
for (int i = 0; i < 8; ++i) {
mostSigBits = mostSigBits << 8 | randomBytes[i] & 0xFF;
}
for (int i = 8; i < 16; ++i) {
leastSigBits = leastSigBits << 8 | randomBytes[i] & 0xFF;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutput out = new DataOutputStream(baos);
out.writeLong(mostSigBits);
out.writeLong(leastSigBits);
out.writeInt(bosType);
return Base64.encode(baos.toByteArray());
}
/**
* 根据十六进制 bosType 生成ID
*/
public static String createID(String bosType) throws IOException {
return createID(getBosTypeInt(bosType));
}
/**
* 把十进制的 bosType 返回十六进制的 bosType,ID 经过base64解码后取最后4位生成int 型数据,转十六进制即可以得到bosType,然后可以通过bosType得到实体名
*/
public static String getBosType(String id) throws Base64DecodingException {
byte[] result = Arrays.copyOfRange(Base64.decode(id), 16, 20);
int type = bytesToInt(result);
return Integer.toHexString(type).toUpperCase();
}
/**
* 十六进制的 bosType 转十进制的 bosType
*/
public static int getBosTypeInt(String bosType) {
return Integer.valueOf(bosType, 16);
}
public static void main(String[] args) {
try {
String id = createID("2B62B38A");
System.out.println(id);
System.out.println(getBosType(id));
} catch (IOException e) {
e.printStackTrace();
} catch (Base64DecodingException e) {
e.printStackTrace();
}
}
}
按自己的理解,解释下吧:
通过 SecureRadom 生成16进制随机数,然后转换为long类型,稍处理后再连接int 型的 bosType ,最后Base64 加密.....因为SecureRadom 是伪随机,所以不会重复,而base64 根据不同的内容生成的密文也是不同的,就保证了ID的唯一???