Java后端实现短链接服务
Java短链接服务是一个基于Java编程语言开发的应用程序,能够将长网址转换为短网址。它的主要作用包括:
1、简化分享:短链接使得链接更易于分享,尤其是在字符限制的环境中(如社交媒体、短信等)。
2、数据跟踪与分析:通过短链接,服务提供商可以跟踪链接的点击量、来源、时间等信息,帮助用户分析流量来源。
3、提高用户体验:短链接更美观,便于记忆,提升了用户的访问体验。
4、防止链接被截断:长链接在某些情况下可能被截断,短链接可以避免这个问题。
首先引入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.10.5</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.10.5</version>
<scope>provided</scope>
</dependency>
以下为一个简单的短链接服务代码示例:
短链接实体类
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @Description: 短链接实体类
* @ClassName: UrlModel
* @Author: ceshi
* @Date: 2025/1/17 15:34
* @Version: 1.0
*/
@Data
@Accessors(chain = true)
@Table("short_url")
public class UrlModel {
@Id(keyType = KeyType.Auto)
private Integer id;
private String shortUrl;
private String longUrl;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(onInsertValue = "now()")
private Date createTime;
private int clickCount;
}
Mapper接口
import com.mybatisflex.core.BaseMapper;
import com.xiong.examine.model.UrlModel;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description: urlMapper接口
* @ClassName: UrlMapper
* @Author: ceshi
* @Date: 2025/1/16 15:06
* @Version: 1.0
*/
@Mapper
public interface UrlMapper extends BaseMapper<UrlModel> {
}
UrlService类
import com.mybatisflex.core.service.IService;
import com.xiong.examine.model.UrlModel;
/**
* @Description: url服务类
* @ClassName: UrlService
* @Author: ceshi
* @Date: 2025/1/17 15:40
* @Version: 1.0
*/
public interface UrlService extends IService<UrlModel> {
/**
* 长链接生成短连接
* @param longUrl
* @return
*/
String generateShortUrl(String longUrl);
/**
* 短链接跳转
* @param shortUrl
* @return
*/
String redirect(String shortUrl);
}
UrlServiceImpl实现类
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.xiong.examine.mapper.UrlMapper;
import com.xiong.examine.model.UrlModel;
import com.xiong.examine.service.UrlService;
import com.xiong.examine.util.HashUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: UrlServiceImpl实现类
* @ClassName: UrlService
* @Author: ceshi
* @Date: 2025/1/17 15:40
* @Version: 1.0
*/
@Service
public class UrlServiceImpl extends ServiceImpl<UrlMapper, UrlModel> implements UrlService {
@Autowired
private UrlMapper urlMapper;
private final String BASE_URL = "http://short.url/";
private Map<String, UrlModel> urlMappingCache = new HashMap<>();
/**
* 长链接生成短链接
* @param longUrl
* @return
*/
@Override
public String generateShortUrl(String longUrl) {
// 使用Murmurhash算法 + Base62编码生成短链
String shortUrl = BASE_URL + HashUtils.hashToBase62(longUrl);
UrlModel urlModel = new UrlModel();
urlModel.setShortUrl(shortUrl);
urlModel.setLongUrl(longUrl);
urlModel.setCreateTime(new Date());
urlModel.setClickCount(0);
urlMapper.insert(urlModel);
// 将短链接url放置缓存map中
urlMappingCache.put(shortUrl, urlModel);
return shortUrl;
}
/**
* 点击短链接跳转,并统计次数
* @param shortUrl
* @return
*/
@Override
public String redirect(String shortUrl) {
// 从缓存中取数据
UrlModel urlModel = urlMappingCache.get(shortUrl);
if (urlModel != null) {
// 更新点击次数
urlModel.setClickCount(urlModel.getClickCount() + 1);
urlMapper.update(urlModel);
return urlModel.getLongUrl();
}
return null;
}
}
UrlController控制器
package com.xiong.examine.controller;
import com.xiong.examine.service.UrlService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @Description: 短链接服务
* @ClassName: UrlController
* @Author: ceshi
* @Date: 2025/1/17 15:57
* @Version: 1.0
*/
@RestController
@RequestMapping("api")
public class UrlController {
@Autowired
private UrlService urlService;
/**
* 长链接生成短链接
* @param longUrl
* @return
*/
@PostMapping("shorten")
public String shortenUrl(@RequestParam String longUrl) {
return urlService.generateShortUrl(longUrl);
}
/**
* 短链接点击跳转
* @param shortUrl
* @return
*/
@PostMapping("redirect")
public String redirect(@RequestParam String shortUrl) {
return urlService.redirect(shortUrl);
}
}
短链接生成工具类HashUtils
import cn.hutool.core.lang.hash.MurmurHash;
/**
* @Description: 短链接生成工具类
* @ClassName: HashUtils
* @Author: ceshi
* @Date: 2025/1/17 17:12
* @Version: 1.0
*/
public class HashUtils {
private static final char[] CHARS = new char[]{
'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',
'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'
};
private static final int SIZE = CHARS.length;
private static String convertDecToBase62(long num) {
// 特殊情况处理:当数字为0时,返回"0"
if (num == 0) return "0";
StringBuilder sb = new StringBuilder();
while (num > 0) {
// 计算余数
int i = (int) (num % SIZE);
// 将余数映射到 Base62 字符
sb.append(CHARS[i]);
// 更新数字
num /= SIZE;
}
// 逆序返回 Base62 编码结果
return sb.reverse().toString();
}
/**
* 使用Murmurhash算法 + Base62编码生成短链
* @param str
* @return
*/
public static String hashToBase62(String str) {
// 使用 MurmurHash 计算字符串的 32 位哈希值
int i = MurmurHash.hash32(str);
// 将负数转换为非负数
long num = i < 0 ? Integer.MAX_VALUE - (long) i : i;
// 将哈希值转换为 Base62 编码的短链接
return convertDecToBase62(num);
}
}
2035

被折叠的 条评论
为什么被折叠?



