SpringBoot短链接跳转的代码实现

 更新时间:2024年03月01日 10:01:48   作者:蜗牛变涡流  
短链跳转是一种通过将长链接转换为短链接的方式,以便在互联网上进行链接共享和传播的技术,短链将原始长链接通过特定算法转换为较短的链接,使得它更容易分享、传播和展示,本文给大家介绍了SpringBoot短链接跳转的代码实现,需要的朋友可以参考下

1.背景介绍

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

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

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

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

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

它会变成如下链接形式:

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

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

2.短链跳转的意义 

  • 节省空间:长链接可能会很长,不方便分享或展示,通过短链跳转可以将长链接转换为短链接,节省字符空间。
  • 美化链接:短链看起来更简洁、美观,对于需要展示给用户或发布到社交媒体等场景更具吸引力。
  • 防止链接失效:某些长链接可能会因为过期、失效或变动而无法访问,通过短链跳转可以在后台进行管理和更新,保证链接的可访问性。
  • 统计和跟踪:通过短链跳转服务可以对链接的点击量、来源、地域等信息进行统计和分析,帮助用户了解链接的受众和效果。
  • 方便分享:短链更容易复制、粘贴和分享,适用于短信、微博、邮件等分享场景,提高分享效率。
  • 隐藏原始链接:有时候希望隐藏原始链接的信息,通过短链跳转可以起到一定的保护作用,防止泄露敏感信息。

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;
    }
 
}

4.结果测试

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

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

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

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

5.问题

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

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

以上就是SpringBoot短链接跳转的代码实现的详细内容,更多关于SpringBoot短链接跳转的资料请关注脚本之家其它相关文章!

相关文章

  • 详解SpringBoot构建的Web项目如何在服务端校验表单输入

    详解SpringBoot构建的Web项目如何在服务端校验表单输入

    这篇文章主要介绍了详解SpringBoot构建的Web项目如何在服务端校验表单输入,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • java如何实现多线程的顺序执行

    java如何实现多线程的顺序执行

    多线程是java的一种重要技术,但是多线程的运行是没有绝对的顺序的,那么java如何实现多线程的顺序执行,下面就一起来了解一下
    2021-05-05
  • 如何解决Field name doesn‘t have a default value报错问题

    如何解决Field name doesn‘t have a defau

    这篇文章主要介绍了如何解决Field name doesn‘t have a default value报错问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • 详解SpringBoot初始教程之Tomcat、Https配置以及Jetty优化

    详解SpringBoot初始教程之Tomcat、Https配置以及Jetty优化

    本篇文章主要介绍了详解SpringBoot初始教程之Tomcat、Https配置以及Jetty优化,具有一定的参考价值,有兴趣的可以了解一下
    2017-09-09
  • Java中synchronized的几种使用方法

    Java中synchronized的几种使用方法

    本文主要介绍了Java中synchronized的几种使用方法,synchronized可用于修饰普通方法、静态方法和代码块,下面详细内容介绍,需要的小伙伴可以参考一下
    2022-05-05
  • SpringBoot整合Swagger2实例方法

    SpringBoot整合Swagger2实例方法

    在本篇文章里小编给大家整合了关于SpringBoot整合Swagger2的相关知识点内容,有兴趣的朋友们学习下。
    2019-06-06
  • nacos配置在代码中引用的方法讲解

    nacos配置在代码中引用的方法讲解

    这篇文章主要介绍了nacos配置在代码中如何引用,如果主配置中配置的内容和拓展配置的内容重复则按主配置的配置 ,如果拓展配置中的内容和另一个拓展配置中的内容重复,则按下标大的配置作为最终的配置,对nacos配置代码引用相关知识感兴趣朋友一起看看吧
    2022-12-12
  • Java OpenCV利用KNN算法实现图像背景移除

    Java OpenCV利用KNN算法实现图像背景移除

    这篇文章主要为大家介绍了Java OpenCV利用K最邻近(KNN,K-NearestNeighbor)分类算法实现图像背景移除的示例代码,需要的可以参考一下
    2022-01-01
  • 教你如何区分Spring与Structs2中间件

    教你如何区分Spring与Structs2中间件

    这篇文章主要介绍了教你如何区分Spring与Structs2中间件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • java.lang.Void类源码解析

    java.lang.Void类源码解析

    这篇文章主要介绍了java.lang.Void类源码解析的相关内容,对源码中的部分内容进行解释,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10

最新评论