一、什麼是短鏈接?
就是把平時長的網址鏈接,轉換成很短的網址鏈接。
二、短鏈接有什麼好處?
- 網址很短,便於社交傳播
- 方便根據短鏈跟蹤統計
三、體驗短鏈接業務場景
場景1:推廣短信
以我收到的推廣短信爲例:
【AAS旗艦店】今晚0點雙旦狂歡,指定商品前一小時享8.5折,
下單即贈身體乳 https://s.tb.cn/y6.VpI6e -回T退訂
打開瀏覽器,複製鏈接 https://s.tb.cn/y6.VpI6e 打開,就變成下面這個長鏈接了:
https://aashzp.m.tmall.com/?ajson=1&parentCatId=0&bc_fl_src=tbsms_crm_3705444440_isvsmg%241985808584440_8800958846
場景2:商品分享
自己生成一個分享,內容長下面這樣:
97嘻就子小你他然就看是在上,
https://m.tb.cn/h.fj1UAkD?sm=a8b47c
【官方正品】HR/赫蓮娜 綠寶瓶精華PRO 100ml 修護緊緻保溼
打開瀏覽器,複製鏈接 https://m.tb.cn/h.fj1UAkD?sm=a8b47c 打開,就變成下面這個長鏈接了:
https://h5.m.taobao.com/awp/core/detail.htm?ut_sk=1.XOjlkWoncxMDAAYygVvhI0CS_21380790_1640269776154.Copy.1&id=645568351481&sourceType=item&price=2580&suid=D06C2ECF-F76B-401E-B951-58E657BF8473&shareUniqueId=14249255760&un=f7b24c964aced77f0a62cb2c046d31df&share_crt_v=1&un_site=0&spm=a2159r.13376460.0.0&sp_tk=5bCx5a2Q5bCP5L2g5LuW54S25bCx55yL5piv5Zyo5LiK&bc_fl_src=share-104876817051551-2-2&cpp=1&shareurl=true&short_name=h.fj1UAkD&bxsign=scdj_6JfE23mjgVCqKKOMvDqdasx8u7jsYqqB5AS2EbXcIDDxw_La9PTd_pR4fYIKyQ8G-ZTCU815Kh8z9atg9rTw2yP3bKn8IugksOVSvcw-vOhZ4qhF7HHycnjD_ktg-5&sm=a8b47c&app=chrome
四、算法實現過程
思路
/** * 短鏈接生成算法 * <p> * 1. 將長鏈接網址MD5加密,生成32位字符,然後切割分爲4組 每組8個字節 * 2. 對每組內8個字節處理,將它與0x3FFFFFFF(30位1)位與運算,截取前30位二進制 * 3. 將30位二進制分爲6組,每段與0x0000003D位與運算,獲取數組chars數組的下標,就可以得到6位字符串 * 4. 32位加密串可以獲取4組6位短鏈,可取裏面任意一個作爲長鏈接的短鏈 */
效果如下
位與說明
0x3FFFFFFF 2進制:111111111111111111111111111111
0x3c181996 2進制:111100000110000001100110010110
0x3FFFFFFF & 0x3c181996 位與運算後:111100000110000001100110010110
0x0000003D 2進制:111101
0x0000003D 10進制:61
具體實現
/** * 短鏈接生成算法 * <p> * 1. 將長鏈接網址MD5加密,生成32位字符,然後切割分爲4組 每組8個字節 * 2. 對每組內8個字節處理,將它與0x3FFFFFFF(30位1)位與運算,截取前30位二進制 * 3. 將30位二進制分爲6組,每段與0x0000003D位與運算,獲取數組chars數組的下標,就可以得到6位字符串 * 4. 32位加密串可以獲取4組6位短鏈,可取裏面任意一個作爲長鏈接的短鏈 */ public class ShortUrlGenerator { public static String[] chars = new String[]{ "a", "b", "c", "d", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; public static void main(String[] args) { // 長鏈接文本 String longUrl = "https://h5.m.taobao.com/awp/core/detail.htm?ut_sk=1.XOjlkWoncxMDAAYygVvhI0CS_21380790_1640269776154.Copy.1&id=645568351481&sourceType=item&price=2580&suid=D06C2ECF-F76B-401E-B951-58E657BF8473&shareUniqueId=14249255760&un=f7b24c964aced77f0a62cb2c046d31df&share_crt_v=1&un_site=0&spm=a2159r.13376460.0.0&sp_tk=5bCx5a2Q5bCP5L2g5LuW54S25bCx55yL5piv5Zyo5LiK&bc_fl_src=share-104876817051551-2-2&cpp=1&shareurl=true&short_name=h.fj1UAkD&bxsign=scdS1njVAfx-0lliKyfKqmu-fQeyJFq1c_69OVO1RV1nXVSSffpMMvYQ7zQiJUAMBoqlM5EDiop5WS6Ei0gF5O6HpcwrhNpOkvbSZ322gDPdhPXmT-cpiKUDkvKmpC9CqCO&sm=a8b47c&app=chrome"; System.out.println(longUrl); // 生成4組6位短鏈code List<String> shortCodes = shortUrl(longUrl); shortCodes.forEach(System.out::println); // 0x3FFFFFFF 2進制 System.out.println(String.format("0x3FFFFFFF 2進制:%s", Long.toBinaryString(0x3FFFFFFF))); // 3c181996 System.out.println(String.format("0x3c181996 2進制:%s", Long.toBinaryString(0x3c181996))); // 位與運算,有0出0 全1出1 System.out.println(String.format("0x3FFFFFFF & 0x3c181996 位與運算後:%s", Long.toBinaryString(0x3FFFFFFF & 0x3c181996))); System.out.println(String.format("0x0000003D 2進制:%s", Long.toBinaryString(0x0000003D))); System.out.println(String.format("0x0000003D 10進制:%s", Long.parseLong("0000003D", 16))); } /** * 生成短鏈code * * @param longUrl 長鏈接文本 * @return 4組短鏈 */ private static List<String> shortUrl(String longUrl) { List<String> result = new ArrayList<>(); // 先對長鏈接進行MD5加密,生成32位字符串 String md5Encrypt = DigestUtils.md5Hex(longUrl); // 對加密字符串切割4組,每組8個字符 for (int i = 0; i < 4; i++) { String temp = md5Encrypt.substring(i * 8, (i + 1) * 8); // 先轉爲16進制 就是在字符串前面加了0x // 然後與0x3FFFFFFF 進行位與運算,有0出0 全1出1 // 目的:截取前30位二進制 long hexLong = 0x3FFFFFFF & Long.parseLong(temp, 16); StringBuffer outChar = new StringBuffer(); // 把前面30位二進制拆分成6組,每組5位二進制 for (int j = 0; j < 6; j++) { // 0x0000003D的10進制是61,而61是數組chars數組的下標 // 目的:保證下標在61內 long index = 0x0000003D & hexLong; outChar.append(chars[(int) index]); // 按位向右移5位,30位的二進制 6次循環既可以結束 hexLong = hexLong >> 5; } result.add(outChar.toString()); } return result; } }