分享短链接实战

现在很多应用中进行分享的链接都是短链接,如下图所示

 为什么要使用短链接呢?

因为正常链接一般很长,用我的博客地址举例,https://blog.csdn.net/hollycloud/article/details/120759185,可以看到一长串,而这个已经算短的了,很多地址更长,而微博和Twitter都有140字数的限制,如果分享一个长网址,很容易就超出限制,发不出去。短网址服务可以把一个长网址变成短网址,方便在社交网络上传播。而且每条短信也有字数限制,如果网址太长就只能分两条短信发了,浪费资源。

短链接生成算法有很多种,今天我们就使用最简单的方式,通过累加获取一个唯一值,然后通过Base62编码来生成短链接,Base62是由数字和大小字母组成,跟Base64相比没有特殊字符,特别合适生成链接。生成完链接后把短链接和长链接的对应关系存入redis,等访问的时候取出来跳转就可以了。

@RestController
@Api(tags = "短链接")
public class ShortUrlController extends BaseController {
    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/shortUrl/encode")
    @ApiOperation(value = "生成短链接")
    public Result encode(String url) {
        //初始化计数器
        redisTemplate.opsForValue().setIfAbsent("shorturl:count", 100000);
        //计数累加
        long count = redisTemplate.opsForValue().increment("shorturl:count");
        //通过base62编码生成短链接
        String shortUrl = Base62.encode(HexUtils.removeLeftZero(HexUtils.long2bytes(count)));
        //记录短链接与长链接的对应关系
        redisTemplate.opsForHash().put("shortUrl:map", shortUrl, url);
        return resultOk("http://localhost:8087/t/" + shortUrl);
    }

    @GetMapping("/t/{shortUrl}")
    @ApiOperation(value = "跳转")
    public void decode(@PathVariable String shortUrl, HttpServletResponse response) {
        //取出长链接跳转
        String url = (String) redisTemplate.opsForHash().get("shortUrl:map", shortUrl);
        try {
            response.sendRedirect(url);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/**
 *  long数字转成8字节byte数组
 * @param num
 * @return
 */
public static byte[] long2bytes(long num) {
    byte[] bytes = new byte[8];
    for (int ix = 0; ix < Long.BYTES; ++ix) {
        int offset = Long.SIZE - (ix + 1) * Byte.SIZE;
        bytes[ix] = (byte) ((num >> offset) & 0xff);
    }
    return bytes;
}

/**
 * 去除左边为0的字节
 * @param bytes
 * @return
 */
public static byte[] removeLeftZero(byte[] bytes) {
    List<Byte> list = new ArrayList();
    boolean filter = true;
    for (int i = 0; i < bytes.length; i++) {
        if (filter) {
            if (bytes[i] == 0) {
                continue;
            } else {
                list.add(bytes[i]);
                filter = false;
            }
        } else {
            list.add(bytes[i]);
        }
    }
    byte[] result = new byte[list.size()];
    for (int i = 0; i < list.size(); i++) {
        result[i] = list.get(i);
    }
    return result;
}

演示:

调用接口返回短链接

 浏览器里面输入短链接

成功跳转到我的博客


版权声明:本文为ting4937原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。