java-URL短连接的生成(保证生成的唯一性)

导读:本篇文章讲解 java-URL短连接的生成(保证生成的唯一性),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

业务场景:

短信平台发送带有跳转链接的短信时,会存在一个问题,有的时候链接会特别长,而且可能会有一些特殊字符,影响点:

  • 这样手机的短信会将链接会切开来,直接点击无法跳转.
  • 复制粘贴时浏览器可能无法将其直接跳转,会将其默认为搜索条件而不是链接地址来跳转.

正是以上的这些原因(只是一小部分的原因),就衍生了短连接的生成这个需求

短链接的生成方式:

  • 加密方式:
    最简单的办法就是通过MD5方式来加密,也是目前网上最多的一种实现方式,我也是借鉴了其方法,不过亲测高并发下无法支持其生成的唯一性,可能引起短连接地址不唯一,导致bug.
    解决办法下面再讲.先看看我们的加密方式,代码如下:
import java.security.MessageDigest;
import java.util.Map;
import java.util.Random;

public class URLUtils {
    /**
     * 根据MD5加密方式生成短链接
     *@author DingYongJun
     *@date 2020/8/18
     *@return List<Map<String, Object>>
     */
    public static String getShortURL(String URL){
        // 可以自定义生成 MD5 加密字符传前的混合 KEY
        String key = "QDGYJ";
        // 要使用生成 URL 的字符
        String[] chars = new String[] { "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", "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"

        };
        // 对传入网址进行 MD5 加密
        String hex = md5ByHex(key + URL);

        String[] resUrl = new String[4];
        for (int i = 0; i < 4; i++) {

            // 把加密字符按照 8 位一组 16 进制与 0x3FFFFFFF 进行位与运算
            String sTempSubString = hex.substring(i * 8, i * 8 + 8);

            // 这里需要使用 long 型来转换,因为 Inteper .parseInt() 只能处理 31 位 , 首位为符号位 , 如果不用long ,则会越界
            long lHexLong = 0x3FFFFFFF & Long.parseLong(sTempSubString, 16);
            String outChars = "";
            for (int j = 0; j < 6; j++) {
                // 把得到的值与 0x0000003D 进行位与运算,取得字符数组 chars 索引
                long index = 0x0000003D & lHexLong;
                // 把取得的字符相加
                outChars += chars[(int) index];
                // 每次循环按位右移 5 位
                lHexLong = lHexLong >> 5;
            }
            // 把字符串存入对应索引的输出数组
            resUrl[i] = outChars;
        }
        Random random=new Random();
        int j=random.nextInt(4);
        //随机取一个作为短链
        return resUrl[j];
    }

    /**
     * MD5加密(32位大写)
     *@author DingYongJun
     *@date 2020/8/18
     *@return List<Map<String, Object>>
     */
    public static String md5ByHex(String src) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] b = src.getBytes();
            md.reset();
            md.update(b);
            byte[] hash = md.digest();
            String hs = "";
            String stmp = "";
            for (int i = 0; i < hash.length; i++) {
                stmp = Integer.toHexString(hash[i] & 0xFF);
                if (stmp.length() == 1)
                    hs = hs + "0" + stmp;
                else {
                    hs = hs + stmp;
                }
            }
            return hs.toUpperCase();
        } catch (Exception e) {
            return "";
        }
    }
}

以上是借鉴网上其他博主的代码,在此不做过多赘述,有兴趣研究其具体的生成方式的可以使用断点的方式来进去了解.

  • 问题所在:
    大家可以很轻易的发现一些问题,比如每次传的url一毛一样的时候,我们只生成四个短连接和随机数,当并发量大到一定的程度时,就会发生不唯一性的问题.

  • 解决办法:
    为了不使短连接地址太长(不超过12位,否则和长链接本质上区别不大了).我们可以在业务层调用两次getShortURL方法.
    具体代码如下:

		Date date = new Date();
		String URL = paramsMap.get("url").toString();
        String shortUrl = URLUtils.getShortURL(URL);
        //为了保证数据的唯一性,再加个时间戳压缩成短链接,两个拼接在一起,确保数据的唯一性
        String timeStamp = String.valueOf(date.getTime());
        String shotTime = URLUtils.getShortURL(timeStamp);
        String duanlianjie = shortUrl+shotTime;

解释:
为了保证数据的唯一性,再加个时间戳压缩成短链接,两个拼接在一起,确保数据的唯一性,系统时间是一直在变化的,所以在一定程度上就保证了这个短链接的唯一性!
可能出现的问题:
这个在高并发的情况也是可能会出现重复的情况,但是这个保证了同样的长链接不会生成重复的短链接.又因为短信平台不会同一时间多次调用.基本上满足了我的业务需求.
解决办法:
在此我就不具体实现解决办法了,只提供一个大概思路给大家.

  • 1.在getShortURL加上同步锁Synchronized ,保证每次只能有一个线程可以调用该方法,虽然在一定程度上可能会损失性能,但是会确保短链接的唯一性!
  • 2.可以加上其他的算法来和时间戳拼接到一起,然后再调用生成方法.如:(雪花算法等).有兴趣的可以自己去研究一下.

自此全部结束,以上都是个人所言,如有不对,尽请指出,大家一起交流进步。谢谢!

有需要源码的,或者有不理解,欢迎关注微信公众号来讨论,留言会回复的哦~

欢迎微信搜索关注:《全员格子》!!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/17141.html

(0)
小半的头像小半

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!