短网址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地址。 

很简单的理论,我们并不一定说得到的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.     * 验证输入的密码是否正确  
  12.     * @param 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. }   


你可能感兴趣的:(spring,算法,hadoop,新浪微博,开源项目)