JAVA 短链码生成工具类
请慢用,如果对你有帮助,就留个言,点个赞。
ConversionUtils.java
包含:
自增id转换方法
MD5+BASE64转换方法
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
/**
* @Author : JCccc
* @CreateTime : 2019/12/6
* @Description :
* 短链接生成
* 10进制,62进制互转
**/
@Slf4j
public class ConversionUtils {
/**
* 初始化 62 进制数据,索引位置代表字符的数值,比如 A代表10,z代表61等
*/
private static String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static int scale = 62;
/**
* 将数字转为62进制
*
* @param num Long 型数字
* @param length 转换后的字符串长度,不足则左侧补0
* @return 62进制字符串
*/
public static String encode(long num, int length) {
StringBuilder sb = new StringBuilder();
int remainder;
// id混淆算法
long snum = num & 0xff000000;
snum += (num & 0x0000ff00) << 8;
snum += (num & 0x00ff0000) >> 8;
snum += (num & 0x0000000f) << 4;
snum += (num & 0x000000f0) >> 4;
while (snum > scale - 1) {
/*
对 scale 进行求余,然后将余数追加至 sb 中,由于是从末位开始追加的,因此最后需要反转(reverse)字符串
*/
remainder = Long.valueOf(snum % scale).intValue();
sb.append(chars.charAt(remainder));
snum = snum / scale;
}
sb.append(chars.charAt(Long.valueOf(snum).intValue()));
String value = sb.reverse().toString();
log.info("encode id: {}", snum);
return StringUtils.leftPad(value, length, '0');
}
/**
* 62进制字符串转为数字
*
* @param str 编码后的62进制字符串
* @return 解码后的 10 进制字符串
*/
public static long decode(String str) {
/*
将 0 开头的字符串进行替换
*/
str = str.replace("^0*", "");
long num = 0;
int index;
for (int i = 0; i < str.length(); i++) {
/*
查找字符的索引位置
*/
index = chars.indexOf(str.charAt(i));
/*
索引位置代表字符的数值
*/
num += (long) (index * (Math.pow(scale, str.length() - i - 1)));
}
// id混淆算法
long snum = num & 0xff000000;
snum += (num & 0x00ff0000) >> 8;
snum += (num & 0x0000ff00) << 8;
snum += (num & 0x000000f0) >> 4;
snum += (num & 0x0000000f) << 4;
return snum;
}
public static String Md5CodeEncode(String longUrl, int urlLength) {
if (urlLength < 4 ) {
urlLength = 8;// defalut length
}
StringBuilder sbBuilder = new StringBuilder(urlLength + 2);
String md5Hex = "";
int nLen = 0;
while (nLen < urlLength) {
// 这个方法是先 md5 再 base64编码 参见
// https://github.com/ndxt/centit-commons/blob/master/centit-utils/src/main/java/com/centit/support/security/Md5Encoder.java
md5Hex = Md5Encoder.encodeBase64(md5Hex + longUrl);
for(int i=0;i<md5Hex.length();i++){
char c = md5Hex.charAt(i);
if(c != '/' && c != '+'){
sbBuilder.append(c);
nLen ++;
}
if(nLen == urlLength){
break;
}
}
}
return sbBuilder.toString();
}
public static void main(String[] args) {
System.out.println("62进制:" + encode(1000000001L, 6));
System.out.println("10进制:" + decode("15t2ps"));
System.out.println( Md5CodeEncode("http://abcd.cn/JCccc.html",6));
}
}
Md5Encoder.java
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @Author : JCccc
* @CreateTime : 2019/11/27
* @Description :
**/
public abstract class Md5Encoder {
private Md5Encoder() {
throw new IllegalAccessError("Utility class");
}
protected static final Logger logger = LoggerFactory.getLogger(Md5Encoder.class);
public static byte[] rawEncode(byte[] data){
MessageDigest MD5;
try {
MD5 = MessageDigest.getInstance("MD5");
MD5.update(data, 0, data.length);
return MD5.digest();
} catch (NoSuchAlgorithmException e) {
logger.error(e.getMessage(),e);//e.printStackTrace();
return null;
}
}
public static String encode(byte[] data){
byte [] md5Code = rawEncode(data);
if(md5Code!=null){
return new String(Hex.encodeHex(md5Code));
} else {
return null;
}
}
public static String encode(String data){
try {
return encode(data.getBytes("utf8"));
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(),e);//e.printStackTrace();
return null;
}
}
/**
* 将md5 编码进行base64编码,去掉最后的两个==,16位的md5码base64后最后两位肯定是==
* @param data 需要编码的 数据
* @param urlSafe 返回url合法字符
* @return 将md5 编码进行base64编码,去掉最后的两个==
*/
public static String encodeBase64(byte[] data, boolean urlSafe){
byte [] md5Code = rawEncode(data);
if(md5Code != null){
return new String(
urlSafe? Base64.encodeBase64URLSafe(md5Code): Base64.encodeBase64(md5Code),0,22);
} else {
return null;
}
}
public static String encodeBase64(byte[] data){
return encodeBase64(data, false);
}
public static String encodeBase64(String data, boolean urlSafe){
try {
return encodeBase64(data.getBytes("utf8"), urlSafe);
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(),e);//e.printStackTrace();
return null;
}
}
public static String encodeBase64(String data){
return encodeBase64(data, false);
}
/**
* encoding password for spring security
* 目前框架中的密码都是这样加密的
* @param data 密文
* @param salt 盐
* @return 散列值
*/
public static String encodePasswordAsSpringSecurity(String data,String salt){
return encode(data + "{" + salt + "}");
}
/**
* encoding password for spring JA-SIG Cas
* @param data 密文
* @param salt 盐
* @param iterations 迭代次数
* @return 散列值
*/
public static String encodePasswordAsJasigCas(String data,String salt, int iterations){
MessageDigest MD5;
try {
MD5 = MessageDigest.getInstance("MD5");
byte[] saltBytes = salt.getBytes("utf8");
MD5.update(saltBytes, 0, saltBytes.length);
byte[] hashedBytes = MD5.digest(data.getBytes("utf8"));
for(int i=0;i<iterations-1;i++)
hashedBytes = MD5.digest(hashedBytes);
return new String(Hex.encodeHex(hashedBytes));
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
logger.error(e.getMessage(),e);//e.printStackTrace();
return null;
}
}
/**
* 先腾框架默认的密码算法
* @param data 密文
* @param salt 盐
* @return 散列值
*/
public static String encodePassword(String data,String salt){
return encodePasswordAsSpringSecurity(data , salt);
}
/**
* 先腾框架双重加密算法: 客户端 用md5将密码加密一下传输到后台,后台将密码再用salt加密一下放入数据库中
* 这个算法可以用于后台设置密码时使用,正常验证和以前一样。
* @param data 密文
* @param salt 盐
* @return 散列值
*/
public static String encodePasswordWithDoubleMd5(String data,String salt){
return encodePasswordAsSpringSecurity(
encode(data) , salt);
}
}