长链接转成短链接的原理和实现详解
一、為什么要設計短鏈接,短鏈接有什么好處?
1、鏈接變短,在對內容長度有限制的平臺發文,可編輯的文字就變多了。
比如:微博,限定了只能發 140 個字,如果一串長鏈直接懟上去,其他可編輯的內容就所剩無幾了,用短鏈的話,鏈接長度大大減少,自然可編輯的文字多了不少。
?
2、我們經常需要將鏈接轉成二維碼的形式分享給他人,如果是長鏈的話二維碼密集難識別,短鏈就不存在這個問題了。
3、鏈接太長在有些平臺上無法自動識別為超鏈接。
二、短鏈接實現的原理。
1、請求流程:
首先,我們先看看當當的短鏈接http://localhost:8060/1J0vEa
它是由兩個部分組成
http://localhost:8060短鏈接系統的域名地址或者IP+端口
1J0vEa:請求參數
請求?http://localhost:8060/1J0vEa?地址后,返回狀態如下所示
?2、請求短鏈接后,瀏覽器發生了什么?
上圖所示短鏈接系統,返回的狀態可以為301或者302。
301代表什么?
301代表的是永久重定向。什么意思呢?
對于GET請求, 301跳轉會默認被瀏覽器cache。也就是說,用戶第一次訪問某個短鏈接后,如果服務器返回301狀態碼,則這個用戶在后續多次訪問同一短鏈接地址,瀏覽器會直接請求跳轉地址,而不會再去短鏈接系統上取!
這么做優點很明顯,降低了服務器壓力,但是無法統計到短鏈接地址的點擊次數。
302代表什么?
302代表的是臨時定向。什么意思呢?
對于GET請求, 302跳轉默認不會被瀏覽器緩存,除非在HTTP響應中通過 Cache-Control 或 Expires 暗示瀏覽器緩存。因此,用戶每次訪問同一短鏈接地址,瀏覽器都會去短鏈接系統上取。
這么做的優點是,能夠統計到短地址被點擊的次數了。但是服務器的壓力變大了。
三、短鏈接實現的方法。
1、MurmurHash 非加密型哈希函數 把鏈接轉成一串數字。
public static String hashToBase62(String str) {int i = MurmurHash.hash32(str);long num = i < 0 ? Integer.MAX_VALUE - (long) i : i;return convertDecToBase62(num); }2、由于我們的短鏈接是由 a-z、A-Z 和 0-9 共 62 個字符可以選擇。因此,我們可以由長鏈接經過hashToBase62方法轉成的十進制的數字,轉換為一個62進制的數,例如:http://www.cnblogs.com/rjzheng/p/11827426.html?轉成?1J0vEa
private static char[] CHARS = new char[]{'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','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'};private static int SIZE = CHARS.length;private static String convertDecToBase62(long num) {StringBuilder sb = new StringBuilder();while (num > 0) {int i = (int) (num % SIZE);sb.append(CHARS[i]);num /= SIZE;}return sb.reverse().toString();}3、短鏈接生成方法。
@Overridepublic String saveUrlMap(String shortURL, String longURL, String originalURL) {//保留長度為1的短鏈接if (shortURL.length() == 1) {longURL += DUPLICATE;shortURL = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL);}//在布隆過濾器中查找是否存在else if (FILTER.contains(shortURL)) {//存在,從Redis中查找是否有緩存String redisLongURL = redisTemplate.opsForValue().get(shortURL);if (redisLongURL != null && originalURL.equals(redisLongURL)) {//Redis有緩存,重置過期時間redisTemplate.expire(shortURL, TIMEOUT, TimeUnit.MINUTES);return shortURL;}//沒有緩存,在長鏈接后加上指定字符串,重新hashlongURL += DUPLICATE;shortURL = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL);} else {//不存在,直接存入數據庫try {urlMapper.saveUrlMap(new UrlMap(shortURL, originalURL));FILTER.add(shortURL);//添加緩存redisTemplate.opsForValue().set(shortURL, originalURL, TIMEOUT, TimeUnit.MINUTES);} catch (Exception e) {if (e instanceof DuplicateKeyException) {//數據庫已經存在此短鏈接,則可能是布隆過濾器誤判,在長鏈接后加上指定字符串,重新hashlongURL += DUPLICATE;shortURL = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL);} else {throw e;}}}return shortURL;}四、代碼。
實現的代碼在github:https://github.com/526606178/shortUrl
本文參考了:
https://www.cnblogs.com/rjzheng/p/11827426.html
https://github.com/zzyybs/bestJavaer/commit/cc48eb0680671e8bb362782c78ed708f93f729d8#diff-7dcf1a9faa4713d5be6358d58e41fdc70b8f399b058d1ac50ea025ba99301cd8
總結
以上是生活随笔為你收集整理的长链接转成短链接的原理和实现详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串的方法
- 下一篇: 487 金明的预算方案(分组背包问题扩展