場景:
我們在新浪微博上公布網址的時候。微博會自己主動判別網址。並將其轉換。比如: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 )存儲原始鏈接與短鏈接的映射關系就可以。當我們訪問短鏈接時,僅僅須要從映射關系中找到原始鏈接。就可以跳轉到原始鏈接。
- import util.Encript;
- public class ShortUrl {
- public static void main(String[] args) {
- String url = "http://www.sunchis.com";
- for (String string : ShortText(url)) {
- print(string);
- }
- }
- public static String[] ShortText(String string){
- String key = "XuLiang"; //自己定義生成MD5加密字符串前的混合KEY
- String[] chars = new String[]{ //要使用生成URL的字符
- "a","b","c","d","e","f","g","h",
- "i","j","k","l","m","n","o","p",
- "q","r","s","t","u","v","w","x",
- "y","z","0","1","2","3","4","5",
- "6","7","8","9","A","B","C","D",
- "E","F","G","H","I","J","K","L",
- "M","N","O","P","Q","R","S","T",
- "U","V","W","X","Y","Z"
- };
- String hex = Encript.md5(key + string);
- int hexLen = hex.length();
- int subHexLen = hexLen / 8;
- String[] ShortStr = new String[4];
- for (int i = 0; i < subHexLen; i++) {
- String outChars = "";
- int j = i + 1;
- String subHex = hex.substring(i * 8, j * 8);
- long idx = Long.valueOf("3FFFFFFF", 16) & Long.valueOf(subHex, 16);
- for (int k = 0; k < 6; k++) {
- int index = (int) (Long.valueOf("0000003D", 16) & idx);
- outChars += chars[index];
- idx = idx >> 5;
- }
- ShortStr[i] = outChars;
- }
- return ShortStr;
- }
- private static void print(Object messagr){
- System.out.println(messagr);
- }
- }
- public class Encript {
- //十六進制下數字到字符的映射數組
- private final static String[] hexDigits = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
- /**把inputString加密*/
- public static String md5(String inputStr){
- return encodeByMD5(inputStr);
- }
- /**
- * 驗證輸入的password是否正確
- * @param password 真正的password(加密后的真password)
- * @param inputString 輸入的字符串
- * @return 驗證結果,boolean類型
- */
- public static boolean authenticatePassword(String password,String inputString){
- if(password.equals(encodeByMD5(inputString))){
- return true;
- }else{
- return false;
- }
- }
- /**對字符串進行MD5編碼*/
- private static String encodeByMD5(String originString){
- if (originString!=null) {
- try {
- //創建具有指定算法名稱的信息摘要
- MessageDigest md5 = MessageDigest.getInstance("MD5");
- //使用指定的字節數組對摘要進行最后更新,然后完畢摘要計算
- byte[] results = md5.digest(originString.getBytes());
- //將得到的字節數組變成字符串返回
- String result = byteArrayToHexString(results);
- return result;
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return null;
- }
- /**
- * 輪換字節數組為十六進制字符串
- * @param b 字節數組
- * @return 十六進制字符串
- */
- private static String byteArrayToHexString(byte[] b){
- StringBuffer resultSb = new StringBuffer();
- for(int i=0;i<b.length;i++){
- resultSb.append(byteToHexString(b[i]));
- }
- return resultSb.toString();
- }
- //將一個字節轉化成十六進制形式的字符串
- private static String byteToHexString(byte b){
- int n = b;
- if(n<0)
- n=256+n;
- int d1 = n/16;
- int d2 = n%16;
- return hexDigits[d1] + hexDigits[d2];
- }
- }