URL缩短器:详细说明
xsobi 2025-04-29 06:14 10 浏览
介绍
URL缩短器是一种用于从非常长的URL创建短链接的服务。通常,短链接的大小是原始URL的三分之一甚至四分之一,这使得它们更易于键入,呈现或发布。单击短链接用户将自动重定向到原始URL。
在线提供许多URL缩短服务,例如tiny.cc,bitly.com,cutt.ly等。实现URL缩短服务并不是一项复杂的任务,并且通常是系统设计方面的一部分。在这篇文章中,我将尝试解释实现服务的过程。
理论
在实施之前,最好以功能和非功能需求的形式分清楚需要完成的工作。
功能要求:
- 用户需要能够输入长网址。我们的服务应保存该URL并生成一个短链接
- 用户应该可以选择输入到期日期。在该日期之后,短链接应无效
- 单击短链接应将用户重定向到原始长URL
- 用户应创建一个帐户以使用服务。服务可以有每个用户的使用限制*
- 允许用户创建自己的短链接*
- 服务应具有指标,例如访问最多的链接*
非功能需求:
- 服务应已启动并正在运行100%的时间
- 重定向的时间不应超过两秒
网址转换
假设我们要有一个最大长度为7的短链接。URL缩短器中最重要的是转换算法。URL转换可以通过几种不同的方式实现,每种方式各有利弊。
生成短链接的一种方法是使用某种哈希函数(例如MD5 或SHA-2)哈希原始URL 。使用哈希函数时,请确保不同的输入将导致不同的输出。哈希的结果超过七个字符,因此我们需要获取前七个字符。但是,在这种情况下,可能会发生冲突,因为前七个字符可能已经用作短链接。然后,我们接下来的七个字符,直到找到未使用的短链接。
生成短链接的第二种方法是使用UUID。UUID将被复制的概率不为零,但它足够接近零而可以忽略不计。由于UUID包含36个字符,这意味着我们遇到了与上述相同的问题。我们应该采用前七个字符,并检查该组合是否已被使用。
第三种方式是将数字从基数10转换为基数62。基数是可用于表示特定数字的许多数字或字符。以10为基数的数字是[0-9],我们在日常生活中使用的数字是以0为基数的数字[0-9] [az] [AZ]。这意味着,例如,以10为底的四位数数字将以以62为底的相同数字,但带有两个字符。
在URL转换中使用基数62,最大长度为7个字符,这使我们可以为短链接提供62 ^ 7个唯一值。
Base 62转换如何工作
我们有一个以10为底的数字,我们想要转换以62为底的数字。我们将使用以下算法:
while(number > 0)
remainder = number % 62
number = number / 62
//将余数附加到结果收集的开始
之后,我们只需要将结果集中的数字映射到以62为基础的字母= [0,1,2,...,a,b,c ...,A,B,C,...]。
让我们用一个真实的例子看看它是如何工作的。在此示例中,让我们将1000从10转换为62。
1st iteration:
number = 1000
remainder = 1000 % 62 = 8
number = 1000 / 62 = 16
result list = [8]
2nd iteration:
number = 16
remainder = 16 % 62 = 16
number = 16 / 62 = 0
result list = [16,8]
There is no more iterations since number = 0 after 2nd iteration
将[16,8]映射到基数62将是g8。这意味着1000 base10 = g8 base62。
从基础62转换为基础10也很简单:
i = 0
while(i < inputString lenght)
counter = i + 1
mapped = base62alphabet.indexOf(inputString[i])
//根据字母索引将字符映射到数字
result = result + mapped * 62^(inputString lenght - counter)
i++
真实的例子:
inputString = g8
inputString length = 2
i = 0
result = 0
1st iteration
counter = 1
mapped = 16 // base62alphabet中g的索引是16
result = 0 + 16 * 62^1 = 992
2nd iteration
counter = 2
mapped = 8 // base62alphabet中8的索引是8
result = 992 + 8 * 62^1 = 1000
实作
我将使用数据库的自动增量功能。自动递增的数字将用于以62为基数的转换。也可以使用任何其他具有自动增量功能的数据库。
首先,访问Spring初始化程序,然后选择Spring Web和MySql Driver。之后,单击“ 生成”按钮,然后下载zip文件。解压缩文件,然后在您喜欢的IDE中打开项目。每次启动新项目时,我都喜欢创建一些文件夹来按逻辑划分代码。在这种情况下,我的文件夹是controller,entity,service,repository,dto和config。
里面的实体文件夹,让我们创建一个Url.java有四个属性类:id,longUrl,createdDate,expiresDate。
请注意,没有短链接属性。每当有GET请求时,我们就将id属性从10转换为62。这样,我们可以节省数据库空间。
该LongUrl属性是我们应该重定向到当一个用户访问一个短链接的URL。创建日期仅用于查看longUrl保存的时间(这并不重要),expiresDate如果用户希望在一段时间后使短链接不可用,则创建日期在此处。
接下来,让我们在服务文件夹中创建BaseService.java。包含从10转换为62的方法,反之亦然。
private static final String allowedString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private char[] allowedCharacters = allowedString.toCharArray();
private int base = allowedCharacters.length;
就像我之前提到的,如果要使用基数为62的转换,则需要有一个基数为62的字母,在这种情况下称为allowedCharacters。另外,base如果我们要更改允许的字符,则从允许的字符的长度计算出变量的值。
该encode方法以数字作为输入并返回短链接。该decode方法将字符串(短链接)作为输入并返回数字。该算法应按照上面的说明进行实施。
然后,在存储库文件夹中,创建一个UrlRepository.java文件,该文件只是的扩展JpaRepository。它为我们提供了很多方法,例如findById,save等。我们无需为此添加任何其他内容。
然后,让我们在controller文件夹中创建一个UrlController.java文件。控制器应具有一种用于创建短链接的POST方法和一种用于重定向至原始URL的GET方法。
@PostMapping("create-short")
public String convertToShortUrl(@RequestBody UrlLongRequest request) {
return urlService.convertToShortUrl(request);
}
@GetMapping(value = "{shortUrl}")
public ResponseEntity<Void> getAndRedirect(@PathVariable String shortUrl) {
var url = urlService.getOriginalUrl(shortUrl);
return ResponseEntity.status(HttpStatus.FOUND)
.location(URI.create(url))
.build();
}
POST方法将UrlLongRequest作为其请求正文。它只是具有longUrl和expiresDate属性的类。
GET方法将短URL作为路径变量,然后获取并重定向到原始URL。在控制器的顶部,作为依赖项UrlService 被注入,接下来将对其进行说明。
UrlService.java是大多数逻辑所在的位置,并且是控制器使用的服务。ConvertToShortUrl由控制器的POST方法使用。它只是在数据库中创建一条新记录并获取一个ID。然后将该id转换为以62为基础的短链接,并返回给控制器。
GetOriginalUrl是控制器的GET方法使用的方法。它首先将字符串转换为以10为底的字符串,其结果是一个id。然后,它通过该ID从数据库中获取一条记录,如果不存在则抛出异常。之后,它将原始URL返回给控制器。
结论
URL缩短服务是一种简单的服务,它需要较长的URL并将其转换为短链接。访问该链接后,用户将被重定向到原始URL。
相关推荐
- C/C++编程笔记:C++中的函数重载(c++如何实现函数重载)
-
函数重载是C++中的一项功能,其中两个或多个函数可以具有相同的名称,但可以具有不同的参数。当函数名称因不同的作业而被重载时,称为函数重载。在函数重载中,“函数”的名称应相同,而参数则应不同。函数重载...
- C/C++编程笔记:C++中的运算符重载
-
在C++中,我们可以使运算符为用户定义的类工作。这意味着C++能够为运算符提供数据类型的特殊含义,这种能力称为运算符重载。例如,我们可以在String之类的类中重载运算符'+',以...
- 变频器如何区分重载和轻载?我们应该如何进行选择?
-
在选择变频器的过程中,重载和轻载是两个非常重要的参数。它是我们选择变频器的先决条件。1、那什么是轻型负载,轻型负载有哪些特征?轻载典型特征就是能拖动同等功率的负载,但是它的输出转距较小。像我们经常用到...
- 面试官:Java的重写和重载有什么区别?
-
先来看一段重写的代码吧。class LaoWang{ public void write() { &...
- Idea项目的创建和模块的导入Java中方法的三种调用方式和方法重载
-
一:如何创建工程和模块File-->New-->Project...EemptProject-->Next输入Finish-->Ok-->NewWindow关闭刚创建...
- C# - 构造方法重载与调用,析构方法(*) 068
-
构造方法重载普通方法构成重载的规则:方法名称一样,对应位置参数的类型或个数不同可以构成方法重载而构造方法的构成规则与此一样注意事项:如果方法的访问修饰符是private(还有其他的访问修饰符之后再说)...
- Java方法的重载与重写详解(java方法重载的规则是哪些)
-
1.方法的重载1.1.基本介绍在同一个类中,允许多个重名方法的存在,但要求形参列表不一致。比如:System.out.println(11)//输出整数System.out.println(...
- Go如何优雅的解决方法的重载(golang 优雅重启)
-
1、问题你是否曾经见过这样的代码funcHandler(){//...}funcHandler(timeOuttime.Duration){//..}fu...
- 你知道Java方法重载的本质吗?(java的方法重载是什么意思)
-
背景考大家一道题目,下面的类执行结果是什么???publicclassDispatcherClient{publicstaticvoidmain(String[]args)...
- Java方法重载&栈的了解(java方法重载有什么用)
-
函数的重载1.函数重载重载:在同一个类中,允许存在一个以上的同名函数,只要他们的参数个数或者参数类型不同即可。看一下示例:实例中函数名都为add,但是参数表(圆括号中的参数类型+形参)中的参数类型或者...
- 初学java常见问题:Java方法的重载是咋回事?
-
前言小千在之前给大家讲解构造方法的时候说过,在一个类中,可以定义多个构造方法,这叫做方法的重载!但是关于方法重载,具有有哪些要求和细节?很多小白还并不清楚,所以在今天的这篇文章中,小千给大家详细说说方...
- C#基础之方法重载(c# 重载运算符)
-
在具有相同名称但具有不同参数列表的类中定义多个方法时。此方法参数在参数的数量、类型和顺序上必须不同。这称为方法重载。方法重载是多态性的一种形式。C#中的方法重载方法重载的语法:以下是在C#中使用方...
- 观察者模式-Java实现(观察者模式实例)
-
介绍观察者模式的使用场景非常广泛,小到代码层面的解耦,达到架构层面的系统解耦,再或者到一些产品的设计思路,都有这种模式的影子。现在我们常说的基于事件驱动的架构,其实也是观察者模式的一种最佳实践。当我们...
- 如何使用Go实现观察者模式(观察者模式的使用场景)
-
#从今天起记录我的2023##头条创作挑战赛#观察者模式是一种设计模式,它允许对象之间的松散耦合,因为这些对象不需要知道彼此的细节信息,只需要知道如何通知其他对象,以便它们可以做出相应的响应。在g...
- JAVA实现观察者模式,其实真的很简单
-
#头条创作挑战赛#概述观察者模式,又叫发布/订阅模式(Publish-Subscribe)。定义对象之间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于他的对象都会收到通知并且执行对应的...
- 一周热门
- 最近发表
- 标签列表
-
- grid 设置 (58)
- 移位运算 (48)
- not specified (45)
- 导航栏 (58)
- context xml (46)
- scroll (43)
- dedecms模版 (53)
- c 视频教程下载 (33)
- listview排序 (33)
- characterencodingfilter (33)
- getmonth (34)
- label换行 (33)
- android studio 3 0 (34)
- html转js (35)
- 索引的作用 (33)
- checkedlistbox (34)
- xmlhttp (35)
- mysql更改密码 (34)
- 权限777 (33)
- htmlposition (33)
- 学校网站模板 (34)
- textarea换行 (34)
- 轮播 (34)
- asp net三层架构 (38)
- bash (34)