【短链接】——自己实现一个短网址服务

目录

前言

什么是短链接

为什么要用短链接(引用)

如何生成短链接

实现

代码

演示


前言

前段时间做支付的时候,要生成可供微信和支付宝扫描的支付二维码,二维码里存储的也就是一个链接,但是可能是因为链接比较长的缘故,总是被微信拦截。

然后就换成了微信官方的长链接转短链接,好不容易弄好了,发现支付宝扫的话会拦截,两家果真是水火不容。。。

有问题就解决问题呗,那我换成第三方的好了,但是网上一般的第三方短链接服务平台都不会被微信接纳,那就只能找比较知名的,比如新浪、百度、谷歌,我首先试了新浪的,完美,终于让微信和支付宝都满意了。

然后就在前几周,测试人员忽然找我说二维码出不来了。。我真是心力交瘁,去新浪官方一看你说气不气,在11号的时候这个接口下线了。。。

【短链接】——自己实现一个短网址服务_第1张图片

靠别人永远靠不住。。。那就只能靠自己了!

没有接触过这种业务的小伙伴可能会问什么是短链接?长链接好好地,干嘛要把它转成短链接?咋就能转成短链接呢?

下面我们简单介绍一下短链接的相关知识。

什么是短链接

顾名思义,就是将长网址缩短到一个很短的网址,用户访问这个短网址可以就可以访问到原本的长网址。这样可以达到易于记忆、转换的目的。

比如一个百度图片的搜索网址是这样的:http://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gb18030&word=%CD%BC%C6%AC&fr=ala&ala=1&alatpl=others&pos=0

够长吧,那我们用一些短网址服务平台来进行短网址生成:

  • 百度短网址服务生成的短网址:https://dwz.cn/afLO9WNV
  • 新浪免费版短网址服务生成的短网址:http://1t.click/atFy

以及一些第三方的:

  • (https://dwz3.cn/)生成的短网址:https://0x9.me/8NhQJ
  • (http://www.h5ip.cn/)生成的短网址:http://h5ip.cn/SmDX

看到没有,一个那么长的网址,确被缩短到这么短,而且每个平台生成的都不一样,缺都可以访问到我们原本那个长长的网址。以上生成的网址有些可能是永久的,有些可能一段时间就过期了。

为什么要用短链接(引用)

1、新浪微博

我们在新浪微博上发布网址的时候,微博会自动判别网址,并将其转换,例如:https://t.cn/RuPKzRW。为什么要这样做的?

这是因为微博限制字数为140字一条,那么如果我们需要发一些链接上去,但是这个链接非常的长,以至于将近要占用我们内容的一半篇幅,这肯定是不能被允许的或者说用户体验很差的,所以短网址应运而生了,短网址这种服务可以说是在微博出现之后才流行开来的!往下看:

(1)首先,我先发一条微博带有一个URL地址: 

【短链接】——自己实现一个短网址服务_第2张图片

(2)然后,看他转换之后显示的效果是什么样子的哪? 

【短链接】——自己实现一个短网址服务_第3张图片

(3)查看对应页面元素的HTML源码如下: 

【短链接】——自己实现一个短网址服务_第4张图片

(4)可以看出:https://blog.csdn.net/xlgen157387/article/details/79863301 被转换为:http://t.cn/RuPKzRW,此时你访问http://t.cn/RuPKzRW是可以定位到https://blog.csdn.net/xlgen157387/article/details/79863301,也就是实现了转换。

2、短网址二维码

网址在转换成短网址时,也可以生成相应的短网址二维码,短网址二维码的应用,二维码核心解决的是跨平台、跨现实的数据传输问题;而且二维码跟应用场景结合之后,所能解决的问题会越来越多。

(1)短网址二维码相比短链接更方便,能少输入,尽量少输入,哪怕只是少点一下键盘,都是有意义的。

(2)二维码只是扫描一个简单的链接,打开的却是一个世界。想象一下,用手机购买售货机里商品,二维码扫描是略快于从用手机找到该售货机并找到该商品的,而且这种操作相对于搜索/查找而言不是更优雅吗?

(3)所有商超里面的商品,都是使用条码来确定商品的唯一性的,去买单的时候都是扫描条码。试想,如果里面加入了更多产品的生产日期、厂家、流转途径、原材料等等信息,是不是厉害了呢?特别是针对食品信息的可追溯上,二维码应用场景更广泛。
除了上述场景中,我们将长地址转换为短地址的使用场景的优点(压缩URL长度)之外,短地址还具有很多实际场景中的优点,例如:

(1)节省网址长度,便于社交化传播,一个是让URL更短小,传播更方便,尤其是URL中有中文和特殊字符,短网址解决很长的URL难以记忆不利于传播的问题;

(2)短网址在我们项目里可以很好的对开放以及对URL进行管理。有一部分网址可以会涵盖性、暴力、广告等信息,这样我们可以通过用户的举报,完全管理这个连接将不出现在我们的应用中,对同样的URL通过加密算法之后,得到的地址是一样的;

(3)方便后台跟踪点击量、地域分布等用户统计。我们可以对一系列的网址进行流量,点击等统计,挖掘出大多数用户的关注点,这样有利于我们对项目的后续工作更好的作出决策;

(4)规避关键词、域名屏蔽手段、隐藏真实地址,适合做付费推广链接;

(5)当你看到一个淘宝的宝贝连接后面是200个“e7x8bv7c8bisdj”这样的字符的时候,你还会觉得舒服吗。更何况微博字数只有140字,微博或短信里,字数不够,你用条短网址就能帮你腾出很多空间来;

如何生成短链接

网上比较流行的算法有两种 自增序列算法、 摘要算法

这里我也没去专门很细的研究,着急拿来用,后续有时间再去深入吧,有兴趣的小伙伴可以看一下以下博客:

面试必备:如何将一个长URL转换为一个短URL?

短网址(short URL)系统的原理及其实现

实现

好了,说了这么多,终于到实现的部分了,其实短网址生成服务基本的实现流程都是一样的,不一样的知识短网址生成的算法不同而已,下面是一个短网址系统基本的实现,我这里是存在redis中比较方便快捷,大家也可以选择存入mysql等。

【短链接】——自己实现一个短网址服务_第5张图片【短链接】——自己实现一个短网址服务_第6张图片

代码

这里的案例场景模仿我遇到的支付问题

案例是基于springboot项目,其他框架可能要做适当修改

OrderPayController:项目内生成二维码的接口,这里简化,只是生成链接,未转变为二维码,想转为二维码的可以看:【二维码】——生成二维码并转为base64

/**
 * @author: WangZhiJun
 * @create: 2019-09-21 12:31
 **/
@RestController
@RequestMapping("/api/v1/order")
public class OrderController {
    private static final String SHORT_URL = "shortUrl:";

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 系统内生成支付二维码接口
     */
    @GetMapping(value = "/payOrder")
    public String pay(@RequestParam String orderId) {
        String orderName = "XXSuperMarketPay";
        BigDecimal orderMoney = new BigDecimal(100);
        System.out.println("订单"+orderId+orderName+"需支付:"+orderMoney+"元");

        String wxPayUrl = "http://localhost:8080/wx/pay/pay?orderId="+orderId+"&orderName="+orderName+"&orderMoney="+orderMoney;
        String shortUrl = ShortUrlUtils.shortUrl(wxPayUrl);
        System.out.println("生成的微信支付链接为:"+wxPayUrl);
        System.out.println("生成的短链接为:"+ shortUrl);
        //存入redis或者数据库,键值为六位数的短链接
        redisTemplate.opsForValue().set(SHORT_URL + shortUrl, shortUrl, 1, TimeUnit.HOURS);
        //这里我的业务场景中是生成二维码,这里简化为链接
        return "http://localhost:8080/url/" + shortUrl;
    }
}

WxPayController:模仿微信支付官方接口

/** 假设这是微信支付的接口
 * @author: WangZhiJun
 * @create: 2019-09-21 12:31
 **/
@RestController
@RequestMapping("/wx/pay")
public class WxPayController {
    /**
     * 模仿微信支付API
     */
    @GetMapping(value = "/pay")
    public void paySuccess(@RequestParam String orderId,
                         @RequestParam String orderMoney,
                         @RequestParam String orderName) {
        System.out.println("订单"+orderId+orderName+"支付:"+orderMoney+"元");
        System.out.println("支付成功");
    }
}

UrlController:短码转发,将短码对应的长链接取出并重定向到长链接

/**
 * @description: 短网址转发
 * @author: WangZhiJun
 * @create: 2019-09-21 12:20
 **/
@RestController
@RequestMapping("/url")
public class UrlController {
    private static final String SHORT_URL = "shortUrl:";

    @Resource
    private RedisTemplate redisTemplate;

    @GetMapping(value = "/{shortUrl}")
    public void getInvoiceUrl(@PathVariable(required = false) String shortUrl,
                              HttpServletResponse response) {
        String url = (String) redisTemplate.opsForValue().get(SHORT_URL + shortUrl);
        try {
            //将短链接映射的长链接取出并重定向到长链接
            response.sendRedirect(url);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

长链接转短码的算法主要是使用MD5 算法对原始链接进行加密(这里使用的MD5 加密后的字符串长度为32 位),然后对加密后的字符串进行处理以得到短链接的地址。

import java.security.MessageDigest;

/** 短链接生成工具类
 * @author WangZhiJun
 */
public class ShortUrlUtils {

    /**
     * 十六进制下数字到字符的映射数组
     */
    private final static String[] HEXDIGITS = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
    /**把inputString加密*/
    public static String md5(String inputStr){
        return encodeByMD5(inputStr);
    }

    /**对字符串进行MD5编码*/
    private static String encodeByMD5(String originString){
        if (originString!=null) {
            try {
                //创建具有指定算法名称的信息摘要
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                //使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
                byte[] results = md5.digest(originString.getBytes());
                //将得到的字节数组变成字符串返回
                String result = byteArrayToHexString(results);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    /**
     * 轮换字节数组为十六进制字符串
     * @param b 字节数组
     * @return 十六进制字符串
     */
    private static String byteArrayToHexString(byte[] b){
        StringBuffer resultSb = new StringBuffer();
        for(int i=0;i> 5;
            }
            // 把字符串存入对应索引的输出数组
            resUrl[i] = outChars.toString();
        }
        return resUrl;
    }
}

演示

 然后访问生成的短码网址:http://localhost:8080/url/vqQjEj,会自动重定向到原本的支付链接

实现效果可以去我的个人主页进行测试:短网址服务

大功告成!

 

 

 

你可能感兴趣的:(★JAVA学习之路★)