SpringBoot实现短链跳转

本文介绍了短链跳转的原理和意义,重点展示了如何在SpringBoot项目中使用Lombok实现短链到长链的数据库映射,并详细讲解了Dao、Service和Controller层的代码实现。通过实例测试验证了短链的生成与重定向功能。
摘要由CSDN通过智能技术生成

目录

1.背景介绍

2.短链跳转的意义    

3.SpringBoot中的代码实现

1.建议短链-长链的数据库表:t_url_map:

2.映射实体

3.Dao层实现

4.Service层实现

5.Controller层实现 

3.结果测试

4.问题


1.背景介绍

        短链跳转是一种通过将长链接转换为短链接的方式,以便在互联网上进行链接共享和传播的技术。通常情况下,长链接可能由于包含大量参数或者较长的路径而显得复杂且不易记忆,而短链则是将原始长链接通过特定算法转换为较短的链接,使得它更容易分享、传播和展示

        短链跳转服务通常由第三方提供,用户可以将需要缩短的长链接提交到该服务,服务会返回一个短链接,当用户访问这个短链接时,会被重定向到原始的长链接地址。这种服务通常还提供了统计功能,可以跟踪短链接被点击的次数访问来源等信息,帮助用户了解链接的传播效果。

        短链跳转服务有助于美化链接、节省空间、方便分享和统计链接访问情况,因此被广泛应用于社交媒体、微博客、推广活动等各种互联网应用场景中。

        比如在b站中,一个视频的网址原来是这样的:

        在移动端中,点击分享按钮,复制其链接:

       

        它会变成如下链接形式:

      【Cookie、Session、Token、JWT一次性讲完-哔哩哔哩】 https://b23.tv/0SMtYq6

        点击该链接后,你会发现浏览器的网址URL为原来的长链接形式,也就是说这其中发生了重定向 ,而这个过程就是这篇博客要提到的短链跳转了。

2.短链跳转的意义    

  1. 节省空间:长链接可能会很长,不方便分享或展示,通过短链跳转可以将长链接转换为短链接,节省字符空间。

  2. 美化链接:短链看起来更简洁、美观,对于需要展示给用户或发布到社交媒体等场景更具吸引力。

  3. 防止链接失效:某些长链接可能会因为过期、失效或变动而无法访问,通过短链跳转可以在后台进行管理和更新,保证链接的可访问性。

  4. 统计和跟踪:通过短链跳转服务可以对链接的点击量、来源、地域等信息进行统计和分析,帮助用户了解链接的受众和效果。

  5. 方便分享:短链更容易复制、粘贴和分享,适用于短信、微博、邮件等分享场景,提高分享效率。

  6. 隐藏原始链接:有时候希望隐藏原始链接的信息,通过短链跳转可以起到一定的保护作用,防止泄露敏感信息。

3.SpringBoot中的代码实现

        这里我们以快速入门为主,即主要实现长链到短链的映射逻辑。

1.建议短链-长链的数据库表:t_url_map:

2.映射实体
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.Instant;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UrlMap {


    private Long id;

    private String longUrl;

    private String shortUrl;

    private String username;

    private Instant expireTime;

    private Instant creationTime;



}

        这里要添加lombok依赖:

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
3.Dao层实现

        这里简单写三个关键的接口方法:根据长链找短链(若无则生成短链)、根据短链找长链(若无则跳转失败页面)、插入实体

import com.zhan.zhan215.Entity.UrlMap;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.time.Instant;
import java.util.List;


@Mapper
public interface UrlMapMapper {

    UrlMap findFirstByLongUrl(@Param("longUrl") String longUrl, @Param("username") String username);

    void saveUrlMap(UrlMap urlMap);

    UrlMap findByShortUrl(String shortUrl);


}

        对应的xml映射:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhan.zhan215.Dao.UrlMapMapper">

    <select id="findFirstByLongUrl" parameterType="string" resultType="com.zhan.zhan215.Entity.UrlMap">

        select *

        from t_url_map

        where longUrl =#{longUrl} and username = #{username}

        limit 1

    </select>

    <!-- 在Mapper XML文件中定义保存urlMap对象的方法 -->
    <insert id="saveUrlMap" parameterType="com.zhan.zhan215.Entity.UrlMap">
        INSERT INTO t_url_map (shortUrl, longUrl,username)
        VALUES (#{shortUrl}, #{longUrl},#{username})
    </insert>

    <select id="findByShortUrl"  parameterType="string" resultType="com.zhan.zhan215.Entity.UrlMap">

        select *

        from t_url_map

        where shortUrl = #{shortUrl} limit 1

    </select>
4.Service层实现
import com.zhan.zhan215.Dao.UrlMapMapper;
import com.zhan.zhan215.Entity.UrlMap;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;

@Service
public class UrlMapService {

    @Resource
    private UrlMapMapper urlMapMapper;


    // 编码
    public String encode(String longUrl,String username) {

        UrlMap urlMap = urlMapMapper.findFirstByLongUrl(longUrl,username);

        // 看看该长链接是否存在
        // 如果存在并且其对应用户名等于已有用户名,则直接给出短链接
        if (urlMap != null&&username.equals(urlMap.getUsername())) {
            return urlMap.getShortUrl();

        } else {
            // 如果不存在,则生成短链接
            UrlMap urlMap1 = new UrlMap();
            // 生成短链接
            String shortLink = generateShortLink(longUrl,username);
            // 保存短链接
            urlMap1.setLongUrl(longUrl);
            urlMap1.setShortUrl(shortLink);
            urlMap1.setUsername(username);
            urlMap1.setCreationTime(Instant.now());
            urlMapMapper.saveUrlMap(urlMap1);


            return shortLink;
        }
    }

    // 解码
    public String decode(String shortUrl){

        // 根据短链接获取长链接
        UrlMap byShortUrl = urlMapMapper.findByShortUrl(shortUrl);

        // 如果存在,返回长链接
        if(byShortUrl!=null){
            return byShortUrl.getLongUrl();
        }

        // 如果没有,返回首页(正常是返回一个失败页面)
        return "https://bilibili.com";

    }

    // 生成短链接
    public static String generateShortLink(String originalUrl,String username) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hashBytes = md.digest(originalUrl.getBytes());
            // 对原始URL进行MD5哈希计算

            StringBuilder sb = new StringBuilder();
            for (byte b : hashBytes) {
                sb.append(String.format("%02x", b));
                // 将字节数组转换为十六进制字符串
            }

            return sb.toString().substring(0, 8)+username;
            // 截取前8位,加上用户名(这里先简单默认用户名是4位数)
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }


}
5.Controller层实现 
import com.zhan.zhan215.Common.ResponseBean;
import com.zhan.zhan215.Service.UrlMapService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.view.RedirectView;

import javax.annotation.Resource;

@RestController
public class UrlMapController {

    @Resource
    private UrlMapService urlMapService;



    @PostMapping("/shorten")
    // 长链接转短连接,相当于实际项目中的点击“分享”,形成一条短连接
    public ResponseBean shorten(@RequestParam String longUrl,@RequestParam String username){

        String encode =  urlMapService.encode(longUrl,username);
        // 形成短链

        return ResponseBean.success(encode);

    }

    @GetMapping("redirect")
    //重定向
    public RedirectView redirectView(@RequestParam String shortUrl){

        String longUrl = urlMapService.decode(shortUrl);

        return new RedirectView(longUrl);
    }

}

相关的ResponseBean的返回结果集代码:

public class ResponseBean<T> {

    /** 200:操作成功  -1:操作失败**/

    // http 状态码
    private boolean success;

    // 返回的数据
    private T data;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static <T> ResponseBean<T> success(T data) {
        ResponseBean<T> responseBean = new ResponseBean<>();
        responseBean.setSuccess(true);
        responseBean.setData(data);
        return responseBean;
    }

    public static <T> ResponseBean<T> error(T errorData) {
        ResponseBean<T> responseBean = new ResponseBean<>();
        responseBean.setSuccess(false);
        responseBean.setData(errorData);
        return responseBean;
    }

    public static <T> ResponseBean<T> success() {
        ResponseBean<T> responseBean = new ResponseBean<>();
        responseBean.setSuccess(true);
        return responseBean;
    }

}

3.结果测试

        我们就拿刚刚那个b站的长链接作测试,即https://www.bilibili.com/video/BV18u4m1K7D4/?spm_id_from=333.1007.tianma.10-4-38.click&vd_source=1c7e32cfbc70017a24ee2c337620ff51

        

        可以看到短链接生成为1b9590bezhan,

        然后我们再用这条链接去测试能否跳转到原始链接:

        

        成功根据短链接定向到原始链接的网站了。

4.问题

        1.为什么生成短链接需要带上username参数?

         答:这里其实模仿的是不同用户对应同一个原始链接(或长链接)时,确保他们生成的短链接各不相同,这样可以方便后台追踪是由哪个用户分享的短链接,进而统计分享数。在表中LongUrl和shortUrl的对应关系为一对多

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
SpringBoot是一个开源的Java框架,可以简化Java应用程序的开发。它提供了很多方便的功能,可以帮助我们快速构建稳定可靠的应用程序。 要实现短链生成和统计,可以借助SpringBoot的特性和第三方库来完成。以下是一个基本的实现思路: 1. 短链生成 首先,我们需要设计一个用于生成短链的算法或方法。常见的方法是将长链接通过哈希算法转换为字符串。你可以选择使用MD5、SHA1等哈希算法,并取其中一部分字符作为短链接。另外,为了避免生成过长的短链,可以将其进一步进行压缩。 在SpringBoot中,可以通过创建一个生成短链的Controller来实现。Controller接收长链接作为参数,调用短链生成的方法,然后将生成短链接返回给前端。 2. 短链重定向 当用户点击短链接时,服务器需要将其重定向到原始的长链接地址。可以在SpringBoot中创建一个Controller,设置一个路由映射,并在该Controller中获取短链接对应的长链接,然后进行重定向。 3. 统计短链点击量 为了统计短链的点击量,我们可以在数据库中创建一个表,用于记录短链的相关信息,例如短链、长链接、点击次数等。 在SpringBoot中,可以定义一个点击事件的Controller,当用户点击短链时,将触发该Controller。该Controller负责将点击事件信息保存至数据库,并更新短链对应的点击次数。 以上是一个基本的实现思路,你可以根据具体需求和场景进行进一步的优化和改进。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛变涡流

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值