python3.8.2中文手册chm_springboot2.2.X手册:构建全局唯一的短链接数据中心
溪云閣:專注編程教學,架構,JAVA,Python,微服務,機器學習等領域,歡迎關注,一起學習。
什么是短鏈接
短鏈接,其實這個東西很常見,最早開始的時候小編是在微博上看見的,然后就很好奇這是個什么東西,怎么點進去后網(wǎng)址又辣么長?
其實這個東西就必須按照字面來理解,就是短的鏈接,通過短的鏈接去數(shù)據(jù)庫或者緩存中找到長的鏈接,映射出來即可。
今天我們用redis來實現(xiàn)短鏈接服務,想換存儲介質的同學自行更換。
有哪些場景
1、微博,短信等那些有限制字數(shù)的文案需求
2、用戶角度上來考慮,短鏈接更適合現(xiàn)在的快餐文化
加載包體
<?xml version="1.0"?>4.0.0com.boots boots 1.1.0.RELEASE boots-shorturl boots-shorturlhttp://maven.apache.orgUTF-8com.boots module-boots-api 2.0.0.RELEASEcom.boots module-boots-redis 1.1.0.RELEASE編寫短鏈接工具類
/** * All rights Reserved, Designed By 林溪 * Copyright: Copyright(C) 2016-2020 * Company 溪云閣 . */package com.boots.shorturl.common.utils;import java.util.Random;import java.util.UUID;/** * 短鏈接工具類 * @author:溪云閣 * @date:2020年6月11日 */public class ShortUrlUtils { /** * 獲取短鏈接 * @author 溪云閣 * @param host 請求的URL解析出來的域名信息 * @param length 自定義你需要的短鏈接長度 * @return String 返回的短鏈接 */ public static String getShortUr(int length) { // 定義偏移量,每6個生成一個字符 final int PER_VARCHAR = 6; // 定義數(shù)字+大小寫字母的字符數(shù)組 final char[] c = 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' }; // 2的35次方,每五位一個字符,可生成7個字符 final long long16 = (long) Math.pow(2, PER_VARCHAR * length) - 1; // 生成的隨機數(shù)里面存在-的話直接用空空字符串替代 final String a = UUID.randomUUID().toString().replace("-", ""); // 生成隨機數(shù),使之成為35長度 final Random random = new Random(); // 每8字符=32位,加3位=111 final int nextInt = random.nextInt(8); // 偏移起始位置 int subIndexStart = 0; // 定義需要返回的短鏈接后綴 final StringBuffer sb = new StringBuffer(); while (subIndexStart < a.length()) { // 8位一組,使用16進行轉換,可轉換成 4*8=32長度二進制 final String substring = a.substring(subIndexStart, subIndexStart += 8); final long parseLong = Long.parseLong(nextInt + substring, 16); long x = long16 & parseLong; for (int j = 0; j < length; j++) { final long x2 = c.length - 1 & x; sb.append(c[(int) x2]); x = x >> PER_VARCHAR; } return sb.toString(); } return null; }}編寫URL工具類
/** * All rights Reserved, Designed By 林溪 * Copyright: Copyright(C) 2016-2020 * Company 溪云閣 . */package com.boots.shorturl.common.utils;import java.net.URI;import java.net.URISyntaxException;import java.net.URL;import java.util.regex.Matcher;import java.util.regex.Pattern;import com.module.boots.exception.CommonRuntimeException;/** * 校驗工具類 * @author:溪云閣 * @date:2020年6月11日 */public class UrlsUtils { /** * 驗證是否是URL * @param url * @return */ public static boolean verifyUrl(String url) { // URL驗證規(guī)則 final String regEx = "[a-zA-z]+://[^s]*"; // 編譯正則表達式 final Pattern pattern = Pattern.compile(regEx); // 忽略大小寫的寫法 // Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE); final Matcher matcher = pattern.matcher(url); // 字符串是否與正則表達式相匹配 final boolean rs = matcher.matches(); return rs; } /** * 獲取域名 * @author 溪云閣 * @param address 網(wǎng)址 * @return String * @throws URISyntaxException */ public static String getHost(String address) { String host = ""; try { final URL url = new URL(address); final URI uri = url.toURI(); host = uri.getScheme() + "://" + url.getHost(); } catch (final Exception e) { throw new CommonRuntimeException(e.fillInStackTrace()); } return host; }}編寫服務接口
/** * All rights Reserved, Designed By 林溪 * Copyright: Copyright(C) 2016-2020 * Company 溪云閣 . */package com.boots.shorturl.view.shorturl.view;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import com.boots.shorturl.common.utils.ShortUrlUtils;import com.boots.shorturl.common.utils.UrlsUtils;import com.module.boots.api.message.ResponseMsg;import com.module.boots.api.utils.MsgUtils;import com.module.boots.exception.CommonRuntimeException;import com.module.boots.redis.RedisUtils;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import lombok.SneakyThrows;/** * 短鏈接服務 * @author:溪云閣 * @date:2020年6月11日 */@Api(tags = { "web服務:短鏈接服務接口" })@RestController@RequestMapping("view/shortUrl")public class ShortUrlView { @Autowired private RedisUtils redisUtils; /** * 生成短鏈接 * @author 溪云閣 * @param url 長連接地址 * @return * @throws Exception ResponseMsg */ @ApiOperation(value = "生成短鏈接") @PostMapping(value = "/generateShortUrl") @SneakyThrows(CommonRuntimeException.class) public ResponseMsg generateShortUrl(@RequestParam("url") String url) { // 判斷是否為網(wǎng)址 if (UrlsUtils.verifyUrl(url)) { // 生成6位數(shù)的隨機短鏈接后綴 final String suffix = ShortUrlUtils.getShortUr(6); // 生成完整的短鏈接 final String shortUrl = UrlsUtils.getHost(url) + "/" + suffix; // 把短鏈接設置到Redis,這里為了方便,直接把短鏈接作為KEY,也可以把后綴作為key redisUtils.set(shortUrl, url); // 返回短鏈接地址 return MsgUtils.buildSuccessMsg(shortUrl); } else { return MsgUtils.buildFailureMsg("網(wǎng)址不合法"); } } /** * 獲取長連接 * @author 溪云閣 * @param url * @return ResponseMsg */ @ApiOperation(value = "獲取長鏈接") @PostMapping(value = "/getLongUrl") @SneakyThrows(CommonRuntimeException.class) public ResponseMsg getLongUrl(@RequestParam("url") String url) { // 判斷是否為網(wǎng)址 if (UrlsUtils.verifyUrl(url)) { // 返回長鏈接地址 return MsgUtils.buildSuccessMsg(redisUtils.get(url)); } else { return MsgUtils.buildFailureMsg("網(wǎng)址不合法"); } }}配置redis地址
# redis地址spring.redis.host: 127.0.0.1# redis端口號spring.redis.port: 6379# redis密碼,如果沒有不用填寫,建議還是得有spring.redis.password: 123456# 最大活躍連接數(shù),默認是8spring.redis.lettuce.pool.maxActive: 100# 最大空閑連接數(shù) ,默認是8spring.redis.lettuce.pool.maxIdle: 100# 最小空閑連接數(shù) ,默認是0spring.redis.lettuce.pool.minIdle: 0測試
調用生成短鏈接接口
獲取長鏈接接口
查看redis中數(shù)據(jù)
從測試結果上看,短鏈接按照我們的需求已經(jīng)生成,并且存到redis中去,一個簡單的短鏈接服務完成。
后續(xù)的拓展各位同學可以根據(jù)需要進行拓展,這里不做標準。
拓展
1、目前采用6位數(shù)的短鏈接,可以產(chǎn)生56800235584個短鏈接,不夠的話,可以采用7位的,62的7次方個
2、目前采用redis存儲,用set存儲的話,最多只能存儲40多億個,可以根據(jù)不同需求加入不同過期時間
3、目前按照6位數(shù)的生成方案,按照一個數(shù)據(jù)或者字符為1個字節(jié)來算,一個短鏈接就有6個字節(jié),短鏈接單量的話接近2T數(shù)據(jù),再加上長鏈接的數(shù)據(jù),在增長到一定程度后,需要引入大數(shù)據(jù)存儲,一般情況下,超過500萬的數(shù)據(jù)就要開始引入。
--END--
作者:@溪云閣
原創(chuàng)作品,抄襲必究
如需要源碼,轉發(fā),關注后私信我
部分圖片或代碼來源網(wǎng)絡,如侵權請聯(lián)系刪除,謝謝!
歷史文章:
springboot2.2.X手冊:放棄fastdfs,整合Minio做文件服務器真香
springboot2.2.X手冊:分布式系統(tǒng)下,重復提交的解決方案
springboot2.2.X手冊:Easypoi導出excel,最新版的手感香不香?
springboot2.2.X手冊:項目從100M瘦身到100K,部署省事多了!
springboot2.2.X手冊:redis的7種類型100個方法全解析
springboot2.2.X手冊:是時候用Lettuce替換Jedis操作Redis緩存了
springboot2.2.X手冊:構建多元化的API接口,我們這樣子設計
springboot2.2.X手冊:基于Jasypt的JavaConfig方式敏感信息加密
springboot2.2.X手冊:整合最新版MybatisPlus 3.3.1版本
springboot2.2.X手冊:對象復制哪種最快?7種復制方式性能對比
springboot2.2.X手冊:基于OSS解決文件存儲(一年9元^^,賺了)
springboot2.2.X手冊:36個注解詳細解析,一目了然
總結
以上是生活随笔為你收集整理的python3.8.2中文手册chm_springboot2.2.X手册:构建全局唯一的短链接数据中心的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: ts获取服务器数据_基于Nginx的媒体
- 下一篇: 微软第一方大作退出XGP!官方回应:授权
