前言

短网址就是将一个长网址转换成一个短网址,访问短网址会重定向到原来的长网址,短网址会更利于传播和推广。微博就会将我们发的长网址转换成短网址,

显示效果

查看HTML源码

实现

通过发号策略,每次来一个长网址,发一个号,这里我们使用SnowFlake(雪花算法)实现发号,然后转成62进制。

雪花算法

/**

* 分布式Id生成器-雪花算法

*/

public class SnowFlake {

/**

* 起始的时间戳

*/

private final static long START_STMP = 1480166465631L;

/**

* 每一部分占用的位数

*/

private final static long SEQUENCE_BIT = 12; //序列号占用的位数

private final static long MACHINE_BIT = 5; //机器标识占用的位数

private final static long DATACENTER_BIT = 5;//数据中心占用的位数

/**

* 每一部分的最大值

*/

private final static long MAX_DATACENTER_NUM = ~(-1L << DATACENTER_BIT);

private final static long MAX_MACHINE_NUM = ~(-1L << MACHINE_BIT);

private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);

/**

* 每一部分向左的位移

*/

private final static long MACHINE_LEFT = SEQUENCE_BIT;

private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;

private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;

private long datacenterId; //数据中心

private long machineId; //机器标识

private long sequence = 0L; //序列号

private long lastStmp = -1L;//上一次时间戳

public SnowFlake(long datacenterId, long machineId) {

if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {

throw new IllegalArgumentException(

"datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");

}

if (machineId > MAX_MACHINE_NUM || machineId < 0) {

throw new IllegalArgumentException(

"machineId can't be greater than MAX_MACHINE_NUM or less than 0");

}

this.datacenterId = datacenterId;

this.machineId = machineId;

}

/**

* 产生下一个ID

*/

public synchronized long nextId() {

long currStmp = getNewstmp();

if (currStmp < lastStmp) {

throw new RuntimeException("Clock moved backwards. Refusing to generate id");

}

if (currStmp == lastStmp) {

//相同毫秒内,序列号自增

sequence = (sequence + 1) & MAX_SEQUENCE;

//同一毫秒的序列数已经达到最大4096

if (sequence == 0L) {

currStmp = getNextMill();

}

} else {

//不同毫秒内,序列号置为0

sequence = 0L;

}

lastStmp = currStmp;

return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分

| datacenterId << DATACENTER_LEFT //数据中心部分

| machineId << MACHINE_LEFT //机器标识部分

| sequence; //序列号部分

}

private long getNextMill() {

long mill = getNewstmp();

while (mill <= lastStmp) {

mill = getNewstmp();

}

return mill;

}

private long getNewstmp() {

return System.currentTimeMillis();

}

public static void main(String[] args) {

SnowFlake snowFlake = new SnowFlake(2, 3);

for (int i = 0; i < (1 << 12); i++) {

System.out.println(snowFlake.nextId());

}

}

}

转62进制

/**

* 进制转换工具,最大支持十进制和62进制的转换

* 1、将十进制的数字转换为指定进制的字符串;

* 2、将其它进制的数字(字符串形式)转换为十进制的数字

*/

public class NumericConvertUtils {

/**

* 在进制表示中的字符集合,0-Z分别用于表示最大为62进制的符号表示

*/

private static final char[] digits = {'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'};

/**

* 将十进制的数字转换为指定进制的字符串

*

* @param number 十进制的数字

* @param seed 指定的进制

* @return 指定进制的字符串

*/

public static String toOtherNumberSystem(long number, int seed) {

if (number < 0) {

number = ((long) 2 * 0x7fffffff) + number + 2;

}

char[] buf = new char[32];

int charPos = 32;

while ((number / seed) > 0) {

buf[--charPos] = digits[(int) (number % seed)];

number /= seed;

}

buf[--charPos] = digits[(int) (number % seed)];

return new String(buf, charPos, (32 - charPos));

}

/**

* 将其它进制的数字(字符串形式)转换为十进制的数字

*

* @param number 其它进制的数字(字符串形式)

* @param seed 指定的进制,也就是参数str的原始进制

* @return 十进制的数字

*/

public static long toDecimalNumber(String number, int seed) {

char[] charBuf = number.toCharArray();

if (seed == 10) {

return Long.parseLong(number);

}

long result = 0, base = 1;

for (int i = charBuf.length - 1; i >= 0; i--) {

int index = 0;

for (int j = 0, length = digits.length; j < length; j++) {

//找到对应字符的下标,对应的下标才是具体的数值

if (digits[j] == charBuf[i]) {

index = j;

}

}

result += index * base;

base *= seed;

}

return result;

}

}

将一个long型数字转成包含0-9,A-Z,a-z共62个字符的62进制字符串。将生成的字符串和短网址服务器域名连接即为最终的短网址,如https://t.cn/FWSc3ki8mY

public class Main {

public static void main(String[] args) {

SnowFlake snowFlake = new SnowFlake(0, 0);

for (int i = 0; i < 10; i++) {

System.out.println(NumericConvertUtils.toOtherNumberSystem(snowFlake.nextId(), 62));

}

}

}

输出结果为

FWSc3ki8mY

FWSc3ki8mZ

FWSc3ki8n0

FWSc3ki8n1

FWSc3ki8n2

FWSc3ki8n3

FWSc3ki8n4

FWSc3ki8n5

FWSc3ki8n6

FWSc3ki8n7

整体流程

利用发号器创建短网址,保存长网址和短网址的映射关系到数据库或Redis。

短网址服务器接收到请求,根据 FWSc3ki8mY 找到原来的长网址,返回302,告诉浏览器重定向到长网址。

待优化地方

现在的实现对于同一个长网址,每次创建的短网址也是不同的,如果每次创建前去数据库查询的话,效率太低,可以使用 LRU 缓存最近的N次映射结果,先查缓存,再查数据库,兼顾了空间和性能。

参考

标签:java,进制,URL,生成器,number,long,网址,seed,static

来源: https://www.cnblogs.com/strongmore/p/14527890.html

url短网址 java,java实现一个短URL生成器相关推荐

  1. 类的别名java,类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。例如:typeAliases typeAlias ali...

    类型别名是为 Java 类型设置一个短的名字. 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余.例如: 当这样配置时,Blog 可以用在任何使用 domain.blog.Blog ...

  2. PHP短网址生成系统/短链接生成系统/URL缩短器系统源码免费下载

    源码介绍: 没有教程.我也没有测试 全新PHP短网址系统URL缩短器平台,它使您可以轻松地缩短链接, 根据受众群体的位置或平台来定位受众,并为缩短的链接提供分析见解. 系统使用了Laravel框架编写 ...

  3. 新浪短网址生成java_新浪短链接 推荐几个最新的新浪t.cn短链接生成的API接口

    新浪很久之前提供了长链接转为短链接的公开API,可以把长链接转为t.cn/xxx这种格式的新浪短链接.但是在去年9月的时候,新浪由于政策上的调整,将之前的接口关闭了! 今天就给大家带来几个还可以使用新 ...

  4. 短网址 php mysql_PHP+MySQl实现短网址生成器的几种代码

    短网址的实现原理就是有一个数据表会配置文件将短网址和实际网址进行对应,当请求某个短网址时,程序跳转到对应的实际网址上去,从而实现网址的访问. PHP+MySQl实现短网址的生成和读取 常规的方案我们将 ...

  5. 腾讯短网址在线生成(url.cn短网址) 2020最新腾讯短网址生成api接口推荐

    短网址生成指的是把帮您把冗长的URL地址缩短成8个字符以内的短网址.目前市面上的短网址品牌很多很多,但是最常见的还是下面说的几种: 腾讯短链接:url.cn 淘宝短链接:c.tb.cn 新浪短链接:t ...

  6. 2021全新PHP短网址生成系统/短链接生成系统/URL缩短器系统源码/站长亲测

    简介: 全新PHP短网址系统URL缩短器平台,它使您可以轻松地缩短链接,根据受众群体的位置或平台来定位受众,并为缩短的链接提供分析见解. 系统使用了laravel框架编写,前后台双语言使用,可以设置多 ...

  7. 百度短网址api java_Java调用百度短网址生成短链接

    1. 方式一 直接在线生成 2. 方式二 调用接口生成 引入gson-2.8.5.jar 可以通过maven仓库搜索下载地址 import com.google.gson.annotations.Se ...

  8. 新浪短网址api接口 - t.cn 短链接生成

    简要描述 新浪短网址api接口是新浪官方对外公开的t.cn短链接生成接口,可以将一个冗长的链接缩短生成t.cn/xxxx 格式的短链接. 应用场景 短网址的应用场景很广,譬如短信营销.邮件推广.微信营 ...

  9. PHP实现短网址规则,使用PHP生成短网址的方案

    短网址的实现原理就是有一个数据表会配置文件将短网址和实际网址进行对应,当请求某个短网址时,程序跳转到对应的实际网址上去,从而实现网址的访问. 方案1:PHP+MySQl实现短网址的生成和读取 常规的方 ...

  10. php短网址程序,php中生成短网址实现程序代码

    生成短网址我们可以直接使用一个函数来生成一个唯一的长度为5-6字符的地址,但是我们还需要做一点就是直接利用为静态做跳转,下面我来给大家介绍. 生成短网址程序  代码如下 复制代码 function c ...

最新文章

  1. mysql 联合索引长度_MySQL 中索引的长度的限制
  2. ORA-07445 [kkoipt()+3881] [SIGSEGV] [Address not mapped to object] 问题
  3. 基于verilog的洗衣机设计
  4. 【牛客 - 369A】小D的剧场(线性dp)
  5. 知道这些用于数据科学和机器学习的GitHub存储库和Reddit主题吗?
  6. 如何在SQL Server Reporting Services中自动创建KPI
  7. ansible之安装与简单使用
  8. C++基础:什么是数据库?如何创建一个表?
  9. 8个习惯让你减肥不用节食 - 生活至上,美容至尚!
  10. 20190906每日一句
  11. 部分计算机会议和期刊论文的下载方法
  12. Django使用pyjwt实现Token跨域认证登录过程实践
  13. 用知识图谱解读抑郁症——树洞
  14. 快让你的App分20亿吧!
  15. AMD CPU 开启Android Studio emulator虚拟机
  16. vscode下载太慢,快速下载vscode方法!
  17. 弱电计算机网络系统技术交底,弱电综合布线施工技术交底.doc
  18. MVP注册登录和XListView刷新加载
  19. 配置小程序项目的第一个页面—小程序入门与实战(五)
  20. 推荐系统论文阅读——Factorizing Personalized Markov Chains for Next-Basket Recommendation

热门文章

  1. [附源码]JAVA+ssm计算机毕业设计村务管理系统(程序+Lw)
  2. android手机截图gif,bash 一键录屏 Android 生成 gif 文件脚本
  3. 爬虫回响521_爬虫遇到521错误怎么办
  4. acacm icpc java_Java在acm-icpc的应用
  5. 计算机网络技术大几用电脑,大一计算机网络技术论文
  6. 电路板焊锡质量视觉检测方案测试
  7. 同步和异步的区别及优缺点
  8. [附源码]Python计算机毕业设计SSM基于售楼系统(程序+LW)
  9. 三菱PLC通过ALTP和CJ指令实现暂停功能的具体方法及程序示例
  10. 会声会影2022序列号有哪些新功能