springboot 实现长链接转短链接的示例代码
作者:鹏鹏博客
短链接服务通过将长URL转换成6位短码,并存储长短链接对应关系到数据库中,用户访问短链接时,系统通过查询数据库并重定向到原始URL,实现快速访问,本文就来介绍一下如何使用,感兴趣的可以了解一下
实现结果:
转换短链接api:
接口:http://127.0.0.1/api?url=urlencode('要缩短的网址')
例如:http://127.0.0.1/api?url=http%3a%2f%2fwww.baidu.com
返回:http://127.0.0.1/baidu
访问短链接即可还原原url;
转换原理: 将原url通过一系列方式,转换成6位短码(只要能不重复,随便怎么方式都行);将长短链接存入数据库,形成一条对应关系;访问短链接的时候,在数据库找到对应的长链接,并通过重定向实现原url的访问;(如果你的转换方式能过还原,也可以不要数据库,但必须保证转换后的短码不能重复)
实现步骤:
1.创建数据库(shorturl),创建一个表,存储长链接和与之对应的短链接;
CREATE TABLE `link` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `long_url` varchar(500) DEFAULT NULL COMMENT '长链接', `short_url` varchar(255) DEFAULT NULL COMMENT '短链接', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
2.搭建springboot项目,搭建方式网上很多,自行查找;下图是项目构建完成的项目结构(public可以忽略):

3.逻辑层代码依次是:
entity:
package com.tips.entity;
public class Link {
private Integer id;
private String longUrl;
private String shortUrl;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLongUrl() {
return longUrl;
}
public void setLongUrl(String longUrl) {
this.longUrl = longUrl;
}
public String getShortUrl() {
return shortUrl;
}
public void setShortUrl(String shortUrl) {
this.shortUrl = shortUrl;
}
}
dao:
package com.tips.mapper;
import com.tips.entity.Link;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LinkMapper {
Link selectByPrimaryKey(Integer id);
int insert(Link link);
Link findByLongUrl(String longUrl);
String findByShortUrl(String shortUrl);
}
service:
package com.tips.service;
import com.tips.entity.Link;
public interface LinkService {
String save(Link link);
String restoreUrl(String url);
}
service.impl:
package com.tips.service.impl;
import com.tips.entity.Link;
import com.tips.mapper.LinkMapper;
import com.tips.service.LinkService;
import com.tips.util.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LinkServiceImpl implements LinkService{
@Autowired
private LinkMapper linkMapper;
/**
* 转化url
* 查询数据库是否已经存在 如果存在就返回数据库对应的短链接,如果不存在就查询一条新纪录并返回新的短链接
* <strong>@param </strong>link
* <strong>@return
</strong><strong> </strong>*/
@Override
public String save(Link link) {
String shortUrl = "http://127.0.0.1/";
String longUrl = link.getLongUrl();
System.out.println(longUrl);
Link link1 = linkMapper.findByLongUrl(longUrl);
if(link1 == null) {
shortUrl += this.gererateShortUrl(longUrl);
link.setShortUrl(shortUrl);
linkMapper.insert(link);
}else{
shortUrl = link1.getShortUrl();
}
return shortUrl;
}
@Override
public String restoreUrl(String url) {
return linkMapper.findByShortUrl(url);
}
/**
* <strong>@param </strong>args
*/
public static void main(String[] args) {
String sLongUrl = "http://474515923.qzone.qq.com" ; //长链接
LinkServiceImpl link = new LinkServiceImpl();
String result = link.gererateShortUrl(sLongUrl);
// 打印出结果
System.out.println("短链接为: "+ result);
}
/**
* 将长链接转换为短链接
* <strong>@param </strong>url
* <strong>@return
</strong><strong> </strong>*/
public String gererateShortUrl(String url) {
// 可以自定义生成 MD5 加密字符传前的混合 KEY
String key = "caron" ;
// 要使用生成 URL 的字符
String[] chars = new String[] { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" ,
"i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" ,
"u" , "v" , "w" , "x" , "y" , "z" , "0" , "1" , "2" , "3" , "4" , "5" ,
"6" , "7" , "8" , "9" , "A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" ,
"I" , "J" , "K" , "L" , "M" , "N" , "O" , "P" , "Q" , "R" , "S" , "T" ,
"U" , "V" , "W" , "X" , "Y" , "Z"
};
// 对传入网址进行 MD5 加密
String sMD5EncryptResult = MD5Util.MD5(key+url);
String hex = sMD5EncryptResult;
// String[] resUrl = new String[4];
// for ( int i = 0; i < 4; i++) {
// 把加密字符按照 8 位一组 16 进制与 0x3FFFFFFF 进行位与运算
String sTempSubString = hex.substring(2 * 8, 2 * 8 + 8); //固定取第三组
// 这里需要使用 long 型来转换,因为 Inteper .parseInt() 只能处理 31 位 , 首位为符号位 , 如果不用 long ,则会越界
long lHexLong = 0x3FFFFFFF & Long.parseLong (sTempSubString, 16);
String outChars = "" ;
for ( int j = 0; j < 6; j++) {
// 把得到的值与 0x0000003D 进行位与运算,取得字符数组 chars 索引
long index = 0x0000003D & lHexLong;
// 把取得的字符相加
outChars += chars[( int ) index];
// 每次循环按位右移 5 位
lHexLong = lHexLong >> 5;
}
// 把字符串存入对应索引的输出数组
// resUrl[i] = outChars;
// }
return outChars;
}
}util:
package com.tips.util;
import java.security.MessageDigest;
public class MD5Util {
// MD5加码。32位
public static String MD5(String inStr) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
return "";
}
char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++)
byteArray[i] = (byte) charArray[i];
byte[] md5Bytes = md5.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16)
hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
// 可逆的加密算法
public static String KL(String inStr) {
// String s = new String(inStr);
char[] a = inStr.toCharArray();
for (int i = 0; i < a.length; i++) {
a[i] = (char) (a[i] ^ 't');
}
String s = new String(a);
return s;
}
// 加密后解密
public static String JM(String inStr) {
char[] a = inStr.toCharArray();
for (int i = 0; i < a.length; i++) {
a[i] = (char) (a[i] ^ 't');
}
String k = new String(a);
return k;
}
// 测试主函数
public static void main(String args[]) {
String s = new String("a");
System.out.println("原始:" + s);
System.out.println("MD5后:" + MD5(s));
System.out.println("MD5后再加密:" + KL(MD5(s)));
System.out.println("解密为MD5后的:" + JM(KL(MD5(s))));
System.out.println("判断是否相同:" + MD5(s).equals(JM(KL(MD5(s)))));
}
} mapper:
<?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.tips.mapper.LinkMapper">
<resultMap id="BaseResultMap" type="com.tips.entity.Link">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="long_url" jdbcType="VARCHAR" property="longUrl" />
<result column="short_url" jdbcType="VARCHAR" property="shortUrl" />
</resultMap>
<sql id="Base_Column_List">
id, long_url, short_url
</sql>
<!-- 根据长链接查询 -->
<select id="findByLongUrl" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from link
where long_url = #{longUrl,jdbcType=VARCHAR}
</select>
<!-- 根据短链接查询 -->
<select id="findByShortUrl" parameterType="java.lang.String" resultType="java.lang.String">
select long_url from link
where short_url = #{shortUrl,jdbcType=VARCHAR}
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from link
where id = #{id,jdbcType=INTEGER}
</select>
<insert id="insert" parameterType="com.tips.entity.Link">
insert into link (id, long_url, short_url)
values (#{id,jdbcType=INTEGER}, #{longUrl,jdbcType=VARCHAR}, #{shortUrl,jdbcType=VARCHAR})
</insert>
</mapper>controller:
package com.tips.controller;
import com.tips.entity.Link;
import com.tips.service.LinkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class LinkController {
@Autowired
private LinkService linkService;
/**
* 生成短链接
* @param url
* @return Caron
*/
@RequestMapping("/api")
@ResponseBody
public Object save(String url){
if (url == null || "".equals(url)){
return null;
}
if(url.startsWith("http://") || url.startsWith("https://")){
Link link = new Link();
link.setLongUrl(url);
return linkService.save(link);
}else{
return "网址必须以http或https开头";
}
}
/**
* 301跳转
* @param url
* @return
*/
@RequestMapping("/{url}")
public String restoreUrl(@PathVariable("url") String url){
String restoreUrl = linkService.restoreUrl("http://cni.tips/"+url);
if(restoreUrl != null && !"".equals(restoreUrl)){
return "redirect:"+restoreUrl;
}else{
return "redirect:http://www.cnilink.com";
// return "forward:/404.html"; //如果要访问本地html,@RequestMapping("/{url}")前面必须加一层路径/aa/{url}
}
}
}application.properties:

pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com</groupId> <artifactId>tips</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>tips</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
基本所有源码都贴出来了。跑起来试一下呗
到此这篇关于springboot 实现长链接转短链接的示例代码的文章就介绍到这了,更多相关springboot 长链接转短链接内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
