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短链接跳转的资料请关注脚本之家其它相关文章!

相关文章

  • spring简单MVC实现方法(URL映射及其参数使用、查询(id、其他参数)、增加)

    spring简单MVC实现方法(URL映射及其参数使用、查询(id、其他参数)、增加)

    这篇文章主要介绍了spring简单MVC实现方法(URL映射及其参数使用、查询(id、其他参数)、增加),方法参数使用包括在无注解下获取参数,使用@RequestParam 获取参数的方法,每种方法讲解的非常详细,需要的朋友可以参考下
    2024-01-01
  • jboss( WildFly)上运行 springboot程序的步骤详解

    jboss( WildFly)上运行 springboot程序的步骤详解

    这篇文章主要介绍了jboss( WildFly)上运行 springboot程序的步骤详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • java中多线程加锁的四种方式

    java中多线程加锁的四种方式

    Java中实现多线程安全的关键是加锁,主要方式有synchronized关键字、ReentrantLock类、ReadWriteLock接口和Semaphore类,本文就来介绍一下这四种方式,感兴趣的可以了解一下
    2024-10-10
  • Java中常用的代码汇总

    Java中常用的代码汇总

    本文给大家分享了20个常用的java代码,都是别人项目中使用过的代码,这里推荐给大家,有需要的小伙伴可以参考下。
    2015-05-05
  • Java 中组合模型之对象结构模式的详解

    Java 中组合模型之对象结构模式的详解

    这篇文章主要介绍了Java 中组合模型之对象结构模式的详解的相关资料,希望通过本文能帮助到大家理解应用对象结构模型,需要的朋友可以参考下
    2017-09-09
  • 用Java轻松读取Word文档内容的常用方法

    用Java轻松读取Word文档内容的常用方法

    这篇文章主要介绍了用Java轻松读取Word文档内容的常用方法,对于doc格式使用Apache POI库中的HWPFDocument和WordExtractor类,对于docx格式使用XWPFDocument类,并通过遍历段落和文本运行对象来提取文本内容,需要的朋友可以参考下
    2025-03-03
  • Java Optional的判空操作详解

    Java Optional的判空操作详解

    JAVA在1.8版本推出Optional,官方文档将其描述为可能包含或不包含非空值的容器对象,目前Optional用于避免程序出现异常NullPointerException,感兴趣的可以了解一下
    2022-09-09
  • MyBatis-Plus模糊查询特殊字符串转义的实现

    MyBatis-Plus模糊查询特殊字符串转义的实现

    使用MyBatis中的模糊查询时,当查询关键字中包括有_、\、%时,查询关键字失效,本文主要介绍了MyBatis-Plus模糊查询特殊字符串转义的实现,感兴趣的可以了解一下
    2024-06-06
  • Java Swing BoxLayout箱式布局的实现代码

    Java Swing BoxLayout箱式布局的实现代码

    这篇文章主要介绍了Java Swing BoxLayout箱式布局的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • mybatis输出SQL格式化方式

    mybatis输出SQL格式化方式

    这篇文章主要介绍了mybatis输出SQL格式化方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11

最新评论