短网址ShortUrl的算法

场景:

我们在新浪微博上公布网址的时候。微博会自己主动判别网址。并将其转换。比如:http://t.cn/hrYnr0。

为什么要这样做的,原因我想有这样几点: 


1、微博限制字数为140字一条,那么假设我们须要发一些连接上去,可是这个连接很的长。以至于将近要占用我们内容的一半篇幅。这肯定是不能被同意的。所以短网址应运而生了。 

2、短网址能够在我们项目里能够非常好的对开放级URL进行管理。

有一部分网址能够会涵盖性、暴力、广告等信息。这样我们能够通过用户的举报,全然管理这个连接将不出如今我们的应用中,应为相同的URL通过加密算法之后,得到的地址是一样的。 

3、我们能够对一系列的网址进行流量,点击等统计,挖掘出大多数用户的关注点。这样有利于我们对项目的兴许工作更好的作出决策。

 

以下先来看看短网址映射算法的理论(网上找到的资料): 

① 将长网址用md5算法生成32位签名串,分为4段,,每段8个字符; 

② 对这4段循环处理,取每段的8个字符, 将他看成16进制字符串与0x3fffffff(30位1)的位与操作。超过30位的忽略处理。 

③ 将每段得到的这30位又分成6段,每5位的数字作为字母表的索引取得特定字符,依次进行获得6位字符串; 

④ 这样一个md5字符串能够获得4个6位串。取里面的随意一个就可作为这个长url的短url地址。 

非常easy的理论,我们并不一定说得到的URL是唯一的。可是我们可以取出4组URL,这样差点儿不会出现太大的反复。 

三、  跳转原理

当我们生成短链接之后。仅仅须要在表中(数据库或者NoSql )存储原始链接与短链接的映射关系就可以。当我们訪问短链接时,仅仅须要从映射关系中找到原始链接。就可以跳转到原始链接。


Java代码  收藏代码
  1.    
  2. import util.Encript;   
  3.    
  4. public class ShortUrl {   
  5.     public static void main(String[] args) {   
  6.         String url = "http://www.sunchis.com";   
  7.         for (String string : ShortText(url)) {   
  8.             print(string);   
  9.         }   
  10.     }   
  11.        
  12.     public static String[] ShortText(String string){   
  13.         String key = "XuLiang";                 //自己定义生成MD5加密字符串前的混合KEY   
  14.         String[] chars = new String[]{          //要使用生成URL的字符   
  15.             "a","b","c","d","e","f","g","h",   
  16.             "i","j","k","l","m","n","o","p",   
  17.             "q","r","s","t","u","v","w","x",   
  18.             "y","z","0","1","2","3","4","5",   
  19.             "6","7","8","9","A","B","C","D",   
  20.             "E","F","G","H","I","J","K","L",   
  21.             "M","N","O","P","Q","R","S","T",   
  22.             "U","V","W","X","Y","Z"   
  23.         };   
  24.            
  25.         String hex = Encript.md5(key + string);   
  26.         int hexLen = hex.length();   
  27.         int subHexLen = hexLen / 8;   
  28.         String[] ShortStr = new String[4];   
  29.            
  30.         for (int i = 0; i < subHexLen; i++) {   
  31.             String outChars = "";   
  32.             int j = i + 1;   
  33.             String subHex = hex.substring(i * 8, j * 8);   
  34.             long idx = Long.valueOf("3FFFFFFF"16) & Long.valueOf(subHex, 16);   
  35.                
  36.             for (int k = 0; k < 6; k++) {   
  37.                 int index = (int) (Long.valueOf("0000003D"16) & idx);   
  38.                 outChars += chars[index];   
  39.                 idx = idx >> 5;   
  40.             }   
  41.             ShortStr[i] = outChars;   
  42.         }   
  43.            
  44.         return ShortStr;   
  45.     }   
  46.        
  47.     private static void print(Object messagr){   
  48.         System.out.println(messagr);   
  49.     }   
  50. }   


Java代码  收藏代码
  1. public class Encript {   
  2.     //十六进制下数字到字符的映射数组   
  3.     private final static String[] hexDigits = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};   
  4.    
  5.     /**把inputString加密*/   
  6.     public static String md5(String inputStr){   
  7.         return encodeByMD5(inputStr);   
  8.     }   
  9.    
  10.     /**  
  11.     * 验证输入的password是否正确  
  12.     * @param password 真正的password(加密后的真password)  
  13.     * @param inputString 输入的字符串  
  14.     * @return 验证结果,boolean类型  
  15.     */   
  16.     public static boolean authenticatePassword(String password,String inputString){   
  17.         if(password.equals(encodeByMD5(inputString))){   
  18.             return true;   
  19.         }else{   
  20.             return false;   
  21.         }   
  22.     }   
  23.    
  24.     /**对字符串进行MD5编码*/   
  25.     private static String encodeByMD5(String originString){   
  26.         if (originString!=null) {   
  27.             try {   
  28.                 //创建具有指定算法名称的信息摘要   
  29.                 MessageDigest md5 = MessageDigest.getInstance("MD5");   
  30.                 //使用指定的字节数组对摘要进行最后更新,然后完毕摘要计算   
  31.                 byte[] results = md5.digest(originString.getBytes());   
  32.                 //将得到的字节数组变成字符串返回    
  33.                 String result = byteArrayToHexString(results);   
  34.                 return result;   
  35.             } catch (Exception e) {   
  36.                 e.printStackTrace();   
  37.             }   
  38.         }   
  39.         return null;   
  40.     }   
  41.    
  42.     /**  
  43.     * 轮换字节数组为十六进制字符串  
  44.     * @param b 字节数组  
  45.     * @return 十六进制字符串  
  46.     */   
  47.     private static String byteArrayToHexString(byte[] b){   
  48.         StringBuffer resultSb = new StringBuffer();   
  49.         for(int i=0;i<b.length;i++){   
  50.             resultSb.append(byteToHexString(b[i]));   
  51.         }   
  52.         return resultSb.toString();   
  53.     }   
  54.    
  55.     //将一个字节转化成十六进制形式的字符串   
  56.     private static String byteToHexString(byte b){   
  57.         int n = b;   
  58.         if(n<0)   
  59.         n=256+n;   
  60.         int d1 = n/16;   
  61.         int d2 = n%16;   
  62.         return hexDigits[d1] + hexDigits[d2];   
  63.     }   
  64. }   


posted @ 2017-07-05 12:24  zhchoutai  阅读(4281)  评论(0编辑  收藏  举报