SpringBoot实现短链跳转

目录

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_mapwhere 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_mapwhere 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 {@Resourceprivate 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 {@Resourceprivate 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的对应关系为一对多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/498725.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【两颗二叉树】【递归遍历】【▲队列层序遍历】Leetcode 617. 合并二叉树

【两颗二叉树】【递归遍历】【▲队列层序遍历】Leetcode 617. 合并二叉树 解法1 深度优先 递归 前序解法2 采用队列进行层序遍历 挺巧妙的可以再看 ---------------&#x1f388;&#x1f388;题目链接&#x1f388;&#x1f388;------------------- 解法1 深度优先 递归 前…

【InternLM 实战营笔记】大模型评测

随着人工智能技术的快速发展&#xff0c; 大规模预训练自然语言模型成为了研究热点和关注焦点。OpenAI于2018年提出了第一代GPT模型&#xff0c;开辟了自然语言模型生成式预训练的路线。沿着这条路线&#xff0c;随后又陆续发布了GPT-2和GPT-3模型。与此同时&#xff0c;谷歌也…

VS连接MySQL以及找不到libmysql.dll的解决方法

VS连接数据库需要在项目中进行配置&#xff0c;具体可见 https://blog.csdn.net/weixin_40582034/article/details/115562097?ops_request_misc%257B%2522request%255Fid%2522%253A%2522170891897216800213058288%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522…

C++之数组

1&#xff0c;概述 所谓数组&#xff0c;就是一个集合&#xff0c;里面存放了相同类型的数据元素 特点1&#xff1a;数组中没干过数据元素都是相同的数据类型 特点2&#xff1a;数组都是连续存放位置组成的 2&#xff0c;一维数组 2.1 一维数组的定义 一维数组定义有三种…

抖音视频评论提取软件|视频数据批量采集工具

抖音视频评论批量下载软件是一款基于C#开发的高效工具&#xff0c;旨在帮助用户快速获取抖音视频评论数据。无论您是市场分析师、社交媒体管理者还是数据研究人员&#xff0c;这款软件都会成为您工作中不可或缺的利器。 软件的关键功能包括&#xff1a; 关键词搜索&#xff1…

【C#】SixLabors.ImageSharp和System.Drawing两者知多少

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的理解和掌握。…

Mac 制作可引导安装器

Mac 使用U盘或移动固态硬盘制作可引导安装器&#xff08;以 Monterey 为例&#xff09; 本教程参考 Apple 官网相关教程 创建可引导 Mac OS 安装器 重新安装 Mac OS 相关名词解释 磁盘分区会将其划分为多个单独的部分&#xff0c;称为分区。分区也称为容器&#xff0c;不同容器…

uniapp实战:父子组件传参之子组件数量动态变化

需求说明 现有的设置单元列表,每个带有虚线加号的可以看做是一组设置单元,点击加号可以添加一组设置单元.点击设置单元右上角可以删除对应的设置单元. 实现思路说明 利用数组元素添加或是删除的方式实现页面数量动态变化.由于每个设置单元内容都相同所以单独封装了一个子组件.…

Vue3+springboot实现简单登录demo

Vue3从0搭建脚手架步骤【默认已安装node.js】 前置条件&#xff1a;默认已安装node.js、yarn 第一步&#xff1a;创建项目 选择任意一个空白文件夹如下&#xff1a; cmd进入该文件夹下的命令窗口模式&#xff0c;然后输入指令创建vue项目&#xff1a;vue create my-project …

Python3中真真假假True、False、None等含义详解

在Python中&#xff0c;不仅仅和类C一样的真假类似&#xff0c;比如1代表真&#xff0c;0代表假。Python中的真假有着更加广阔的含义范围&#xff0c;Python会把所有的空数据结构视为假&#xff0c;比如 [] (空列表)、 {} &#xff08;空集合&#xff09;、 &#xff08;空字符…

立誓登峰,龙年必赢 |大势智慧2024年营销动员誓师大会圆满召开

2月27日&#xff0c;大势智慧2024年度营销动员誓师大会成功召开。大势智慧CEO黄先锋、CTO张帆、常务副总裁徐建民、副总裁周济安、营销中心副总经理段鸿、全国各分公司总经理及营销中心全体精英齐聚武汉总部&#xff0c;共同为新一年的市场必赢之战吹响冲锋号角。 凝心聚力 再…

Flutter 数据持久化存储之Hive库

Flutter 数据持久化存储之Hive库 前言正文一、配置项目二、UI① 增加UI② 显示和删除UI 三、使用Hive① 初始化Hive② TypeAdapter自定义对象③ 注册TypeAdapter③ CURD 四、源码 前言 在Flutter中&#xff0c;有多种方式可以进行数据持久化存储。以下是一些常见的方式&#xf…