问题引出
在生活中有很多场景需要把长链接转化为短连接,比如微博限制字数为140字一条,那么如果我们需要发一些链接上去,但是这个链接非常的长,以至于将近要占用我们内容的一半篇幅,这肯定是不能被允许的,所以短链接应运而生了。
又比如短信的链接都是处理后的短链接,如果链接很长,也会影响短信的阅读体验。
实际是长链接
代码实现
这里我们采用Redis存储短链接。
我们先来定义几个常量
代码语言:javascript复制private static final String SHORT_URL_KEY = "SHORT_URL_KEY";
private static final String LOCALHOST = "http://t.cn/";
private static final String SHORT_LONG_PREFIX = "short_long_prefix_";
private static final String CACHE_KEY_PREFIX = "cache_key_prefix_";
private static final int CACHE_SECONDS = 1 * 60 * 60;
final static 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'
};
SHORT_URL_KEY
是短链末尾的值。LOCALHOST
是短链的前缀。
「从Redis里获取短链接」
代码语言:javascript复制public String getShortUrl(String longUrl, Decimal decimal) {
String cache = redisTemplate.opsForValue().get(CACHE_KEY_PREFIX longUrl);
if (cache != null) {
log.info("从缓存【{}】中获取到:{}",CACHE_KEY_PREFIX longUrl,cache);
return LOCALHOST toOtherBaseString(Long.valueOf(cache), decimal.x);
}
Long num = redisTemplate.opsForValue().increment(SHORT_URL_KEY);
redisTemplate.opsForValue().set(SHORT_LONG_PREFIX num, longUrl);
redisTemplate.opsForValue().set(CACHE_KEY_PREFIX longUrl, String.valueOf(num), CACHE_SECONDS, TimeUnit.SECONDS);
return LOCALHOST toOtherBaseString(num, decimal.x);
}
num
通过「Redis」的原子自增获取,每生成一个链接这里就加1。
「转码方式」
代码语言:javascript复制private String toOtherBaseString(long n, int base) {
long num = 0;
if (n < 0) {
num = ((long) 2 * 0x7fffffff) n 2;
} else {
num = n;
}
char[] buf = new char[32];
int charPos = 32;
while ((num / base) > 0) {
buf[--charPos] = digits[(int) (num % base)];
num /= base;
}
buf[--charPos] = digits[(int) (num % base)];
return new String(buf, charPos, (32 - charPos));
}
将10进制转换成其他进制。我们来对这个方法做个测试。
代码语言:javascript复制@Test
public void testToString() {
int n = 568002355;
int base = 64;
String s = toOtherBaseString(n, base);
System.out.println(s);
}
「测试」
代码语言:javascript复制@Test
public void testShortUrl() {
String url = "www.google.com";
String shortUrl = shortUrlUtil.getShortUrl(url, ShortUrlUtil.Decimal.D64);
System.out.println("短链:" shortUrl);
}
我们将www.google.com
转化为短链接
转成的短链接如图所示
代码语言:javascript复制短链:http://t.cn/4
SHORT_URL_KEY
的值为4,代表短链末尾的值为4。
而对应长链存储在这里。
这样同一长链每次生成的短链是一样的。
再运行一次,显示的短链还是一样。
采用Redis原子自增生成短链,即使是在分布式环境下也不会重复。利用Redis生成在高并发下也会有很好的性能。