欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JAVA實現(xiàn)生成短鏈接的示例代碼

 更新時間:2023年08月29日 09:30:14   作者:lcz-2000  
短鏈接就是將長度較長的鏈接壓縮成較短的鏈接,本文就來介紹一下JAVA實現(xiàn)生成短鏈接的示例代碼,具有一定的參考價值,感興趣的可以了解一下

短鏈接

短鏈接就是將長度較長的鏈接壓縮成較短的鏈接。

好處:便于發(fā)布、傳播。

短鏈跳轉(zhuǎn)訪問原理

其實就是在后臺保存有短鏈和長鏈的映射關(guān)系,然后進(jìn)行重定向,讓瀏覽器跳轉(zhuǎn)到對應(yīng)的長鏈接。首先訪問短鏈接,根據(jù)短鏈接查詢數(shù)據(jù)庫獲取完整長鏈接,返回301或者302,讓瀏覽器重定向到目標(biāo)地址,瀏覽器跳轉(zhuǎn)到長鏈接。

例子:當(dāng)訪問短鏈接,https://域名/xxx時,后端返回了302,同時多了一個Location響應(yīng)頭,值就是原始鏈接地址。

關(guān)于重定向:

  • 301 永久重定向
  • 302 臨時重定向 (很多短鏈生成平臺其實都是走的302重定向)

解決方案:

第一種是對 URL 進(jìn)行hash運算,得到較短的hash值,Murmur哈希就是其中之一。既然是通過哈希函數(shù),就避免不了哈希沖突。雖然這概率很低,但我們設(shè)計系統(tǒng)時需要考慮。

第二種對數(shù)據(jù)存儲,由短鏈接跳轉(zhuǎn)到長鏈接,肯定有必然的關(guān)系,我們需要把他們保存起來,存儲的方式有Redis、Mysql等數(shù)據(jù)庫。

例子:如果是Mysql存儲,表結(jié)構(gòu)大概有(自增id、短鏈接、長鏈接、創(chuàng)建時間)這些字段;我們可以通過生成的短鏈接,查詢數(shù)據(jù)庫是否有存在的短鏈接。不存在,直接存儲;存在,需要二次拼接生成短鏈接,直到不存在為止,進(jìn)行存儲。如果當(dāng)數(shù)據(jù)庫數(shù)據(jù)變多,我們需要優(yōu)化,短鏈接字段需要加唯一性索引。如果再一次優(yōu)化,可以使用布隆過濾器,將新生成的短鏈接在布隆過濾器里進(jìn)行查找,不存在直接插入數(shù)據(jù)庫。

生成短鏈接方法:

  • 根據(jù)唯一自增id后,再轉(zhuǎn)換為62進(jìn)制字符串,生成短鏈接。優(yōu)點:ID唯一,生成的短鏈不會重復(fù)和沖突;缺點:高并發(fā)下有性能瓶頸。
  • 雪花算法。優(yōu)點:高性能;缺點:生成的ID比較長。
  • Redis自增。優(yōu)點:高性能,高并發(fā);缺點:是中間件,有維護(hù)成本。
  • Hash算法,常見有MD5、SHA算法。但這里我們一般采用Google的Murmurhash算法,優(yōu)點:哈希沖突的概率低,速度比MD5快,缺點:有幾率哈希沖突。
<!-- 引包 -->     
<dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <version>31.1-jre</version>
</dependency>
 <!-- 使用 -->    
 public static void main(String[] args) {
   System.out.println(Hashing.murmur3_128().hashString("長鏈接", StandardCharsets.UTF_8));
   System.out.println(Hashing.murmur3_32_fixed().hashString("長鏈接", StandardCharsets.UTF_8));
   System.out.println(Hashing.murmur3_32_fixed().hashLong(Long.MAX_VALUE));
   System.out.println(Hashing.murmur3_128().hashString("長鏈接", StandardCharsets.UTF_8).padToLong());
 }

示例

使用用Hash算法 + Base62 編碼生成短鏈。

數(shù)據(jù)庫表結(jié)構(gòu)

 # 短鏈表
create table `t_short_link`
(
    `id`             bigint primary key auto_increment comment '主鍵ID',
    `short_link`     varchar(32)  not null default '' comment '短鏈接',
    `long_link_hash` bigint       not null default 0  comment  'hash值',
    `long_link`      varchar(128) not null default '' comment '長鏈接',
    `status`         tinyint      not null default 1  comment '狀態(tài):1-可用,0-不可用',
    `expiry_time`    datetime     null comment '過期時間',
    `create_time`    datetime     not null default current_timestamp comment '創(chuàng)建時間'
) comment '短鏈表';
# 創(chuàng)建對應(yīng)的索引
create index idx_sl_hash_long_link on t_short_link (long_link_hash, long_link);
create index idx_sl_short_link on t_short_link (short_link);

工具類

/**
 * 短鏈接 - 工具類
 */
public class Base62Utils {
    private static final int SCALE = 62;
    // 下面的字符,可以隨便打亂,安全性更高
    private static final char[] BASE_62_ARRAY = {
            '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',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
    };
    private static final String BASE_62_CHARACTERS = String.valueOf(BASE_62_ARRAY);
    /**
     * 將long類型編碼成Base62字符串
     * @param num
     * @return
     */
    public static String encodeToBase62String(long num) {
        StringBuilder sb = new StringBuilder();
        while (num > 0) {
            sb.insert(0, BASE_62_ARRAY[(int) (num % SCALE)]);
            num /= SCALE;
        }
        return sb.toString();
    }
    /**
     * 將Base62字符串解碼成long類型
     * @param base62Str
     * @return
     */
    public static long decodeToLong(String base62Str) {
        long num = 0, coefficient = 1;
        String reversedBase62Str = new StringBuilder(base62Str).reverse().toString();
        for (char base62Character : reversedBase62Str.toCharArray()) {
            num += BASE_62_CHARACTERS.indexOf(base62Character) * coefficient;
            coefficient *= SCALE;
        }
        return num;
    }
    public static void main(String[] args) {
        String data = "6s3brYkS9OQp7YpY7RHR+GOJUdp//tdRrVPyiUcuJhJZPaHS9dStwDCdOWNWuHk=";
        Base64.Encoder encoder = Base64.getEncoder();
        System.out.println(encoder.encodeToString(data.getBytes()));
        Base64.Encoder encoder2 = Base64.getUrlEncoder();
        System.out.println(encoder2.encodeToString(data.getBytes()));
        // 編碼 這個編碼后 有 url的特殊字符
        System.out.println(URLEncoder.encode(data));
    }
}

測試方法

@SpringBootTest
public class ShortLinkTest {
    @Autowired(required = false)
    private ShortLinkService shortLinkService;
    // 生成短鏈接
    @Test
    void test1() throws Exception {
        String shortLink = shortLinkService.generateShortLink("https://www.good.com/xxx");
        System.err.println("生成的短鏈為:" + shortLink);
    }
}

Service層

@Service
public class ShortLinkServiceImpl implements ShortLinkService {
    @Autowired(required = false)
    private ShortLinkManager shortLinkManager;
    /**
     * 生成短鏈接
     *
     * @param longLink 長連接
     * @return {@code String}
     */
    @Override
    public String generateShortLink(String longLink) {
        // 使用 Murmurhash算法,進(jìn)行哈希,得到長鏈接Hash值
        long longLinkHash = Hashing.murmur3_32_fixed().hashString(longLink, StandardCharsets.UTF_8).padToLong();
        System.out.println(longLinkHash); 
        // 通過長鏈接Hash值和長鏈接檢索 (查詢數(shù)據(jù)庫里是否唯一)
        String shortLink = "";
        // SQL 模擬操作 getShortLink(長鏈接Hash值,長鏈接) 判定是否唯一
          // SQL ...
        if (StringUtils.isNotBlank(shortLink)) {
            return shortLink;
        }
        // 如果Hash沖突則加隨機(jī)鹽再次Hash
        return regenerateOnHashConflict(longLink, longLinkHash);
    }
    // 參數(shù)1 長連接  參數(shù)2 生成的Hash
    private String regenerateOnHashConflict(String longLink, long longLinkHash) {
        // 這個工具類是 雪花算法的工具類
        SnowFlakeUtils snowFlakeUtil = new SnowFlakeUtils();
        // 雪花算法 生成主鍵id
        long id = snowFlakeUtil.nextId();
        long uniqueIdHash = Hashing.murmur3_32_fixed().hashLong(id).padToLong();
        // 相減主要是為了讓哈希值更小
        String shortLink = Base62Utils.encodeToBase62String(Math.abs(longLinkHash - uniqueIdHash));
        System.out.println("產(chǎn)生更短的短連接" + shortLink);
        // SQL 模擬操作 isShortLinkRepeated(短鏈接) 判定是短鏈接否唯一
          // SQL ... 如果為false 代表 短鏈接不存在表中
        boolean isShort = false;
        if (!isShort) {
             // SQL 模擬操作 saveShortLink 保存表中 (shortLink、longLinkHash、longLink)
               // SQL ... 
            return shortLink;
        }
        // 如果有 短鏈接 重復(fù) 再走一遍
        return regenerateOnHashConflict(longLink, longLinkHash);
    }
}

到此這篇關(guān)于JAVA實現(xiàn)生成短鏈接的示例代碼的文章就介紹到這了,更多相關(guān)JAVA生成短鏈接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論